mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-15 07:34:33 +00:00
ARM: fix thumb literal loads decoding
This fixes two previous issues: - Negative offsets were not correctly disassembled - The decoded opcodes were not the right one git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184180 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cea0032f73
commit
ce046b98ed
@ -959,6 +959,8 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
|
||||
let Inst{19-16} = addr{16-13}; // Rn
|
||||
let Inst{15-12} = Rt;
|
||||
let Inst{11-0} = addr{11-0}; // imm
|
||||
|
||||
let DecoderMethod = "DecodeT2LoadImm12";
|
||||
}
|
||||
def i8 : T2Ii8 <(outs target:$Rt), (ins t2addrmode_negimm8:$addr), iii,
|
||||
opc, "\t$Rt, $addr",
|
||||
@ -979,6 +981,8 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
|
||||
let Inst{9} = addr{8}; // U
|
||||
let Inst{8} = 0; // The W bit.
|
||||
let Inst{7-0} = addr{7-0}; // imm
|
||||
|
||||
let DecoderMethod = "DecodeT2LoadImm8";
|
||||
}
|
||||
def s : T2Iso <(outs target:$Rt), (ins t2addrmode_so_reg:$addr), iis,
|
||||
opc, ".w\t$Rt, $addr",
|
||||
@ -1019,6 +1023,8 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
|
||||
bits<12> addr;
|
||||
let Inst{15-12} = Rt{3-0};
|
||||
let Inst{11-0} = addr{11-0};
|
||||
|
||||
let DecoderMethod = "DecodeT2LoadLabel";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1228,15 +1234,15 @@ defm t2LDR : T2I_ld<0, 0b10, "ldr", IIC_iLoad_i, IIC_iLoad_si, GPR,
|
||||
|
||||
// Loads with zero extension
|
||||
defm t2LDRH : T2I_ld<0, 0b01, "ldrh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
|
||||
rGPR, UnOpFrag<(zextloadi16 node:$Src)>>;
|
||||
GPR, UnOpFrag<(zextloadi16 node:$Src)>>;
|
||||
defm t2LDRB : T2I_ld<0, 0b00, "ldrb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
|
||||
rGPR, UnOpFrag<(zextloadi8 node:$Src)>>;
|
||||
GPR, UnOpFrag<(zextloadi8 node:$Src)>>;
|
||||
|
||||
// Loads with sign extension
|
||||
defm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
|
||||
rGPR, UnOpFrag<(sextloadi16 node:$Src)>>;
|
||||
GPR, UnOpFrag<(sextloadi16 node:$Src)>>;
|
||||
defm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
|
||||
rGPR, UnOpFrag<(sextloadi8 node:$Src)>>;
|
||||
GPR, UnOpFrag<(sextloadi8 node:$Src)>>;
|
||||
|
||||
let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
|
||||
// Load doubleword
|
||||
@ -1373,6 +1379,8 @@ class T2IldT<bit signed, bits<2> type, string opc, InstrItinClass ii>
|
||||
let Inst{11} = 1;
|
||||
let Inst{10-8} = 0b110; // PUW.
|
||||
let Inst{7-0} = addr{7-0};
|
||||
|
||||
let DecoderMethod = "DecodeT2LoadT";
|
||||
}
|
||||
|
||||
def t2LDRT : T2IldT<0, 0b10, "ldrt", IIC_iLoad_i>;
|
||||
|
@ -347,6 +347,14 @@ static DecodeStatus DecodeT2AddrModeSOReg(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder);
|
||||
static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder);
|
||||
static DecodeStatus DecodeT2LoadT(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder);
|
||||
static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder);
|
||||
static DecodeStatus DecodeT2Imm8S4(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2AddrModeImm8s4(MCInst &Inst, unsigned Val,
|
||||
@ -3188,19 +3196,9 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM::t2PLDs:
|
||||
case ARM::t2PLDWs:
|
||||
case ARM::t2PLIs:
|
||||
break;
|
||||
default: {
|
||||
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
|
||||
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
|
||||
|
||||
if (Rn == 0xF) {
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM::t2LDRBs:
|
||||
@ -3215,19 +3213,32 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
|
||||
case ARM::t2LDRSBs:
|
||||
Inst.setOpcode(ARM::t2LDRSBpci);
|
||||
break;
|
||||
case ARM::t2PLDs:
|
||||
case ARM::t2LDRs:
|
||||
Inst.setOpcode(ARM::t2LDRpci);
|
||||
break;
|
||||
case ARM::t2PLDs: {
|
||||
Inst.setOpcode(ARM::t2PLDi12);
|
||||
Inst.addOperand(MCOperand::CreateReg(ARM::PC));
|
||||
break;
|
||||
int imm = fieldFromInstruction(Insn, 0, 12);
|
||||
if (!fieldFromInstruction(Insn, 23, 1)) imm *= -1;
|
||||
Inst.addOperand(MCOperand::CreateImm(imm));
|
||||
return S;
|
||||
}
|
||||
default:
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
||||
int imm = fieldFromInstruction(Insn, 0, 12);
|
||||
if (!fieldFromInstruction(Insn, 23, 1)) imm *= -1;
|
||||
Inst.addOperand(MCOperand::CreateImm(imm));
|
||||
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
|
||||
}
|
||||
|
||||
return S;
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM::t2PLDs:
|
||||
case ARM::t2PLDWs:
|
||||
case ARM::t2PLIs:
|
||||
break;
|
||||
default:
|
||||
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
||||
unsigned addrmode = fieldFromInstruction(Insn, 4, 2);
|
||||
@ -3239,6 +3250,154 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
|
||||
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
|
||||
unsigned U = fieldFromInstruction(Insn, 9, 1);
|
||||
unsigned imm = fieldFromInstruction(Insn, 0, 8);
|
||||
imm |= (U << 8);
|
||||
imm |= (Rn << 9);
|
||||
|
||||
if (Rn == 15) {
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM::t2LDRi8:
|
||||
Inst.setOpcode(ARM::t2LDRpci);
|
||||
break;
|
||||
case ARM::t2LDRBi8:
|
||||
Inst.setOpcode(ARM::t2LDRBpci);
|
||||
break;
|
||||
case ARM::t2LDRSBi8:
|
||||
Inst.setOpcode(ARM::t2LDRSBpci);
|
||||
break;
|
||||
case ARM::t2LDRHi8:
|
||||
Inst.setOpcode(ARM::t2LDRHpci);
|
||||
break;
|
||||
case ARM::t2LDRSHi8:
|
||||
Inst.setOpcode(ARM::t2LDRSHpci);
|
||||
break;
|
||||
default:
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
|
||||
}
|
||||
|
||||
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
|
||||
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
|
||||
unsigned imm = fieldFromInstruction(Insn, 0, 12);
|
||||
imm |= (Rn << 13);
|
||||
|
||||
if (Rn == 15) {
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM::t2LDRi12:
|
||||
Inst.setOpcode(ARM::t2LDRpci);
|
||||
break;
|
||||
case ARM::t2LDRHi12:
|
||||
Inst.setOpcode(ARM::t2LDRHpci);
|
||||
break;
|
||||
case ARM::t2LDRSHi12:
|
||||
Inst.setOpcode(ARM::t2LDRSHpci);
|
||||
break;
|
||||
case ARM::t2LDRBi12:
|
||||
Inst.setOpcode(ARM::t2LDRBpci);
|
||||
break;
|
||||
case ARM::t2LDRSBi12:
|
||||
Inst.setOpcode(ARM::t2LDRSBpci);
|
||||
break;
|
||||
default:
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
|
||||
}
|
||||
|
||||
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeT2AddrModeImm12(Inst, imm, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeT2LoadT(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
|
||||
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
|
||||
unsigned imm = fieldFromInstruction(Insn, 0, 8);
|
||||
imm |= (Rn << 9);
|
||||
|
||||
if (Rn == 15) {
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM::t2LDRT:
|
||||
Inst.setOpcode(ARM::t2LDRpci);
|
||||
break;
|
||||
case ARM::t2LDRBT:
|
||||
Inst.setOpcode(ARM::t2LDRBpci);
|
||||
break;
|
||||
case ARM::t2LDRHT:
|
||||
Inst.setOpcode(ARM::t2LDRHpci);
|
||||
break;
|
||||
case ARM::t2LDRSBT:
|
||||
Inst.setOpcode(ARM::t2LDRSBpci);
|
||||
break;
|
||||
case ARM::t2LDRSHT:
|
||||
Inst.setOpcode(ARM::t2LDRSHpci);
|
||||
break;
|
||||
default:
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
|
||||
}
|
||||
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void* Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
|
||||
unsigned U = fieldFromInstruction(Insn, 23, 1);
|
||||
int imm = fieldFromInstruction(Insn, 0, 12);
|
||||
|
||||
// FIXME: detect and decode PLD properly
|
||||
if (Inst.getOpcode() == ARM::t2LDRBpci && Rt == 15) {
|
||||
Inst.setOpcode(ARM::t2PLDi12);
|
||||
Inst.addOperand(MCOperand::CreateReg(ARM::PC));
|
||||
} else {
|
||||
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
||||
if (!U) {
|
||||
// Special case for #-0.
|
||||
if (imm == 0)
|
||||
imm = INT32_MIN;
|
||||
else
|
||||
imm = -imm;
|
||||
}
|
||||
Inst.addOperand(MCOperand::CreateImm(imm));
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeT2Imm8S4(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
if (Val == 0)
|
||||
@ -3353,6 +3512,34 @@ static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Insn,
|
||||
addr |= Rn << 9;
|
||||
unsigned load = fieldFromInstruction(Insn, 20, 1);
|
||||
|
||||
if (Rn == 15) {
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM::t2LDR_PRE:
|
||||
case ARM::t2LDR_POST:
|
||||
Inst.setOpcode(ARM::t2LDRpci);
|
||||
break;
|
||||
case ARM::t2LDRB_PRE:
|
||||
case ARM::t2LDRB_POST:
|
||||
Inst.setOpcode(ARM::t2LDRBpci);
|
||||
break;
|
||||
case ARM::t2LDRH_PRE:
|
||||
case ARM::t2LDRH_POST:
|
||||
Inst.setOpcode(ARM::t2LDRHpci);
|
||||
break;
|
||||
case ARM::t2LDRSB_PRE:
|
||||
case ARM::t2LDRSB_POST:
|
||||
Inst.setOpcode(ARM::t2LDRSBpci);
|
||||
break;
|
||||
case ARM::t2LDRSH_PRE:
|
||||
case ARM::t2LDRSH_POST:
|
||||
Inst.setOpcode(ARM::t2LDRSHpci);
|
||||
break;
|
||||
default:
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
|
||||
}
|
||||
|
||||
if (!load) {
|
||||
if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
|
@ -315,15 +315,29 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
if (MO1.isExpr())
|
||||
if (MO1.isExpr()) {
|
||||
O << *MO1.getExpr();
|
||||
else if (MO1.isImm()) {
|
||||
O << markup("<mem:") << "[pc, "
|
||||
<< markup("<imm:") << "#" << formatImm(MO1.getImm())
|
||||
<< markup(">]>", "]");
|
||||
return;
|
||||
}
|
||||
else
|
||||
llvm_unreachable("Unknown LDR label operand?");
|
||||
|
||||
O << markup("<mem:") << "[pc, ";
|
||||
|
||||
int32_t OffImm = (int32_t)MO1.getImm();
|
||||
bool isSub = OffImm < 0;
|
||||
|
||||
// Special value for #-0. All others are normal.
|
||||
if (OffImm == INT32_MIN)
|
||||
OffImm = 0;
|
||||
if (isSub) {
|
||||
O << markup("<imm:")
|
||||
<< "#-" << formatImm(-OffImm)
|
||||
<< markup(">");
|
||||
} else {
|
||||
O << markup("<imm:")
|
||||
<< "#" << formatImm(OffImm)
|
||||
<< markup(">");
|
||||
}
|
||||
O << "]" << markup(">");
|
||||
}
|
||||
|
||||
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
|
||||
|
@ -552,6 +552,17 @@
|
||||
0xd7 0xf8 0x01 0xf1
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDR(literal)
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: ldr.w r4, [pc, #-0]
|
||||
# CHECK: ldr.w r2, [pc, #-40]
|
||||
# CHECK: ldr.w r1, [pc, #1024]
|
||||
0x5f 0xf8 0x00 0x40
|
||||
0x5f 0xf8 0x28 0x20
|
||||
0xdf 0xf8 0x00 0x14
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDR(register)
|
||||
#------------------------------------------------------------------------------
|
||||
@ -630,6 +641,17 @@
|
||||
0x1d 0xf8 0x04 0x39
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRB(literal)
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: ldrb.w r6, [pc, #-0]
|
||||
# CHECK: ldrb.w r10, [pc, #227]
|
||||
# CHECK: ldrb.w r5, [pc, #0]
|
||||
0x1f 0xf8 0x00 0x60
|
||||
0x9f 0xf8 0xe3 0xa0
|
||||
0x9f 0xf8 0x00 0x50
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRBT
|
||||
#------------------------------------------------------------------------------
|
||||
@ -699,14 +721,12 @@
|
||||
# CHECK: ldrh.w r5, [r6, #33]
|
||||
# CHECK: ldrh.w r5, [r6, #257]
|
||||
# CHECK: ldrh.w lr, [r7, #257]
|
||||
# CHECK: ldrh.w r0, [pc, #-21]
|
||||
|
||||
0x35 0xf8 0x04 0x5c
|
||||
0x35 0x8c
|
||||
0xb6 0xf8 0x21 0x50
|
||||
0xb6 0xf8 0x01 0x51
|
||||
0xb7 0xf8 0x01 0xe1
|
||||
0x3f 0xf8 0x15 0x00
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@ -739,6 +759,17 @@
|
||||
0x3d 0xf8 0x04 0x39
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRH(literal)
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: ldrh.w r7, [pc, #-0]
|
||||
# CHECK: ldrh.w r5, [pc, #121]
|
||||
# CHECK: ldrh.w r4, [pc, #0]
|
||||
0x3f 0xf8 0x00 0x70
|
||||
0xbf 0xf8 0x79 0x50
|
||||
0xbf 0xf8 0x00 0x40
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRSB(immediate)
|
||||
#------------------------------------------------------------------------------
|
||||
@ -785,6 +816,17 @@
|
||||
0x1d 0xf9 0x04 0x39
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRSB(literal)
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: ldrsb.w r0, [pc, #-0]
|
||||
# CHECK: ldrsb.w r12, [pc, #80]
|
||||
# CHECK: ldrsb.w r3, [pc, #0]
|
||||
0x1f 0xf9 0x00 0x00
|
||||
0x9f 0xf9 0x50 0xc0
|
||||
0x9f 0xf9 0x00 0x30
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRSBT
|
||||
#------------------------------------------------------------------------------
|
||||
@ -846,6 +888,17 @@
|
||||
0x3d 0xf9 0x04 0x39
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRSH(literal)
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: ldrsh.w r0, [pc, #-0]
|
||||
# CHECK: ldrsh.w r10, [pc, #-231]
|
||||
# CHECK: ldrsh.w r6, [pc, #0]
|
||||
0x3f 0xf9 0x00 0x00
|
||||
0x3f 0xf9 0xe7 0xa0
|
||||
0xbf 0xf9 0x00 0x60
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# LDRSHT
|
||||
#------------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user