mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
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:
parent
a10c01a6c6
commit
b81b477cd4
@ -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> {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -134,12 +134,14 @@ _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 r11, #-826 @ encoding: [0xaf,0xf2,0x3a,0x3b]
|
||||
@ CHECK: adr.w r1, #-0 @ encoding: [0xaf,0xf2,0x00,0x01]
|
||||
@ 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]
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ AND (immediate)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user