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:
Jim Grosbach 2011-09-09 18:37:27 +00:00
parent 1ab7c8ea03
commit b6aed508e3
10 changed files with 143 additions and 40 deletions

View File

@ -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)

View File

@ -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))

View File

@ -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", "", [],
{?, ?, ?, ?}> {

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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