175 changes: 175 additions & 0 deletions llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ class ARMAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseSetEndImm(OperandVector &);
OperandMatchResultTy parseShifterImm(OperandVector &);
OperandMatchResultTy parseRotImm(OperandVector &);
OperandMatchResultTy parseModImm(OperandVector &);
OperandMatchResultTy parseBitfield(OperandVector &);
OperandMatchResultTy parsePostIdxReg(OperandVector &);
OperandMatchResultTy parseAM3Offset(OperandVector &);
Expand Down Expand Up @@ -400,6 +401,7 @@ class ARMOperand : public MCParsedAsmOperand {
k_ShiftedImmediate,
k_ShifterImmediate,
k_RotateImmediate,
k_ModifiedImmediate,
k_BitfieldDescriptor,
k_Token
} Kind;
Expand Down Expand Up @@ -511,6 +513,11 @@ class ARMOperand : public MCParsedAsmOperand {
unsigned Imm;
};

struct ModImmOp {
unsigned Bits;
unsigned Rot;
};

struct BitfieldOp {
unsigned LSB;
unsigned Width;
Expand All @@ -537,6 +544,7 @@ class ARMOperand : public MCParsedAsmOperand {
struct RegShiftedRegOp RegShiftedReg;
struct RegShiftedImmOp RegShiftedImm;
struct RotImmOp RotImm;
struct ModImmOp ModImm;
struct BitfieldOp Bitfield;
};

Expand Down Expand Up @@ -612,6 +620,9 @@ class ARMOperand : public MCParsedAsmOperand {
case k_RotateImmediate:
RotImm = o.RotImm;
break;
case k_ModifiedImmediate:
ModImm = o.ModImm;
break;
case k_BitfieldDescriptor:
Bitfield = o.Bitfield;
break;
Expand Down Expand Up @@ -1091,6 +1102,22 @@ class ARMOperand : public MCParsedAsmOperand {
bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
bool isRotImm() const { return Kind == k_RotateImmediate; }
bool isModImm() const { return Kind == k_ModifiedImmediate; }
bool isModImmNot() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return ARM_AM::getSOImmVal(~Value) != -1;
}
bool isModImmNeg() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return ARM_AM::getSOImmVal(Value) == -1 &&
ARM_AM::getSOImmVal(-Value) != -1;
}
bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
bool isPostIdxReg() const {
Expand Down Expand Up @@ -1826,6 +1853,39 @@ class ARMOperand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
}

void addModImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");

// Support for fixups (MCFixup)
if (isImm())
return addImmOperands(Inst, N);

if (Inst.getOpcode() == ARM::ADDri &&
Inst.getOperand(1).getReg() == ARM::PC) {
// Instructions of the form [ADD <rd>, pc, #imm] are manually aliased
// in processInstruction() to use ADR. We must keep the immediate in
// its unencoded form in order to not clash with this aliasing.
Inst.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(ModImm.Bits,
ModImm.Rot)));
} else {
Inst.addOperand(MCOperand::CreateImm(ModImm.Bits | (ModImm.Rot << 7)));
}
}

void addModImmNotOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
uint32_t Enc = ARM_AM::getSOImmVal(~CE->getValue());
Inst.addOperand(MCOperand::CreateImm(Enc));
}

void addModImmNegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
uint32_t Enc = ARM_AM::getSOImmVal(-CE->getValue());
Inst.addOperand(MCOperand::CreateImm(Enc));
}

void addBitfieldOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// Munge the lsb/width into a bitfield mask.
Expand Down Expand Up @@ -2630,6 +2690,16 @@ class ARMOperand : public MCParsedAsmOperand {
return Op;
}

static std::unique_ptr<ARMOperand> CreateModImm(unsigned Bits, unsigned Rot,
SMLoc S, SMLoc E) {
auto Op = make_unique<ARMOperand>(k_ModifiedImmediate);
Op->ModImm.Bits = Bits;
Op->ModImm.Rot = Rot;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}

