This corrects the implementation of Thumb ADR instruction. There are three issues:

1. it should accept only 4-byte aligned addresses
2. the maximum offset should be 1020
3. it should be encoded with the offset scaled by two bits


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185528 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mihai Popa 2013-07-03 09:21:44 +00:00
parent a10c01a6c6
commit b81b477cd4
9 changed files with 62 additions and 14 deletions

View File

@ -458,7 +458,7 @@ def AdrLabelAsmOperand : AsmOperandClass { let Name = "AdrLabel"; }
def adrlabel : Operand<i32> {
let EncoderMethod = "getAdrLabelOpValue";
let ParserMatchClass = AdrLabelAsmOperand;
let PrintMethod = "printAdrLabelOperand";
let PrintMethod = "printAdrLabelOperand<0>";
}
def neon_vcvt_imm32 : Operand<i32> {

View File

@ -69,11 +69,6 @@ def thumb_immshifted_shamt : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(V, MVT::i32);
}]>;
// ADR instruction labels.
def t_adrlabel : Operand<i32> {
let EncoderMethod = "getThumbAdrLabelOpValue";
}
// Scaled 4 immediate.
def t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; }
def t_imm0_1020s4 : Operand<i32> {
@ -97,12 +92,27 @@ def t_imm0_508s4_neg : Operand<i32> {
// Define Thumb specific addressing modes.
// unsigned 8-bit, 2-scaled memory offset
class OperandUnsignedOffset_b8s2 : AsmOperandClass {
let Name = "UnsignedOffset_b8s2";
let PredicateMethod = "isUnsignedOffset<8, 2>";
}
def UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2;
let OperandType = "OPERAND_PCREL" in {
def t_brtarget : Operand<OtherVT> {
let EncoderMethod = "getThumbBRTargetOpValue";
let DecoderMethod = "DecodeThumbBROperand";
}
// ADR instruction labels.
def t_adrlabel : Operand<i32> {
let EncoderMethod = "getThumbAdrLabelOpValue";
let PrintMethod = "printAdrLabelOperand<2>";
let ParserMatchClass = UnsignedOffset_b8s2;
}
def t_bcctarget : Operand<i32> {
let EncoderMethod = "getThumbBCCTargetOpValue";
let DecoderMethod = "DecodeThumbBCCTargetOperand";
@ -505,6 +515,7 @@ let isBranch = 1, isTerminator = 1 in
let Inst{7-0} = target;
}
// Tail calls
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// IOS versions.

View File

@ -173,7 +173,7 @@ def t2ldr_pcrel_imm12 : Operand<i32> {
// ADR instruction labels.
def t2adrlabel : Operand<i32> {
let EncoderMethod = "getT2AdrLabelOpValue";
let PrintMethod = "printAdrLabelOperand";
let PrintMethod = "printAdrLabelOperand<0>";
}
// t2addrmode_posimm8 := reg + imm8

View File

@ -629,6 +629,20 @@ public:
bool isITMask() const { return Kind == k_ITCondMask; }
bool isITCondCode() const { return Kind == k_CondCode; }
bool isImm() const { return Kind == k_Immediate; }
// checks whether this operand is an unsigned offset which fits is a field
// of specified width and scaled by a specific number of bits
template<unsigned width, unsigned scale>
bool isUnsignedOffset() const {
if (!isImm()) return false;
if (dyn_cast<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);
return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max);
}
return false;
}
bool isFPImm() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
@ -1707,6 +1721,17 @@ public:
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
}
void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const {
if(const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2));
return;
}
const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
assert(SR && "Unknown value type!");
Inst.addOperand(MCOperand::CreateExpr(SR));
}
void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The operand is actually a so_imm, but we have its bitwise

View File

@ -900,6 +900,7 @@ void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
}
template<unsigned scale>
void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
@ -909,7 +910,7 @@ void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
return;
}
int32_t OffImm = (int32_t)MO.getImm();
int32_t OffImm = (int32_t)MO.getImm() << scale;
O << markup("<imm:");
if (OffImm == INT32_MIN)

View File

@ -76,6 +76,7 @@ public:
void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
template <unsigned scale>
void printAdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbSRImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);

View File

@ -85,11 +85,15 @@ _func:
@ ADR
@------------------------------------------------------------------------------
adr r2, _baz
adr r2, #3
adr r5, #0
adr r2, #4
adr r3, #1020
@ CHECK: adr r2, _baz @ encoding: [A,0xa2]
@ fixup A - offset: 0, value: _baz, kind: fixup_thumb_adr_pcrel_10
@ CHECK: adr r2, #3 @ encoding: [0x03,0xa2]
@ CHECK: adr r5, #0 @ encoding: [0x00,0xa5]
@ CHECK: adr r2, #4 @ encoding: [0x01,0xa2]
@ CHECK: adr r3, #1020 @ encoding: [0xff,0xa3]
@------------------------------------------------------------------------------
@ ASR (immediate)

View File

@ -134,10 +134,12 @@ _func:
@------------------------------------------------------------------------------
subw r11, pc, #3270
adr.w r2, #3
adr.w r11, #-826
adr.w r1, #-0x0
@ CHECK: subw r11, pc, #3270 @ encoding: [0xaf,0xf6,0xc6,0x4b]
@ CHECK: adr.w r2, #3 @ encoding: [0x0f,0xf2,0x03,0x02]
@ CHECK: adr.w r11, #-826 @ encoding: [0xaf,0xf2,0x3a,0x3b]
@ CHECK: adr.w r1, #-0 @ encoding: [0xaf,0xf2,0x00,0x01]

View File

@ -54,8 +54,12 @@
#------------------------------------------------------------------------------
# ADR
#------------------------------------------------------------------------------
# CHECK: adr r2, #3
# CHECK: adr r5, #0
# CHECK: adr r2, #12
# CHECK: adr r3, #1020
0x00 0xa5
0x03 0xa2
0xff 0xa3
#------------------------------------------------------------------------------
# ASR (immediate)