mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 19:31:58 +00:00
Thumb2 assembly parsing and encoding for LDRD(immediate).
Refactor operand handling for STRD as well. Tests for that forthcoming. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139322 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7ec8fb8830
commit
a77295db19
@ -207,6 +207,8 @@ namespace {
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2Imm8s4OpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op)
|
||||
|
@ -1100,8 +1100,8 @@ class T2Ipc<dag oops, dag iops, InstrItinClass itin,
|
||||
string opc, string asm, list<dag> pattern>
|
||||
: Thumb2I<oops, iops, AddrModeT2_pc, 4, itin, opc, asm, "", pattern>;
|
||||
class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
|
||||
string opc, string asm, list<dag> pattern>
|
||||
: Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, "",
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, cstr,
|
||||
pattern> {
|
||||
bits<4> Rt;
|
||||
bits<4> Rt2;
|
||||
@ -1117,14 +1117,14 @@ class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
|
||||
let Inst{11-8} = Rt2{3-0};
|
||||
let Inst{7-0} = addr{7-0};
|
||||
}
|
||||
|
||||
class T2Ii8s4Tied<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
|
||||
string opc, string asm, list<dag> pattern>
|
||||
: Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, "$base = $wb",
|
||||
class T2Ii8s4post<bit P, bit W, bit isLoad, dag oops, dag iops,
|
||||
InstrItinClass itin, string opc, string asm, string cstr,
|
||||
list<dag> pattern>
|
||||
: Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, cstr,
|
||||
pattern> {
|
||||
bits<4> Rt;
|
||||
bits<4> Rt2;
|
||||
bits<4> base;
|
||||
bits<4> addr;
|
||||
bits<9> imm;
|
||||
let Inst{31-25} = 0b1110100;
|
||||
let Inst{24} = P;
|
||||
@ -1132,13 +1132,12 @@ class T2Ii8s4Tied<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass i
|
||||
let Inst{22} = 1;
|
||||
let Inst{21} = W;
|
||||
let Inst{20} = isLoad;
|
||||
let Inst{19-16} = base{3-0};
|
||||
let Inst{19-16} = addr;
|
||||
let Inst{15-12} = Rt{3-0};
|
||||
let Inst{11-8} = Rt2{3-0};
|
||||
let Inst{7-0} = imm{7-0};
|
||||
}
|
||||
|
||||
|
||||
class T2sI<dag oops, dag iops, InstrItinClass itin,
|
||||
string opc, string asm, list<dag> pattern>
|
||||
: Thumb2sI<oops, iops, AddrModeNone, 4, itin, opc, asm, "", pattern>;
|
||||
|
@ -164,15 +164,19 @@ def t2am_imm8_offset : Operand<i32>,
|
||||
}
|
||||
|
||||
// t2addrmode_imm8s4 := reg +/- (imm8 << 2)
|
||||
def MemImm8s4OffsetAsmOperand : AsmOperandClass {let Name = "MemImm8s4Offset";}
|
||||
def t2addrmode_imm8s4 : Operand<i32> {
|
||||
let PrintMethod = "printT2AddrModeImm8s4Operand";
|
||||
let EncoderMethod = "getT2AddrModeImm8s4OpValue";
|
||||
let DecoderMethod = "DecodeT2AddrModeImm8s4";
|
||||
let ParserMatchClass = MemImm8s4OffsetAsmOperand;
|
||||
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
def t2am_imm8s4_offset_asmoperand : AsmOperandClass { let Name = "Imm8s4"; }
|
||||
def t2am_imm8s4_offset : Operand<i32> {
|
||||
let PrintMethod = "printT2AddrModeImm8s4OffsetOperand";
|
||||
let EncoderMethod = "getT2Imm8s4OpValue";
|
||||
let DecoderMethod = "DecodeT2Imm8S4";
|
||||
}
|
||||
|
||||
@ -1193,7 +1197,7 @@ let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
|
||||
// Load doubleword
|
||||
def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs rGPR:$Rt, rGPR:$Rt2),
|
||||
(ins t2addrmode_imm8s4:$addr),
|
||||
IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", []>;
|
||||
IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", "", []>;
|
||||
} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1
|
||||
|
||||
// zextload i1 -> zextload i8
|
||||
@ -1344,7 +1348,7 @@ defm t2STRH:T2I_st<0b01,"strh", IIC_iStore_bh_i, IIC_iStore_bh_si,
|
||||
let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
|
||||
def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs),
|
||||
(ins GPR:$Rt, GPR:$Rt2, t2addrmode_imm8s4:$addr),
|
||||
IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", []>;
|
||||
IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", "", []>;
|
||||
|
||||
// Indexed stores
|
||||
def t2STR_PRE : T2Ipreldst<0, 0b10, 0, 1, (outs GPRnopc:$Rn_wb),
|
||||
@ -1424,23 +1428,31 @@ def t2STRHT : T2IstT<0b01, "strht", IIC_iStore_bh_i>;
|
||||
// ldrd / strd pre / post variants
|
||||
// For disassembly only.
|
||||
|
||||
def t2LDRD_PRE : T2Ii8s4Tied<1, 1, 1,
|
||||
(outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
|
||||
(ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru,
|
||||
"ldrd", "\t$Rt, $Rt2, [$base, $imm]!", []>;
|
||||
def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
|
||||
(ins t2addrmode_imm8s4:$addr), IIC_iLoad_d_ru,
|
||||
"ldrd", "\t$Rt, $Rt2, $addr!", "$addr.base = $wb", []> {
|
||||
let AsmMatchConverter = "cvtT2LdrdPre";
|
||||
let DecoderMethod = "DecodeT2LDRDPreInstruction";
|
||||
}
|
||||
|
||||
def t2LDRD_POST : T2Ii8s4Tied<0, 1, 1,
|
||||
(outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
|
||||
(ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru,
|
||||
"ldrd", "\t$Rt, $Rt2, [$base], $imm", []>;
|
||||
def t2LDRD_POST : T2Ii8s4post<0, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
|
||||
(ins addr_offset_none:$addr, t2am_imm8s4_offset:$imm),
|
||||
IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, $addr, $imm",
|
||||
"$addr.base = $wb", []>;
|
||||
|
||||
def t2STRD_PRE : T2Ii8s4Tied<1, 1, 0, (outs GPR:$wb),
|
||||
(ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm),
|
||||
IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base, $imm]!", []>;
|
||||
def t2STRD_PRE : T2Ii8s4<1, 1, 0, (outs GPR:$wb),
|
||||
(ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_imm8s4:$addr),
|
||||
IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, $addr!",
|
||||
"$addr.base = $wb", []> {
|
||||
let AsmMatchConverter = "cvtT2StrdPre";
|
||||
let DecoderMethod = "DecodeT2STRDPreInstruction";
|
||||
}
|
||||
|
||||
def t2STRD_POST : T2Ii8s4Tied<0, 1, 0, (outs GPR:$wb),
|
||||
(ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm),
|
||||
IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base], $imm", []>;
|
||||
def t2STRD_POST : T2Ii8s4post<0, 1, 0, (outs GPR:$wb),
|
||||
(ins rGPR:$Rt, rGPR:$Rt2, addr_offset_none:$addr,
|
||||
t2am_imm8s4_offset:$imm),
|
||||
IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, $addr, $imm",
|
||||
"$addr.base = $wb", []>;
|
||||
|
||||
// T2Ipl (Preload Data/Instruction) signals the memory system of possible future
|
||||
// data/instruction access. These are for disassembly only.
|
||||
|
@ -158,6 +158,10 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
|
||||
// Asm Match Converter Methods
|
||||
bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
||||
@ -463,6 +467,14 @@ public:
|
||||
bool isITMask() const { return Kind == ITCondMask; }
|
||||
bool isITCondCode() const { return Kind == CondCode; }
|
||||
bool isImm() const { return Kind == Immediate; }
|
||||
bool isImm8s4() const {
|
||||
if (Kind != Immediate)
|
||||
return false;
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
if (!CE) return false;
|
||||
int64_t Value = CE->getValue();
|
||||
return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
|
||||
}
|
||||
bool isImm0_1020s4() const {
|
||||
if (Kind != Immediate)
|
||||
return false;
|
||||
@ -736,6 +748,14 @@ public:
|
||||
int64_t Val = Mem.OffsetImm->getValue();
|
||||
return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
|
||||
}
|
||||
bool isMemImm8s4Offset() const {
|
||||
if (Kind != Memory || Mem.OffsetRegNum != 0)
|
||||
return false;
|
||||
// Immediate offset a multiple of 4 in range [-1020, 1020].
|
||||
if (!Mem.OffsetImm) return true;
|
||||
int64_t Val = Mem.OffsetImm->getValue();
|
||||
return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
|
||||
}
|
||||
bool isMemImm8Offset() const {
|
||||
if (Kind != Memory || Mem.OffsetRegNum != 0)
|
||||
return false;
|
||||
@ -908,6 +928,14 @@ public:
|
||||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
void addImm8s4Operands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
// FIXME: We really want to scale the value here, but the LDRD/STRD
|
||||
// instruction don't encode operands that way yet.
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
|
||||
}
|
||||
|
||||
void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
// The immediate is scaled by four in the encoding and is stored
|
||||
@ -1111,6 +1139,13 @@ public:
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
}
|
||||
|
||||
void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
|
||||
Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
}
|
||||
|
||||
void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
|
||||
@ -2400,6 +2435,42 @@ parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
/// cvtT2LdrdPre - Convert parsed operands to MCInst.
|
||||
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
||||
/// when they refer multiple MIOperands inside a single one.
|
||||
bool ARMAsmParser::
|
||||
cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
// Rt, Rt2
|
||||
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
|
||||
((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
|
||||
// Create a writeback register dummy placeholder.
|
||||
Inst.addOperand(MCOperand::CreateReg(0));
|
||||
// addr
|
||||
((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
|
||||
// pred
|
||||
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// cvtT2StrdPre - Convert parsed operands to MCInst.
|
||||
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
||||
/// when they refer multiple MIOperands inside a single one.
|
||||
bool ARMAsmParser::
|
||||
cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
// Create a writeback register dummy placeholder.
|
||||
Inst.addOperand(MCOperand::CreateReg(0));
|
||||
// Rt, Rt2
|
||||
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
|
||||
((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
|
||||
// addr
|
||||
((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
|
||||
// pred
|
||||
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
|
||||
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
||||
/// when they refer multiple MIOperands inside a single one.
|
||||
|
@ -293,6 +293,10 @@ static DecodeStatus DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeIT(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2LDRDPreInstruction(llvm::MCInst &Inst,unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2STRDPreInstruction(llvm::MCInst &Inst,unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
|
||||
#include "ARMGenDisassemblerTables.inc"
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
@ -3649,3 +3653,75 @@ static DecodeStatus DecodeIT(llvm::MCInst &Inst, unsigned Insn,
|
||||
Inst.addOperand(MCOperand::CreateImm(mask));
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus
|
||||
DecodeT2LDRDPreInstruction(llvm::MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
|
||||
unsigned Rt2 = fieldFromInstruction32(Insn, 8, 4);
|
||||
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
|
||||
unsigned addr = fieldFromInstruction32(Insn, 0, 8);
|
||||
unsigned W = fieldFromInstruction32(Insn, 21, 1);
|
||||
unsigned U = fieldFromInstruction32(Insn, 23, 1);
|
||||
unsigned P = fieldFromInstruction32(Insn, 24, 1);
|
||||
bool writeback = (W == 1) | (P == 0);
|
||||
|
||||
addr |= (U << 8) | (Rn << 9);
|
||||
|
||||
if (writeback && (Rn == Rt || Rn == Rt2))
|
||||
Check(S, MCDisassembler::SoftFail);
|
||||
if (Rt == Rt2)
|
||||
Check(S, MCDisassembler::SoftFail);
|
||||
|
||||
// Rt
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
// Rt2
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rt2, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
// Writeback operand
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
// addr
|
||||
if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus
|
||||
DecodeT2STRDPreInstruction(llvm::MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
|
||||
unsigned Rt2 = fieldFromInstruction32(Insn, 8, 4);
|
||||
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
|
||||
unsigned addr = fieldFromInstruction32(Insn, 0, 8);
|
||||
unsigned W = fieldFromInstruction32(Insn, 21, 1);
|
||||
unsigned U = fieldFromInstruction32(Insn, 23, 1);
|
||||
unsigned P = fieldFromInstruction32(Insn, 24, 1);
|
||||
bool writeback = (W == 1) | (P == 0);
|
||||
|
||||
addr |= (U << 8) | (Rn << 9);
|
||||
|
||||
if (writeback && (Rn == Rt || Rn == Rt2))
|
||||
Check(S, MCDisassembler::SoftFail);
|
||||
|
||||
// Writeback operand
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
// Rt
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
// Rt2
|
||||
if (!Check(S, DecoderGPRRegisterClass(Inst, Rt2, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
// addr
|
||||
if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
return S;
|
||||
}
|
||||
|
@ -144,6 +144,10 @@ public:
|
||||
/// operand.
|
||||
uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
/// getT2Imm8s4OpValue - Return encoding info for '+/- imm8<<2'
|
||||
/// operand.
|
||||
uint32_t getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
|
||||
/// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
|
||||
@ -720,6 +724,37 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return Binary;
|
||||
}
|
||||
|
||||
/// getT2Imm8s4OpValue - Return encoding info for
|
||||
/// '+/- imm8<<2' operand.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// FIXME: The immediate operand should have already been encoded like this
|
||||
// before ever getting here. The encoder method should just need to combine
|
||||
// the MI operands for the register and the offset into a single
|
||||
// representation for the complex operand in the .td file. This isn't just
|
||||
// style, unfortunately. As-is, we can't represent the distinct encoding
|
||||
// for #-0.
|
||||
|
||||
// {8} = (U)nsigned (add == '1', sub == '0')
|
||||
// {7-0} = imm8
|
||||
int32_t Imm8 = MI.getOperand(OpIdx).getImm();
|
||||
bool isAdd = Imm8 >= 0;
|
||||
|
||||
// Immediate is always encoded as positive. The 'U' bit controls add vs sub.
|
||||
if (Imm8 < 0)
|
||||
Imm8 = -Imm8;
|
||||
|
||||
// Scaled by 4.
|
||||
Imm8 /= 4;
|
||||
|
||||
uint32_t Binary = Imm8 & 0xff;
|
||||
// Immediate is always encoded as positive. The 'U' bit controls add vs sub.
|
||||
if (isAdd)
|
||||
Binary |= (1 << 8);
|
||||
return Binary;
|
||||
}
|
||||
|
||||
/// getT2AddrModeImm8s4OpValue - Return encoding info for
|
||||
/// 'reg +/- imm8<<2' operand.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
@ -746,6 +781,12 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
} else
|
||||
isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
|
||||
|
||||
// FIXME: The immediate operand should have already been encoded like this
|
||||
// before ever getting here. The encoder method should just need to combine
|
||||
// the MI operands for the register and the offset into a single
|
||||
// representation for the complex operand in the .td file. This isn't just
|
||||
// style, unfortunately. As-is, we can't represent the distinct encoding
|
||||
// for #-0.
|
||||
uint32_t Binary = (Imm8 >> 2) & 0xff;
|
||||
// Immediate is always encoded as positive. The 'U' bit controls add vs sub.
|
||||
if (isAdd)
|
||||
|
@ -629,6 +629,24 @@ _func:
|
||||
@ CHECK: ldrbt r1, [r8, #255] @ encoding: [0x18,0xf8,0xff,0x1e]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ LDRD(immediate)
|
||||
@------------------------------------------------------------------------------
|
||||
ldrd r3, r5, [r6, #24]
|
||||
ldrd r3, r5, [r6, #24]!
|
||||
ldrd r3, r5, [r6], #4
|
||||
ldrd r3, r5, [r6], #-8
|
||||
ldrd r3, r5, [r6]
|
||||
ldrd r8, r1, [r3, #0]
|
||||
|
||||
@ CHECK: ldrd r3, r5, [r6, #24] @ encoding: [0xd6,0xe9,0x06,0x35]
|
||||
@ CHECK: ldrd r3, r5, [r6, #24]! @ encoding: [0xf6,0xe9,0x06,0x35]
|
||||
@ CHECK: ldrd r3, r5, [r6], #4 @ encoding: [0xf6,0xe8,0x01,0x35]
|
||||
@ CHECK: ldrd r3, r5, [r6], #-8 @ encoding: [0x76,0xe8,0x02,0x35]
|
||||
@ CHECK: ldrd r3, r5, [r6] @ encoding: [0xd6,0xe9,0x00,0x35]
|
||||
@ CHECK: ldrd r8, r1, [r3] @ encoding: [0xd3,0xe9,0x00,0x81]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ IT
|
||||
@------------------------------------------------------------------------------
|
||||
|
@ -1,5 +1,4 @@
|
||||
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
|
||||
# XFAIL: *
|
||||
|
||||
# Opcode=1930 Name=t2LDRD_PRE Format=ARM_FORMAT_THUMBFRM(25)
|
||||
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
|
Loading…
Reference in New Issue
Block a user