static std::unique_ptr<ARMOperand>
CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) {
auto Op = make_unique<ARMOperand>(k_BitfieldDescriptor);
Expand Down Expand Up @@ -2883,6 +2953,10 @@ void ARMOperand::print(raw_ostream &OS) const {
case k_RotateImmediate:
OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
break;
case k_ModifiedImmediate:
OS << "<mod_imm #" << ModImm.Bits << ", #"
<< ModImm.Rot << ")>";
break;
case k_BitfieldDescriptor:
OS << "<bitfield " << "lsb: " << Bitfield.LSB
<< ", width: " << Bitfield.Width << ">";
Expand Down Expand Up @@ -4338,6 +4412,106 @@ ARMAsmParser::parseRotImm(OperandVector &Operands) {
return MatchOperand_Success;
}

ARMAsmParser::OperandMatchResultTy
ARMAsmParser::parseModImm(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
MCAsmLexer &Lexer = getLexer();
int64_t Imm1, Imm2;

if ((Parser.getTok().isNot(AsmToken::Hash) &&
Parser.getTok().isNot(AsmToken::Dollar) /* looking for an immediate */ )
|| Lexer.peekTok().is(AsmToken::Colon)
|| Lexer.peekTok().is(AsmToken::LParen) /* avoid complex operands */ )
return MatchOperand_NoMatch;

SMLoc S = Parser.getTok().getLoc();

// Eat the hash (or dollar)
Parser.Lex();

SMLoc Sx1, Ex1;
Sx1 = Parser.getTok().getLoc();
const MCExpr *Imm1Exp;
if (getParser().parseExpression(Imm1Exp, Ex1)) {
Error(Sx1, "malformed expression");
return MatchOperand_ParseFail;
}

const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm1Exp);

if (CE) {
// immediate must fit within 32-bits
Imm1 = CE->getValue();
if (Imm1 < INT32_MIN || Imm1 > UINT32_MAX) {
Error(Sx1, "immediate operand must be representable with 32 bits");
return MatchOperand_ParseFail;
}

int Enc = ARM_AM::getSOImmVal(Imm1);
if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) {
// We have a match!
Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF),
(Enc & 0xF00) >> 7,
Sx1, Ex1));
return MatchOperand_Success;
}
} else {
Error(Sx1, "constant expression expected");
return MatchOperand_ParseFail;
}

if (Parser.getTok().isNot(AsmToken::Comma)) {
// Consider [mov r0, #-10], which is aliased with mvn. We cannot fail
// the parse here.
Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1));
return MatchOperand_Success;
}

// From this point onward, we expect the input to be a (#bits, #rot) pair
if (Imm1 & ~0xFF) {
Error(Sx1, "immediate operand must a number in the range [0, 255]");
return MatchOperand_ParseFail;
}

if (Lexer.peekTok().isNot(AsmToken::Hash) &&
Lexer.peekTok().isNot(AsmToken::Dollar)) {
Error(Lexer.peekTok().getLoc(), "immediate operand expected");
return MatchOperand_ParseFail;
}

// Eat the comma
Parser.Lex();

// Repeat for #rot
SMLoc Sx2, Ex2;
Sx2 = Parser.getTok().getLoc();

// Eat the hash (or dollar)
Parser.Lex();

const MCExpr *Imm2Exp;
if (getParser().parseExpression(Imm2Exp, Ex2)) {
Error(Sx2, "malformed expression");
return MatchOperand_ParseFail;
}

CE = dyn_cast<MCConstantExpr>(Imm2Exp);

if (CE) {
Imm2 = CE->getValue();
if (!(Imm2 & ~0x1E)) {
// We have a match!
Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2));
return MatchOperand_Success;
}
Error(Sx2, "immediate operand must an even number in the range [0, 30]");
return MatchOperand_ParseFail;
} else {
Error(Sx2, "constant expression expected");
return MatchOperand_ParseFail;
}
}

ARMAsmParser::OperandMatchResultTy
ARMAsmParser::parseBitfield(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
Expand Down Expand Up @@ -9787,6 +9961,7 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
if (CE->getValue() == 0)
return Match_Success;
break;
case MCK_ModImm:
case MCK_ARMSOImm:
if (Op.isImm()) {
const MCExpr *SOExpr = Op.getImm();
Expand Down
46 changes: 46 additions & 0 deletions llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,52 @@ void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
O << markup(">");
}

void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
MCOperand Op = MI->getOperand(OpNum);

// Support for fixups (MCFixup)
if (Op.isExpr())
return printOperand(MI, OpNum, O);

unsigned Bits = Op.getImm() & 0xFF;
unsigned Rot = (Op.getImm() & 0xF00) >> 7;

bool PrintUnsigned = false;
switch (MI->getOpcode()){
case ARM::MOVi:
// Movs to PC should be treated unsigned
PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);
break;
case ARM::MSRi:
// Movs to special registers should be treated unsigned
PrintUnsigned = true;
break;
}

