mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-20 10:24:12 +00:00
Fix issues with the ARM bl and blx thumb instructions and the J1 and J2 bits
for the assembler and disassembler. Which were not being set/read correctly for offsets greater than 22 bits in some cases. Changes to lib/Target/ARM/ARMAsmBackend.cpp from Gideon Myles! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156118 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -3339,10 +3339,25 @@ static DecodeStatus DecodePostIdxReg(MCInst &Inst, unsigned Insn,
|
||||
|
||||
static DecodeStatus DecodeThumbBLXOffset(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
// Val is passed in as S:J1:J2:imm10H:imm10L:’0’
|
||||
// Note only one trailing zero not two. Also the J1 and J2 values are from
|
||||
// the encoded instruction. So here change to I1 and I2 values via:
|
||||
// I1 = NOT(J1 EOR S);
|
||||
// I2 = NOT(J2 EOR S);
|
||||
// and build the imm32 with two trailing zeros as documented:
|
||||
// imm32 = SignExtend(S:I1:I2:imm10H:imm10L:’00’, 32);
|
||||
unsigned S = (Val >> 23) & 1;
|
||||
unsigned J1 = (Val >> 22) & 1;
|
||||
unsigned J2 = (Val >> 21) & 1;
|
||||
unsigned I1 = !(J1 ^ S);
|
||||
unsigned I2 = !(J2 ^ S);
|
||||
unsigned tmp = (Val & ~0x600000) | (I1 << 22) | (I2 << 21);
|
||||
int imm32 = SignExtend32<25>(tmp << 1);
|
||||
|
||||
if (!tryAddingSymbolicOperand(Address,
|
||||
(Address & ~2u) + SignExtend32<22>(Val << 1) + 4,
|
||||
(Address & ~2u) + imm32 + 4,
|
||||
true, 4, Inst, Decoder))
|
||||
Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
|
||||
Inst.addOperand(MCOperand::CreateImm(imm32));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
@ -3456,9 +3471,24 @@ DecodeThumbBCCTargetOperand(MCInst &Inst, unsigned Val,
|
||||
|
||||
static DecodeStatus DecodeThumbBLTargetOperand(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder){
|
||||
if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<22>(Val<<1) + 4,
|
||||
// Val is passed in as S:J1:J2:imm10:imm11
|
||||
// Note no trailing zero after imm11. Also the J1 and J2 values are from
|
||||
// the encoded instruction. So here change to I1 and I2 values via:
|
||||
// I1 = NOT(J1 EOR S);
|
||||
// I2 = NOT(J2 EOR S);
|
||||
// and build the imm32 with one trailing zero as documented:
|
||||
// imm32 = SignExtend(S:I1:I2:imm10:imm11:’0’, 32);
|
||||
unsigned S = (Val >> 23) & 1;
|
||||
unsigned J1 = (Val >> 22) & 1;
|
||||
unsigned J2 = (Val >> 21) & 1;
|
||||
unsigned I1 = !(J1 ^ S);
|
||||
unsigned I2 = !(J2 ^ S);
|
||||
unsigned tmp = (Val & ~0x600000) | (I1 << 22) | (I2 << 21);
|
||||
int imm32 = SignExtend32<25>(tmp << 1);
|
||||
|
||||
if (!tryAddingSymbolicOperand(Address, Address + imm32 + 4,
|
||||
true, 4, Inst, Decoder))
|
||||
Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
|
||||
Inst.addOperand(MCOperand::CreateImm(imm32));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user