mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-28 06:32:09 +00:00
Thumb2 assembly parsing and encoding for LDREX/LDREXB/LDREXD/LDREXH.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139381 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1ab7c8ea03
commit
b6aed508e3
@ -211,6 +211,8 @@ namespace {
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm0_1020s4OpValue(const MachineInstr &MI,unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm12OffsetOpValue(const MachineInstr &MI,unsigned Op)
|
||||
|
@ -5067,7 +5067,10 @@ ARMTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
|
||||
// cmp dest, oldval
|
||||
// bne exitMBB
|
||||
BB = loop1MBB;
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr));
|
||||
MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr);
|
||||
if (ldrOpc == ARM::t2LDREX)
|
||||
MIB.addImm(0);
|
||||
AddDefaultPred(MIB);
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
|
||||
.addReg(dest).addReg(oldval));
|
||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
|
||||
@ -5080,8 +5083,10 @@ ARMTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
|
||||
// cmp scratch, #0
|
||||
// bne loop1MBB
|
||||
BB = loop2MBB;
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(newval)
|
||||
.addReg(ptr));
|
||||
MIB = BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(newval).addReg(ptr);
|
||||
if (strOpc == ARM::t2STREX)
|
||||
MIB.addImm(0);
|
||||
AddDefaultPred(MIB);
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
|
||||
.addReg(scratch).addImm(0));
|
||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
|
||||
@ -5167,7 +5172,10 @@ ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
|
||||
// bne- loopMBB
|
||||
// fallthrough --> exitMBB
|
||||
BB = loopMBB;
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr));
|
||||
MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr);
|
||||
if (ldrOpc == ARM::t2LDREX)
|
||||
MIB.addImm(0);
|
||||
AddDefaultPred(MIB);
|
||||
if (BinOpcode) {
|
||||
// operand order needs to go the other way for NAND
|
||||
if (BinOpcode == ARM::BICrr || BinOpcode == ARM::t2BICrr)
|
||||
@ -5178,8 +5186,10 @@ ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
|
||||
addReg(dest).addReg(incr)).addReg(0);
|
||||
}
|
||||
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2)
|
||||
.addReg(ptr));
|
||||
MIB = BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2).addReg(ptr);
|
||||
if (strOpc == ARM::t2STREX)
|
||||
MIB.addImm(0);
|
||||
AddDefaultPred(MIB);
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
|
||||
.addReg(scratch).addImm(0));
|
||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
|
||||
@ -5274,7 +5284,10 @@ ARMTargetLowering::EmitAtomicBinaryMinMax(MachineInstr *MI,
|
||||
// bne- loopMBB
|
||||
// fallthrough --> exitMBB
|
||||
BB = loopMBB;
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr));
|
||||
MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr);
|
||||
if (ldrOpc == ARM::t2LDREX)
|
||||
MIB.addImm(0);
|
||||
AddDefaultPred(MIB);
|
||||
|
||||
// Sign extend the value, if necessary.
|
||||
if (signExtend && extendOpc) {
|
||||
@ -5290,8 +5303,10 @@ ARMTargetLowering::EmitAtomicBinaryMinMax(MachineInstr *MI,
|
||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr), scratch2)
|
||||
.addReg(oldval).addReg(incr).addImm(Cond).addReg(ARM::CPSR);
|
||||
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2)
|
||||
.addReg(ptr));
|
||||
MIB = BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2).addReg(ptr);
|
||||
if (strOpc == ARM::t2STREX)
|
||||
MIB.addImm(0);
|
||||
AddDefaultPred(MIB);
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
|
||||
.addReg(scratch).addImm(0));
|
||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
|
||||
|
@ -180,6 +180,18 @@ def t2am_imm8s4_offset : Operand<i32> {
|
||||
let DecoderMethod = "DecodeT2Imm8S4";
|
||||
}
|
||||
|
||||
// t2addrmode_imm0_1020s4 := reg + (imm8 << 2)
|
||||
def MemImm0_1020s4OffsetAsmOperand : AsmOperandClass {
|
||||
let Name = "MemImm0_1020s4Offset";
|
||||
}
|
||||
def t2addrmode_imm0_1020s4 : Operand<i32> {
|
||||
let PrintMethod = "printT2AddrModeImm0_1020s4Operand";
|
||||
let EncoderMethod = "getT2AddrModeImm0_1020s4OpValue";
|
||||
let DecoderMethod = "DecodeT2AddrModeImm0_1020s4";
|
||||
let ParserMatchClass = MemImm0_1020s4OffsetAsmOperand;
|
||||
let MIOperandInfo = (ops GPRnopc:$base, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
// t2addrmode_so_reg := reg + (reg << imm2)
|
||||
def t2addrmode_so_reg_asmoperand : AsmOperandClass {let Name="T2MemRegOffset";}
|
||||
def t2addrmode_so_reg : Operand<i32>,
|
||||
@ -191,16 +203,6 @@ def t2addrmode_so_reg : Operand<i32>,
|
||||
let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
// t2addrmode_reg := reg
|
||||
// Used by load/store exclusive instructions. Useful to enable right assembly
|
||||
// parsing and printing. Not used for any codegen matching.
|
||||
//
|
||||
def t2addrmode_reg : Operand<i32> {
|
||||
let PrintMethod = "printAddrMode7Operand";
|
||||
let DecoderMethod = "DecodeGPRRegisterClass";
|
||||
let MIOperandInfo = (ops GPR);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Multiclass helpers...
|
||||
//
|
||||
@ -2877,28 +2879,27 @@ class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, int sz,
|
||||
}
|
||||
|
||||
let mayLoad = 1 in {
|
||||
def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
|
||||
def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"ldrexb", "\t$Rt, $addr", "", []>;
|
||||
def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
|
||||
def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"ldrexh", "\t$Rt, $addr", "", []>;
|
||||
def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
|
||||
def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_imm0_1020s4:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"ldrex", "\t$Rt, $addr", "", []> {
|
||||
bits<4> Rt;
|
||||
bits<12> addr;
|
||||
let Inst{31-27} = 0b11101;
|
||||
let Inst{26-20} = 0b0000101;
|
||||
let Inst{11-8} = 0b1111;
|
||||
let Inst{7-0} = 0b00000000; // imm8 = 0
|
||||
|
||||
bits<4> Rt;
|
||||
bits<4> addr;
|
||||
let Inst{19-16} = addr;
|
||||
let Inst{19-16} = addr{11-8};
|
||||
let Inst{15-12} = Rt;
|
||||
let Inst{11-8} = 0b1111;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
}
|
||||
let hasExtraDefRegAllocReq = 1 in
|
||||
def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2),
|
||||
(ins t2addrmode_reg:$addr),
|
||||
(ins addr_offset_none:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"ldrexd", "\t$Rt, $Rt2, $addr", "",
|
||||
[], {?, ?, ?, ?}> {
|
||||
@ -2909,33 +2910,33 @@ def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2),
|
||||
|
||||
let mayStore = 1, Constraints = "@earlyclobber $Rd" in {
|
||||
def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd),
|
||||
(ins rGPR:$Rt, t2addrmode_reg:$addr),
|
||||
(ins rGPR:$Rt, addr_offset_none:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"strexb", "\t$Rd, $Rt, $addr", "", []>;
|
||||
def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd),
|
||||
(ins rGPR:$Rt, t2addrmode_reg:$addr),
|
||||
(ins rGPR:$Rt, addr_offset_none:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"strexh", "\t$Rd, $Rt, $addr", "", []>;
|
||||
def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr),
|
||||
def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt,
|
||||
t2addrmode_imm0_1020s4:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"strex", "\t$Rd, $Rt, $addr", "",
|
||||
[]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rt;
|
||||
bits<12> addr;
|
||||
let Inst{31-27} = 0b11101;
|
||||
let Inst{26-20} = 0b0000100;
|
||||
let Inst{7-0} = 0b00000000; // imm8 = 0
|
||||
|
||||
bits<4> Rd;
|
||||
bits<4> addr;
|
||||
bits<4> Rt;
|
||||
let Inst{11-8} = Rd;
|
||||
let Inst{19-16} = addr;
|
||||
let Inst{19-16} = addr{11-8};
|
||||
let Inst{15-12} = Rt;
|
||||
let Inst{11-8} = Rd;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
}
|
||||
}
|
||||
|
||||
let hasExtraSrcRegAllocReq = 1, Constraints = "@earlyclobber $Rd" in
|
||||
def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd),
|
||||
(ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_reg:$addr),
|
||||
(ins rGPR:$Rt, rGPR:$Rt2, addr_offset_none:$addr),
|
||||
AddrModeNone, 4, NoItinerary,
|
||||
"strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [],
|
||||
{?, ?, ?, ?}> {
|
||||
|
@ -756,6 +756,14 @@ public:
|
||||
int64_t Val = Mem.OffsetImm->getValue();
|
||||
return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
|
||||
}
|
||||
bool isMemImm0_1020s4Offset() const {
|
||||
if (Kind != Memory || Mem.OffsetRegNum != 0)
|
||||
return false;
|
||||
// Immediate offset a multiple of 4 in range [0, 1020].
|
||||
if (!Mem.OffsetImm) return true;
|
||||
int64_t Val = Mem.OffsetImm->getValue();
|
||||
return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
|
||||
}
|
||||
bool isMemImm8Offset() const {
|
||||
if (Kind != Memory || Mem.OffsetRegNum != 0)
|
||||
return false;
|
||||
@ -1146,6 +1154,14 @@ public:
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
}
|
||||
|
||||
void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
// The lower two bits are always zero and as such are not encoded.
|
||||
int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 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;
|
||||
|
@ -269,6 +269,8 @@ static DecodeStatus DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2AddrModeImm0_1020s4(llvm::MCInst &Inst,unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
|
||||
@ -2669,6 +2671,21 @@ static DecodeStatus DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeT2AddrModeImm0_1020s4(llvm::MCInst &Inst,unsigned Val,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned Rn = fieldFromInstruction32(Val, 8, 4);
|
||||
unsigned imm = fieldFromInstruction32(Val, 0, 8);
|
||||
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
Inst.addOperand(MCOperand::CreateImm(imm));
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
int imm = Val & 0xFF;
|
||||
|
@ -812,6 +812,18 @@ void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(const MCInst *MI,
|
||||
unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (MO2.getImm())
|
||||
O << ", #" << MO2.getImm() * 4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
|
||||
unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
|
@ -96,6 +96,8 @@ public:
|
||||
raw_ostream &O);
|
||||
void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printT2AddrModeImm0_1020s4Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum,
|
||||
|
@ -144,6 +144,12 @@ public:
|
||||
/// operand.
|
||||
uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2'
|
||||
/// operand.
|
||||
uint32_t getT2AddrModeImm0_1020s4OpValue(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,
|
||||
@ -795,6 +801,20 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return Binary;
|
||||
}
|
||||
|
||||
/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for
|
||||
/// 'reg + imm8<<2' operand.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// {11-8} = reg
|
||||
// {7-0} = imm8
|
||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
|
||||
unsigned Reg = getARMRegisterNumbering(MO.getReg());
|
||||
unsigned Imm8 = MO1.getImm();
|
||||
return (Reg << 8) | Imm8;
|
||||
}
|
||||
|
||||
// FIXME: This routine assumes that a binary
|
||||
// expression will always result in a PCRel expression
|
||||
// In reality, its only true if one or more subexpressions
|
||||
|
@ -646,6 +646,23 @@ _func:
|
||||
@ CHECK: ldrd r3, r5, [r6] @ encoding: [0xd6,0xe9,0x00,0x35]
|
||||
@ CHECK: ldrd r8, r1, [r3] @ encoding: [0xd3,0xe9,0x00,0x81]
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ LDREX/LDREXB/LDREXH/LDREXD
|
||||
@------------------------------------------------------------------------------
|
||||
ldrex r1, [r4]
|
||||
ldrex r8, [r4, #0]
|
||||
ldrex r2, [sp, #128]
|
||||
ldrexb r5, [r7]
|
||||
ldrexh r9, [r12]
|
||||
ldrexd r9, r3, [r4]
|
||||
|
||||
@ CHECK: ldrex r1, [r4] @ encoding: [0x54,0xe8,0x00,0x1f]
|
||||
@ CHECK: ldrex r8, [r4] @ encoding: [0x54,0xe8,0x00,0x8f]
|
||||
@ CHECK: ldrex r2, [sp, #128] @ encoding: [0x5d,0xe8,0x20,0x2f]
|
||||
@ CHECK: ldrexb r5, [r7] @ encoding: [0xd7,0xe8,0x4f,0x5f]
|
||||
@ CHECK: ldrexh r9, [r12] @ encoding: [0xdc,0xe8,0x5f,0x9f]
|
||||
@ CHECK: ldrexd r9, r3, [r4] @ encoding: [0xd4,0xe8,0x7f,0x93]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ FIXME: LDRD(literal)
|
||||
|
@ -673,6 +673,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I
|
||||
MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I
|
||||
MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
|
||||
MISC("t2addrmode_imm0_1020s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
|
||||
MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
|
||||
// R, I
|
||||
MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I
|
||||
|
Loading…
x
Reference in New Issue
Block a user