int32_t Rotated = ARM_AM::rotr32(Bits, Rot);
if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {
// #rot has the least possible value
O << "#" << markup("<imm:");
if (PrintUnsigned)
O << static_cast<uint32_t>(Rotated);
else
O << Rotated;
O << markup(">");
return;
}

// Explicit #bits, #rot implied
O << "#"
<< markup("<imm:")
<< Bits
<< markup(">")
<< ", #"
<< markup("<imm:")
<< Rot
<< markup(">");
}

void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
O << markup("<imm:")
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class ARMInstPrinter : public MCInstPrinter {
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printRotImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printGPRPairOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);

void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
Expand Down
22 changes: 22 additions & 0 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,28 @@ class ARMMCCodeEmitter : public MCCodeEmitter {
return Binary;
}

unsigned getModImmOpValue(const MCInst &MI, unsigned Op,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &ST) const {
const MCOperand &MO = MI.getOperand(Op);

// Support for fixups (MCFixup)
if (MO.isExpr()) {
const MCExpr *Expr = MO.getExpr();
// In instruction code this value always encoded as lowest 12 bits,
// so we don't have to perform any specific adjustments.
// Due to requirements of relocatable records we have to use FK_Data_4.
// See ARMELFObjectWriter::ExplicitRelSym and
// ARMELFObjectWriter::GetRelocTypeInner for more details.
MCFixupKind Kind = MCFixupKind(FK_Data_4);
Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
return 0;
}

// Immediate is already in its encoded format
return MO.getImm();
}

/// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
SmallVectorImpl<MCFixup> &Fixups,
Expand Down
158 changes: 155 additions & 3 deletions llvm/test/MC/ARM/basic-arm-instructions.s

Large diffs are not rendered by default.

80 changes: 80 additions & 0 deletions llvm/test/MC/ARM/diagnostics.s
Original file line number Diff line number Diff line change
Expand Up @@ -621,3 +621,83 @@ foo2:
@ CHECK-ERRORS: error: destination register and base register can't be identical
@ CHECK-ERRORS: ldrsb r0, [r0], r1
@ CHECK-ERRORS: ^

@ Out of range modified immediate values
mov r5, #-256, #6
mov r6, #42, #7
mvn r5, #256, #6
mvn r6, #42, #298
cmp r5, #65535, #6
cmp r6, #42, #31
cmn r5, #-1, #6
cmn r6, #42, #32
msr APSR_nzcvq, #-128, #2
msr apsr_nzcvqg, #0, #1
adc r7, r8, #-256, #2
adc r7, r8, #128, #1
sbc r7, r8, #-256, #2
sbc r7, r8, #128, #1
add r7, r8, #-2149, #0
add r7, r8, #100, #1
sub r7, r8, #-2149, #0
sub r7, r8, #100, #1
and r7, r8, #-2149, #0
and r7, r8, #100, #1
orr r7, r8, #-2149, #0
orr r7, r8, #100, #1
eor r7, r8, #-2149, #0
eor r7, r8, #100, #1
bic r7, r8, #-2149, #0
bic r7, r8, #100, #1
rsb r7, r8, #-2149, #0
rsb r7, r8, #100, #1
adds r7, r8, #-2149, #0
adds r7, r8, #100, #1
subs r7, r8, #-2149, #0
subs r7, r8, #100, #1
rsbs r7, r8, #-2149, #0
rsbs r7, r8, #100, #1
rsc r7, r8, #-2149, #0
rsc r7, r8, #100, #1
TST r7, #-2149, #0
TST r7, #100, #1
TEQ r7, #-2149, #0
TEQ r7, #100, #1
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
@ CHECK-ERRORS: error: immediate operand must a number in the range [0, 255]
@ CHECK-ERRORS: error: immediate operand must an even number in the range [0, 30]
2 changes: 1 addition & 1 deletion llvm/test/MC/ARM/thumb-diagnostics.s
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ error: invalid operand for instruction
@ CHECK-ERRORS: error: instruction requires: thumb2
@ CHECK-ERRORS: add sp, sp, #512
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: instruction requires: arm-mode
@ CHECK-ERRORS: error: instruction requires: thumb2
@ CHECK-ERRORS: add r2, sp, #1024
@ CHECK-ERRORS: ^

