// Asm Match Converter Methods
void cvtThumbMultiply(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &);
+ void cvtThumbBranches(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+
bool validateInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
bool processInstruction(MCInst &Inst,
template<unsigned width, unsigned scale>
bool isUnsignedOffset() const {
if (!isImm()) return false;
- if (dyn_cast<MCSymbolRefExpr>(Imm.Val)) return true;
+ if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
int64_t Val = CE->getValue();
int64_t Align = 1LL << scale;
}
return false;
}
+ // checks whether this operand is an signed offset which fits is a field
+ // of specified width and scaled by a specific number of bits
+ template<unsigned width, unsigned scale>
+ bool isSignedOffset() const {
+ if (!isImm()) return false;
+ if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
+ if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
+ int64_t Val = CE->getValue();
+ int64_t Align = 1LL << scale;
+ int64_t Max = Align * ((1LL << (width-1)) - 1);
+ int64_t Min = -Align * (1LL << (width-1));
+ return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max);
+ }
+ return false;
+ }
+
// checks whether this operand is a memory operand computed as an offset
// applied to PC. the offset may have 8 bits of magnitude and is represented
// with two bits of shift. textually it may be either [pc, #imm], #imm or
((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
}
+void ARMAsmParser::
+cvtThumbBranches(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ int CondOp = -1, ImmOp = -1;
+ switch(Inst.getOpcode()) {
+ case ARM::tB:
+ case ARM::tBcc: CondOp = 1; ImmOp = 2; break;
+
+ case ARM::t2B:
+ case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break;
+
+ default: llvm_unreachable("Unexpected instruction in cvtThumbBranches");
+ }
+ // first decide whether or not the branch should be conditional
+ // by looking at it's location relative to an IT block
+ if(inITBlock()) {
+ // inside an IT block we cannot have any conditional branches. any
+ // such instructions needs to be converted to unconditional form
+ switch(Inst.getOpcode()) {
+ case ARM::tBcc: Inst.setOpcode(ARM::tB); break;
+ case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break;
+ }
+ } else {
+ // outside IT blocks we can only have unconditional branches with AL
+ // condition code or conditional branches with non-AL condition code
+ unsigned Cond = static_cast<ARMOperand*>(Operands[CondOp])->getCondCode();
+ switch(Inst.getOpcode()) {
+ case ARM::tB:
+ case ARM::tBcc:
+ Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc);
+ break;
+ case ARM::t2B:
+ case ARM::t2Bcc:
+ Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc);
+ break;
+ }
+ }
+
+ // now decide on encoding size based on branch target range
+ switch(Inst.getOpcode()) {
+ // classify tB as either t2B or t1B based on range of immediate operand
+ case ARM::tB: {
+ ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]);
+ if(!op->isSignedOffset<11, 1>() && isThumbTwo())
+ Inst.setOpcode(ARM::t2B);
+ break;
+ }
+ // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand
+ case ARM::tBcc: {
+ ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]);
+ if(!op->isSignedOffset<8, 1>() && isThumbTwo())
+ Inst.setOpcode(ARM::t2Bcc);
+ break;
+ }
+ }
+ ((ARMOperand*)Operands[ImmOp])->addImmOperands(Inst, 1);
+ ((ARMOperand*)Operands[CondOp])->addCondCodeOperands(Inst, 2);
+}
+
/// Parse an ARM memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
bool ARMAsmParser::
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
SMLoc Loc = Operands[0]->getStartLoc();
+
// Check the IT block state first.
// NOTE: BKPT instruction has the interesting property of being
// allowed in IT blocks, but not being predicable. It just always
// Check for non-'al' condition codes outside of the IT block.
} else if (isThumbTwo() && MCID.isPredicable() &&
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
- ARMCC::AL && Inst.getOpcode() != ARM::tB &&
- Inst.getOpcode() != ARM::t2B)
+ ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
+ Inst.getOpcode() != ARM::t2Bcc)
return Error(Loc, "predicated instructions must be in IT block");
switch (Inst.getOpcode()) {
}
break;
}
+ // final range checking for Thumb unconditional branch instructions
+ case ARM::tB:
+ if(!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<11, 1>())
+ return Error(Operands[2]->getStartLoc(), "Branch target out of range");
+ break;
+ case ARM::t2B: {
+ int op = (Operands[2]->isImm()) ? 2 : 3;
+ if(!(static_cast<ARMOperand*>(Operands[op]))->isSignedOffset<24, 1>())
+ return Error(Operands[op]->getStartLoc(), "Branch target out of range");
+ break;
+ }
+ // final range checking for Thumb conditional branch instructions
+ case ARM::tBcc:
+ if(!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<8, 1>())
+ return Error(Operands[2]->getStartLoc(), "Branch target out of range");
+ break;
+ case ARM::t2Bcc: {
+ int op = (Operands[2]->isImm()) ? 2 : 3;
+ if(!(static_cast<ARMOperand*>(Operands[op]))->isSignedOffset<20, 1>())
+ return Error(Operands[op]->getStartLoc(), "Branch target out of range");
+ break;
+ }
}
StringRef DepInfo;
--- /dev/null
+@ RUN: llvm-mc -triple=thumbv7-apple-darwin -mcpu=cortex-a8 -show-encoding < %s | FileCheck %s
+
+@------------------------------------------------------------------------------
+@ unconditional branches accept narrow suffix and encode to short encodings
+@------------------------------------------------------------------------------
+
+ b.n #-2048
+ b.n #2046
+
+@ CHECK: b #-2048 @ encoding: [0x00,0xe4]
+@ CHECK: b #2046 @ encoding: [0xff,0xe3]
+
+@------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+@------------------------------------------------------------------------------
+
+ b.w #-2048
+ b.w #2046
+ b.w #-1677216
+ b.w #1677214
+
+@ CHECK: b.w #-2048 @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: b.w #2046 @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: b.w #-1677216 @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w #1677214 @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+@------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+@------------------------------------------------------------------------------
+
+ b #-2048
+ b #2046
+ b #-2050
+ b #2048
+ b #-1677216
+ b #1677214
+
+@ CHECK: b #-2048 @ encoding: [0x00,0xe4]
+@ CHECK: b #2046 @ encoding: [0xff,0xe3]
+@ CHECK: b.w #-2050 @ encoding: [0xff,0xf7,0xff,0xbb]
+@ CHECK: b.w #2048 @ encoding: [0x00,0xf0,0x00,0xbc]
+@ CHECK: b.w #-1677216 @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w #1677214 @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+@------------------------------------------------------------------------------
+@ unconditional branches with width narrow suffix in IT block
+@------------------------------------------------------------------------------
+
+ it eq
+ beq.n #-2048
+ it ne
+ bne.n #-2046
+
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: beq #-2048 @ encoding: [0x00,0xe4]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: bne #-2046 @ encoding: [0x01,0xe4]
+
+@------------------------------------------------------------------------------
+@ unconditional branches with wide suffix in IT block
+@------------------------------------------------------------------------------
+
+ it gt
+ bgt.w #-2048
+ it le
+ ble.w #2046
+ it ge
+ bge.w #-1677216
+ it lt
+ blt.w #1677214
+
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: bgt.w #-2048 @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: it le @ encoding: [0xd8,0xbf]
+@ CHECK: ble.w #2046 @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: it ge @ encoding: [0xa8,0xbf]
+@ CHECK: bge.w #-1677216 @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: it lt @ encoding: [0xb8,0xbf]
+@ CHECK: blt.w #1677214 @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+@------------------------------------------------------------------------------
+@ conditional branches accept narrow suffix and encode to short encodings
+@------------------------------------------------------------------------------
+
+ beq.n #-256
+ bne.n #254
+
+@ CHECK: beq #-256 @ encoding: [0x80,0xd0]
+@ CHECK: bne #254 @ encoding: [0x7f,0xd1]
+
+@------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+@------------------------------------------------------------------------------
+
+ bmi.w #-256
+ bne.w #254
+ blt.w #-1048576
+ bge.w #1048574
+
+@ CHECK: bmi.w #-256 @ encoding: [0x3f,0xf5,0x80,0xaf]
+@ CHECK: bne.w #254 @ encoding: [0x40,0xf0,0x7f,0x80]
+@ CHECK: blt.w #-1048576 @ encoding: [0xc0,0xf6,0x00,0x80]
+@ CHECK: bge.w #1048574 @ encoding: [0xbf,0xf2,0xff,0xaf]
+
+@------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+@------------------------------------------------------------------------------
+
+ bne #-256
+ bgt #254
+ bne #-258
+ bgt #256
+ bne #-1048576
+ bgt #1048574
+
+@ CHECK: bne #-256 @ encoding: [0x80,0xd1]
+@ CHECK: bgt #254 @ encoding: [0x7f,0xdc]
+@ CHECK: bne.w #-258 @ encoding: [0x7f,0xf4,0x7f,0xaf]
+@ CHECK: bgt.w #256 @ encoding: [0x00,0xf3,0x80,0x80]
+@ CHECK: bne.w #-1048576 @ encoding: [0x40,0xf4,0x00,0x80]
+@ CHECK: bgt.w #1048574 @ encoding: [0x3f,0xf3,0xff,0xaf]
+
+@------------------------------------------------------------------------------
+@ same branch insturction encoding to conditional or unconditional depending
+@ on whether it is in an IT block or not
+@------------------------------------------------------------------------------
+
+ it eq
+ addeq r0, r1
+ bne #128
+
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: addeq r0, r1 @ encoding: [0x08,0x44]
+@ CHECK: bne #128 @ encoding: [0x40,0xd1]
+
+ ite eq
+ addeq r0, r1
+ bne #128
+
+@ CHECK: ite eq @ encoding: [0x0c,0xbf]
+@ CHECK: addeq r0, r1 @ encoding: [0x08,0x44]
+@ CHECK: bne #128 @ encoding: [0x40,0xe0]
+
+@ RUN: llvm-mc -triple=thumbv7-apple-darwin -mcpu=cortex-a8 -show-encoding < %s | FileCheck %s
+
+@------------------------------------------------------------------------------
+@ unconditional branches accept narrow suffix and encode to short encodings
+@------------------------------------------------------------------------------
+
+ b.n #-2048
+ b.n #2046
+
+@ CHECK: b #-2048 @ encoding: [0x00,0xe4]
+@ CHECK: b #2046 @ encoding: [0xff,0xe3]
+
+@------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+@------------------------------------------------------------------------------
+
+ b.w #-2048
+ b.w #2046
+ b.w #-1677216
+ b.w #1677214
+
+@ CHECK: b.w #-2048 @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: b.w #2046 @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: b.w #-1677216 @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w #1677214 @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+@------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+@------------------------------------------------------------------------------
+
+ b #-2048
+ b #2046
+ b #-2050
+ b #2048
+ b #-1677216
+ b #1677214
+
+@ CHECK: b #-2048 @ encoding: [0x00,0xe4]
+@ CHECK: b #2046 @ encoding: [0xff,0xe3]
+@ CHECK: b.w #-2050 @ encoding: [0xff,0xf7,0xff,0xbb]
+@ CHECK: b.w #2048 @ encoding: [0x00,0xf0,0x00,0xbc]
+@ CHECK: b.w #-1677216 @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w #1677214 @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+@------------------------------------------------------------------------------
+@ unconditional branches with width narrow suffix in IT block
+@------------------------------------------------------------------------------
+
+ it eq
+ beq.n #-2048
+ it ne
+ bne.n #-2046
+
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: beq #-2048 @ encoding: [0x00,0xe4]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: bne #-2046 @ encoding: [0x01,0xe4]
+
+@------------------------------------------------------------------------------
+@ unconditional branches with wide suffix in IT block
+@------------------------------------------------------------------------------
+
+ it gt
+ bgt.w #-2048
+ it le
+ ble.w #2046
+ it ge
+ bge.w #-1677216
+ it lt
+ blt.w #1677214
+
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: bgt.w #-2048 @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: it le @ encoding: [0xd8,0xbf]
+@ CHECK: ble.w #2046 @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: it ge @ encoding: [0xa8,0xbf]
+@ CHECK: bge.w #-1677216 @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: it lt @ encoding: [0xb8,0xbf]
+@ CHECK: blt.w #1677214 @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+@------------------------------------------------------------------------------
+@ conditional branches accept narrow suffix and encode to short encodings
+@------------------------------------------------------------------------------
+
+ beq.n #-256
+ bne.n #254
+
+@ CHECK: beq #-256 @ encoding: [0x80,0xd0]
+@ CHECK: bne #254 @ encoding: [0x7f,0xd1]
+
+@------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+@------------------------------------------------------------------------------
+
+ bmi.w #-256
+ bne.w #254
+ blt.w #-1048576
+ bge.w #1048574
+
+@ CHECK: bmi.w #-256 @ encoding: [0x3f,0xf5,0x80,0xaf]
+@ CHECK: bne.w #254 @ encoding: [0x40,0xf0,0x7f,0x80]
+@ CHECK: blt.w #-1048576 @ encoding: [0xc0,0xf6,0x00,0x80]
+@ CHECK: bge.w #1048574 @ encoding: [0xbf,0xf2,0xff,0xaf]
+
+@------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+@------------------------------------------------------------------------------
+
+ bne #-256
+ bgt #254
+ bne #-258
+ bgt #256
+ bne #-1048576
+ bgt #1048574
+
+@ CHECK: bne #-256 @ encoding: [0x80,0xd1]
+@ CHECK: bgt #254 @ encoding: [0x7f,0xdc]
+@ CHECK: bne.w #-258 @ encoding: [0x7f,0xf4,0x7f,0xaf]
+@ CHECK: bgt.w #256 @ encoding: [0x00,0xf3,0x80,0x80]
+@ CHECK: bne.w #-1048576 @ encoding: [0x40,0xf4,0x00,0x80]
+@ CHECK: bgt.w #1048574 @ encoding: [0x3f,0xf3,0xff,0xaf]
+
+@------------------------------------------------------------------------------
+@ same branch insturction encoding to conditional or unconditional depending
+@ on whether it is in an IT block or not
+@------------------------------------------------------------------------------
+
+ it eq
+ addeq r0, r1
+ bne #128
+
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: addeq r0, r1 @ encoding: [0x08,0x44]
+@ CHECK: bne #128 @ encoding: [0x40,0xd1]
+
+ ite eq
+ addeq r0, r1
+ bne #128
+
+@ CHECK: ite eq @ encoding: [0x0c,0xbf]
+@ CHECK: addeq r0, r1 @ encoding: [0x08,0x44]
+@ CHECK: bne #128 @ encoding: [0x40,0xe0]
+