Expand Down
2 changes: 1 addition & 1 deletion llvm/test/MC/Disassembler/ARM/arm-tests.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 -mcpu=cortex-a9 | FileCheck %s

# CHECK: addpl r4, pc, #318767104
# CHECK: addpl r4, pc, #76, #10
0x4c 0x45 0x8f 0x52

# CHECK: b #0
Expand Down
110 changes: 108 additions & 2 deletions llvm/test/MC/Disassembler/ARM/basic-arm-instructions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
# CHECK: adc r1, r2, #983040
# CHECK: adc r1, r2, #15728640
# CHECK: adc r1, r2, #251658240
# CHECK: adc r1, r2, #4026531840
# CHECK: adc r1, r2, #4026531855
# CHECK: adc r1, r2, #-268435456
# CHECK: adc r1, r2, #-268435441
# CHECK: adc r7, r8, #-2147483638
# CHECK: adc r7, r8, #40, #2
# CHECK: adcs r1, r2, #3840
# CHECK: adcs r7, r8, #40, #2
# CHECK: adcseq r1, r2, #3840
# CHECK: adceq r1, r2, #3840

Expand All @@ -25,8 +28,11 @@
0x0f 0x14 0xa2 0xe2
0x0f 0x12 0xa2 0xe2
0xff 0x12 0xa2 0xe2
0x2a 0x71 0xa8 0xe2
0x28 0x71 0xa8 0xe2

0x0f 0x1c 0xb2 0xe2
0x28 0x71 0xb8 0xe2
0x0f 0x1c 0xb2 0x02
0x0f 0x1c 0xa2 0x02

Expand Down Expand Up @@ -112,6 +118,8 @@
# ADD
#------------------------------------------------------------------------------
# CHECK: add r4, r5, #61440
# CHECK: add r7, r8, #-2147483638
# CHECK: add r7, r8, #40, #2
# CHECK: add r4, r5, r6
# CHECK: add r4, r5, r6, lsl #5
# CHECK: add r4, r5, r6, lsr #5
Expand All @@ -138,6 +146,8 @@
# CHECK: add r4, r4, r5, rrx

0x0f 0x4a 0x85 0xe2
0x2a 0x71 0x88 0xe2
0x28 0x71 0x88 0xe2
0x06 0x40 0x85 0xe0
0x86 0x42 0x85 0xe0
0xa6 0x42 0x85 0xe0
Expand All @@ -164,6 +174,15 @@
0x77 0x69 0x86 0xe0
0x65 0x40 0x84 0xe0

#------------------------------------------------------------------------------
# ADDS
#------------------------------------------------------------------------------
# CHECK: adds r7, r8, #-2147483638
# CHECK: adds r7, r8, #40, #2

0x2a 0x71 0x98 0xe2
0x28 0x71 0x98 0xe2

#------------------------------------------------------------------------------
# ADR
#------------------------------------------------------------------------------
Expand All @@ -183,6 +202,8 @@
# AND
#------------------------------------------------------------------------------
# CHECK: and r10, r1, #15
# CHECK: and r7, r8, #-2147483638
# CHECK: and r7, r8, #40, #2
# CHECK: and r10, r1, r6
# CHECK: and r10, r1, r6, lsl #10
# CHECK: and r10, r1, r6, lsr #10
Expand All @@ -209,6 +230,8 @@
# CHECK: and r10, r10, r1, rrx

0x0f 0xa0 0x01 0xe2
0x2a 0x71 0x08 0xe2
0x28 0x71 0x08 0xe2
0x06 0xa0 0x01 0xe0
0x06 0xa5 0x01 0xe0
0x26 0xa5 0x01 0xe0
Expand Down Expand Up @@ -262,6 +285,8 @@
# BIC
#------------------------------------------------------------------------------
# CHECK: bic r10, r1, #15
# CHECK: bic r7, r8, #-2147483638
# CHECK: bic r7, r8, #40, #2
# CHECK: bic r10, r1, r6
# CHECK: bic r10, r1, r6, lsl #10
# CHECK: bic r10, r1, r6, lsr #10
Expand All @@ -288,6 +313,8 @@
# CHECK: bic r10, r10, r1, rrx

0x0f 0xa0 0xc1 0xe3
0x2a 0x71 0xc8 0xe3
0x28 0x71 0xc8 0xe3
0x06 0xa0 0xc1 0xe1
0x06 0xa5 0xc1 0xe1
0x26 0xa5 0xc1 0xe1
Expand Down Expand Up @@ -393,6 +420,8 @@
# CMN
#------------------------------------------------------------------------------
# CHECK: cmn r1, #15
# CHECK: cmn r7, #40, #2
# CHECK: cmn r7, #-2147483638
# CHECK: cmn r1, r6
# CHECK: cmn r1, r6, lsl #10
# CHECK: cmn r1, r6, lsr #10
Expand All @@ -406,6 +435,8 @@
# CHECK: cmn r1, r6, rrx

0x0f 0x00 0x71 0xe3
0x28 0x01 0x77 0xe3
0x2a 0x01 0x77 0xe3
0x06 0x00 0x71 0xe1
0x06 0x05 0x71 0xe1
0x26 0x05 0x71 0xe1
Expand All @@ -422,6 +453,8 @@
# CMP
#------------------------------------------------------------------------------
# CHECK: cmp r1, #15
# CHECK: cmp r7, #40, #2
# CHECK: cmp r7, #-2147483638
# CHECK: cmp r1, r6
# CHECK: cmp r1, r6, lsl #10
# CHECK: cmp r1, r6, lsr #10
Expand All @@ -435,6 +468,8 @@
# CHECK: cmp r1, r6, rrx

0x0f 0x00 0x51 0xe3
0x28 0x01 0x57 0xe3
0x2a 0x01 0x57 0xe3
0x06 0x00 0x51 0xe1
0x06 0x05 0x51 0xe1
0x26 0x05 0x51 0xe1
Expand Down Expand Up @@ -556,6 +591,8 @@
# EOR
#------------------------------------------------------------------------------
# CHECK: eor r4, r5, #61440
# CHECK: eor r7, r8, #-2147483638
# CHECK: eor r7, r8, #40, #2
# CHECK: eor r4, r5, r6
# CHECK: eor r4, r5, r6, lsl #5
# CHECK: eor r4, r5, r6, lsr #5
Expand All @@ -582,6 +619,8 @@
# CHECK: eor r4, r4, r5, rrx

0x0f 0x4a 0x25 0xe2
0x2a 0x71 0x28 0xe2
0x28 0x71 0x28 0xe2
0x06 0x40 0x25 0xe0
0x86 0x42 0x25 0xe0
0xa6 0x42 0x25 0xe0
Expand Down Expand Up @@ -714,21 +753,31 @@
# CHECK: mov r4, #4080
# CHECK: mov r5, #16711680
# CHECK: mov sp, #35
# CHECK: mov r9, #240, #30
# CHECK: mov r7, #-2147483638
# CHECK: mov pc, #2147483658
# CHECK: movw r6, #65535
# CHECK: movw r9, #65535
# CHECK: movw sp, #1193
# CHECK: movs r3, #7
# CHECK: movs r11, #99
# CHECK: movs r11, #240, #30
# CHECK: moveq r4, #4080
# CHECK: movseq r5, #16711680

0x07 0x30 0xa0 0xe3
0xff 0x4e 0xa0 0xe3
0xff 0x58 0xa0 0xe3
0x23 0xd0 0xa0 0xe3
0xf0 0x9f 0xa0 0xe3
0x2a 0x71 0xa0 0xe3
0x2a 0xf1 0xa0 0xe3
0xff 0x6f 0x0f 0xe3
0xff 0x9f 0x0f 0xe3
0xa9 0xd4 0x00 0xe3
0x07 0x30 0xb0 0xe3
0x63 0xb0 0xb0 0xe3
0xf0 0xbf 0xb0 0xe3
0xff 0x4e 0xa0 0x03
0xff 0x58 0xb0 0x03

Expand Down Expand Up @@ -810,6 +859,8 @@
# CHECK: msr SPSR_fc, #5
# CHECK: msr SPSR_fsxc, #5
# CHECK: msr CPSR_fsxc, #5
# CHECK: msr APSR_nzcvq, #2147483658
# CHECK: msr SPSR_fsxc, #40, #2

0x05 0xf0 0x29 0xe3
0x05 0xf0 0x24 0xe3
Expand All @@ -825,6 +876,8 @@
0x05 0xf0 0x69 0xe3
0x05 0xf0 0x6f 0xe3
0x05 0xf0 0x2f 0xe3
0x2a 0xf1 0x28 0xe3
0x28 0xf1 0x6f 0xe3

# CHECK: msr CPSR_fc, r0
# CHECK: msr APSR_g, r0
Expand Down Expand Up @@ -877,14 +930,22 @@
# CHECK: mvn r3, #7
# CHECK: mvn r4, #4080
# CHECK: mvn r5, #16711680
# CHECK: mvn r7, #40, #2
# CHECK: mvn r7, #-2147483638
# CHECK: mvns r3, #7
# CHECK: mvns r11, #240, #30
# CHECK: mvns r11, #-2147483638
# CHECK: mvneq r4, #4080
# CHECK: mvnseq r5, #16711680

0x07 0x30 0xe0 0xe3
0xff 0x4e 0xe0 0xe3
0xff 0x58 0xe0 0xe3
0x28 0x71 0xe0 0xe3
0x2a 0x71 0xe0 0xe3
0x07 0x30 0xf0 0xe3
0xf0 0xbf 0xf0 0xe3
0x2a 0xb1 0xf0 0xe3
0xff 0x4e 0xe0 0x03
0xff 0x58 0xf0 0x03

Expand Down Expand Up @@ -940,6 +1001,8 @@
# ORR
#------------------------------------------------------------------------------
# CHECK: orr r4, r5, #61440
# CHECK: orr r7, r8, #-2147483638
# CHECK: orr r7, r8, #40, #2
# CHECK: orr r4, r5, r6
# CHECK: orr r4, r5, r6, lsl #5
# CHECK: orr r4, r5, r6, lsr #5
Expand All @@ -966,6 +1029,8 @@
# CHECK: orr r4, r4, r5, rrx

0x0f 0x4a 0x85 0xe3
0x2a 0x71 0x88 0xe3
0x28 0x71 0x88 0xe3
0x06 0x40 0x85 0xe1
0x86 0x42 0x85 0xe1
0xa6 0x42 0x85 0xe1
Expand Down Expand Up @@ -1204,6 +1269,8 @@
# RSB
#------------------------------------------------------------------------------
# CHECK: rsb r4, r5, #61440
# CHECK: rsb r7, r8, #-2147483638
# CHECK: rsb r7, r8, #40, #2
# CHECK: rsb r4, r5, r6
# CHECK: rsb r4, r5, r6, lsl #5
# CHECK: rsblo r4, r5, r6, lsr #5
Expand All @@ -1230,6 +1297,8 @@
# CHECK: rsb r4, r4, r5, rrx

0x0f 0x4a 0x65 0xe2
0x2a 0x71 0x68 0xe2
0x28 0x71 0x68 0xe2
0x06 0x40 0x65 0xe0
0x86 0x42 0x65 0xe0
0xa6 0x42 0x65 0x30
Expand All @@ -1255,10 +1324,21 @@
0x77 0x69 0x66 0xe0
0x65 0x40 0x64 0xe0

#------------------------------------------------------------------------------
# RSBS
#------------------------------------------------------------------------------
# CHECK: rsbs r7, r8, #-2147483638
# CHECK: rsbs r7, r8, #40, #2

0x2a 0x71 0x78 0xe2
0x28 0x71 0x78 0xe2

#------------------------------------------------------------------------------
# RSC
#------------------------------------------------------------------------------
# CHECK: rsc r4, r5, #61440
# CHECK: rsc r7, r8, #-2147483638
# CHECK: rsc r7, r8, #40, #2
# CHECK: rsc r4, r5, r6
# CHECK: rsc r4, r5, r6, lsl #5
# CHECK: rsclo r4, r5, r6, lsr #5
Expand All @@ -1283,6 +1363,8 @@
# CHECK: rsc r6, r6, r7, ror r9

0x0f 0x4a 0xe5 0xe2
0x2a 0x71 0xe8 0xe2
0x28 0x71 0xe8 0xe2
0x06 0x40 0xe5 0xe0
0x86 0x42 0xe5 0xe0
0xa6 0x42 0xe5 0x30
Expand Down Expand Up @@ -1357,6 +1439,8 @@
# SBC
#------------------------------------------------------------------------------
# CHECK: sbc r4, r5, #61440
# CHECK: sbc r7, r8, #-2147483638
# CHECK: sbc r7, r8, #40, #2
# CHECK: sbc r4, r5, r6
# CHECK: sbc r4, r5, r6, lsl #5
# CHECK: sbc r4, r5, r6, lsr #5
Expand All @@ -1381,6 +1465,8 @@
# CHECK: sbc r6, r6, r7, ror r9

0x0f 0x4a 0xc5 0xe2
0x2a 0x71 0xc8 0xe2
0x28 0x71 0xc8 0xe2
0x06 0x40 0xc5 0xe0
0x86 0x42 0xc5 0xe0
0xa6 0x42 0xc5 0xe0
Expand Down Expand Up @@ -1868,6 +1954,8 @@
# SUB
#------------------------------------------------------------------------------
# CHECK: sub r4, r5, #61440
# CHECK: sub r7, r8, #-2147483638
# CHECK: sub r7, r8, #40, #2
# CHECK: sub r4, r5, r6
# CHECK: sub r4, r5, r6, lsl #5
# CHECK: sub r4, r5, r6, lsr #5
Expand All @@ -1892,6 +1980,8 @@
# CHECK: sub r6, r6, r7, ror r9

0x0f 0x4a 0x45 0xe2
0x2a 0x71 0x48 0xe2
0x28 0x71 0x48 0xe2
0x06 0x40 0x45 0xe0
0x86 0x42 0x45 0xe0
0xa6 0x42 0x45 0xe0
Expand All @@ -1916,6 +2006,14 @@
0x57 0x69 0x46 0xe0
0x77 0x69 0x46 0xe0

#------------------------------------------------------------------------------
# SUBS
#------------------------------------------------------------------------------
# CHECK: subs r7, r8, #-2147483638
# CHECK: subs r7, r8, #40, #2

0x2a 0x71 0x58 0xe2
0x28 0x71 0x58 0xe2

#------------------------------------------------------------------------------
# SVC
Expand Down Expand Up @@ -2044,6 +2142,8 @@
# TEQ
#------------------------------------------------------------------------------
# CHECK: teq r5, #61440
# CHECK: teq r7, #-2147483638
# CHECK: teq r7, #40, #2
# CHECK: teq r4, r5
# CHECK: teq r4, r5, lsl #5
# CHECK: teq r4, r5, lsr #5
Expand All @@ -2056,6 +2156,8 @@
# CHECK: teq r6, r7, ror r9

0x0f 0x0a 0x35 0xe3
0x2a 0x01 0x37 0xe3
0x28 0x01 0x37 0xe3
0x05 0x00 0x34 0xe1
0x85 0x02 0x34 0xe1
0xa5 0x02 0x34 0xe1
Expand All @@ -2072,6 +2174,8 @@
# TST
#------------------------------------------------------------------------------
# CHECK: tst r5, #61440
# CHECK: tst r7, #-2147483638
# CHECK: tst r7, #40, #2
# CHECK: tst r4, r5
# CHECK: tst r4, r5, lsl #5
# CHECK: tst r4, r5, lsr #5
Expand All @@ -2084,6 +2188,8 @@
# CHECK: tst r6, r7, ror r9

0x0f 0x0a 0x15 0xe3
0x2a 0x01 0x17 0xe3
0x28 0x01 0x17 0xe3
0x05 0x00 0x14 0xe1
0x85 0x02 0x14 0xe1
0xa5 0x02 0x14 0xe1
Expand Down