Add asm parsing support w/ testcases for strex/ldrex family of instructions

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128236 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes 2011-03-24 21:04:58 +00:00
parent 02af767dca
commit 505f3cd296
11 changed files with 156 additions and 61 deletions

View File

@ -35,6 +35,7 @@ enum OperandTypes {
kOperandTypeARMAddrMode5,
kOperandTypeARMAddrMode6,
kOperandTypeARMAddrMode6Offset,
kOperandTypeARMAddrMode7,
kOperandTypeARMAddrModePC,
kOperandTypeARMRegisterList,
kOperandTypeARMTBAddrMode,
@ -51,7 +52,8 @@ enum OperandTypes {
kOperandTypeThumb2AddrModeImm12,
kOperandTypeThumb2AddrModeSoReg,
kOperandTypeThumb2AddrModeImm8s4,
kOperandTypeThumb2AddrModeImm8s4Offset
kOperandTypeThumb2AddrModeImm8s4Offset,
kOperandTypeThumb2AddrModeReg
};
enum OperandFlags {

View File

@ -73,6 +73,8 @@ EDOperand::EDOperand(const EDDisassembler &disassembler,
case kOperandTypeThumb2AddrModeImm8Offset:
case kOperandTypeARMTBAddrMode:
case kOperandTypeThumb2AddrModeImm8s4Offset:
case kOperandTypeARMAddrMode7:
case kOperandTypeThumb2AddrModeReg:
numMCOperands = 1;
break;
case kOperandTypeThumb2SoReg:
@ -256,6 +258,7 @@ int EDOperand::isMemory() {
case kOperandTypeARMAddrMode4:
case kOperandTypeARMAddrMode5:
case kOperandTypeARMAddrMode6:
case kOperandTypeARMAddrMode7:
case kOperandTypeARMAddrModePC:
case kOperandTypeARMBranchTarget:
case kOperandTypeThumbAddrModeS1:
@ -269,6 +272,7 @@ int EDOperand::isMemory() {
case kOperandTypeThumb2AddrModeImm12:
case kOperandTypeThumb2AddrModeSoReg:
case kOperandTypeThumb2AddrModeImm8s4:
case kOperandTypeThumb2AddrModeReg:
return 1;
}
}

View File

@ -434,11 +434,11 @@ class AIstrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
opc, asm, "", pattern> {
bits<4> Rd;
bits<4> Rt;
bits<4> Rn;
bits<4> addr;
let Inst{27-23} = 0b00011;
let Inst{22-21} = opcod;
let Inst{20} = 0;
let Inst{19-16} = Rn;
let Inst{19-16} = addr;
let Inst{15-12} = Rd;
let Inst{11-4} = 0b11111001;
let Inst{3-0} = Rt;

View File

@ -590,6 +590,21 @@ def addrmodepc : Operand<i32>,
let MIOperandInfo = (ops GPR, i32imm);
}
def MemMode7AsmOperand : AsmOperandClass {
let Name = "MemMode7";
let SuperClasses = [];
}
// addrmode7 := reg
// Used by load/store exclusive instructions. Useful to enable right assembly
// parsing and printing. Not used for any codegen matching.
//
def addrmode7 : Operand<i32> {
let PrintMethod = "printAddrMode7Operand";
let MIOperandInfo = (ops GPR);
let ParserMatchClass = MemMode7AsmOperand;
}
def nohash_imm : Operand<i32> {
let PrintMethod = "printNoHashImmediate";
}
@ -3294,39 +3309,26 @@ let usesCustomInserter = 1 in {
}
let mayLoad = 1 in {
def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
"ldrexb", "\t$Rt, [$Rn]",
[]>;
def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
"ldrexh", "\t$Rt, [$Rn]",
[]>;
def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
"ldrex", "\t$Rt, [$Rn]",
[]>;
def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins GPR:$Rn),
NoItinerary,
"ldrexd", "\t$Rt, $Rt2, [$Rn]",
[]>;
def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary,
"ldrexb", "\t$Rt, $addr", []>;
def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary,
"ldrexh", "\t$Rt, $addr", []>;
def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary,
"ldrex", "\t$Rt, $addr", []>;
def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins addrmode7:$addr),
NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", []>;
}
let mayStore = 1, Constraints = "@earlyclobber $Rd" in {
def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$src, GPR:$Rn),
NoItinerary,
"strexb", "\t$Rd, $src, [$Rn]",
[]>;
def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn),
NoItinerary,
"strexh", "\t$Rd, $Rt, [$Rn]",
[]>;
def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn),
NoItinerary,
"strex", "\t$Rd, $Rt, [$Rn]",
[]>;
def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr),
NoItinerary, "strexb", "\t$Rd, $Rt, $addr", []>;
def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr),
NoItinerary, "strexh", "\t$Rd, $Rt, $addr", []>;
def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr),
NoItinerary, "strex", "\t$Rd, $Rt, $addr", []>;
def STREXD : AIstrex<0b01, (outs GPR:$Rd),
(ins GPR:$Rt, GPR:$Rt2, GPR:$Rn),
NoItinerary,
"strexd", "\t$Rd, $Rt, $Rt2, [$Rn]",
[]>;
(ins GPR:$Rt, GPR:$Rt2, addrmode7:$addr),
NoItinerary, "strexd", "\t$Rd, $Rt, $Rt2, $addr", []>;
}
// Clear-Exclusive is for disassembly only.

View File

@ -145,6 +145,15 @@ def t2addrmode_so_reg : Operand<i32>,
let ParserMatchClass = MemMode5AsmOperand;
}
// 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 MIOperandInfo = (ops tGPR);
let ParserMatchClass = MemMode7AsmOperand;
}
//===----------------------------------------------------------------------===//
// Multiclass helpers...
@ -2821,9 +2830,9 @@ class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz,
let Inst{5-4} = opcod;
let Inst{3-0} = 0b1111;
bits<4> Rn;
bits<4> addr;
bits<4> Rt;
let Inst{19-16} = Rn;
let Inst{19-16} = addr;
let Inst{15-12} = Rt;
}
class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz,
@ -2837,37 +2846,37 @@ class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz,
let Inst{5-4} = opcod;
bits<4> Rd;
bits<4> Rn;
bits<4> addr;
bits<4> Rt;
let Inst{11-8} = Rd;
let Inst{19-16} = Rn;
let Inst{3-0} = Rd;
let Inst{19-16} = addr;
let Inst{15-12} = Rt;
}
let mayLoad = 1 in {
def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins rGPR:$Rn), AddrModeNone,
Size4Bytes, NoItinerary, "ldrexb", "\t$Rt, [$Rn]",
def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone,
Size4Bytes, NoItinerary, "ldrexb", "\t$Rt, $addr",
"", []>;
def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins rGPR:$Rn), AddrModeNone,
Size4Bytes, NoItinerary, "ldrexh", "\t$Rt, [$Rn]",
def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone,
Size4Bytes, NoItinerary, "ldrexh", "\t$Rt, $addr",
"", []>;
def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins rGPR:$Rn), AddrModeNone,
def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone,
Size4Bytes, NoItinerary,
"ldrex", "\t$Rt, [$Rn]", "",
"ldrex", "\t$Rt, $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> Rn;
bits<4> Rt;
let Inst{19-16} = Rn;
bits<4> addr;
let Inst{19-16} = addr;
let Inst{15-12} = Rt;
}
def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins rGPR:$Rn),
def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins t2addrmode_reg:$addr),
AddrModeNone, Size4Bytes, NoItinerary,
"ldrexd", "\t$Rt, $Rt2, [$Rn]", "",
"ldrexd", "\t$Rt, $Rt2, $addr", "",
[], {?, ?, ?, ?}> {
bits<4> Rt2;
let Inst{11-8} = Rt2;
@ -2875,31 +2884,31 @@ def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins rGPR:$Rn),
}
let mayStore = 1, Constraints = "@earlyclobber $Rd" in {
def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd), (ins rGPR:$Rt, rGPR:$Rn),
AddrModeNone, Size4Bytes, NoItinerary,
"strexb", "\t$Rd, $Rt, [$Rn]", "", []>;
def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), (ins rGPR:$Rt, rGPR:$Rn),
AddrModeNone, Size4Bytes, NoItinerary,
"strexh", "\t$Rd, $Rt, [$Rn]", "", []>;
def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, rGPR:$Rn),
AddrModeNone, Size4Bytes, NoItinerary,
"strex", "\t$Rd, $Rt, [$Rn]", "",
[]> {
def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr),
AddrModeNone, Size4Bytes, NoItinerary,
"strexb", "\t$Rd, $Rt, $addr", "", []>;
def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr),
AddrModeNone, Size4Bytes, NoItinerary,
"strexh", "\t$Rd, $Rt, $addr", "", []>;
def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr),
AddrModeNone, Size4Bytes, NoItinerary,
"strex", "\t$Rd, $Rt, $addr", "",
[]> {
let Inst{31-27} = 0b11101;
let Inst{26-20} = 0b0000100;
let Inst{7-0} = 0b00000000; // imm8 = 0
bits<4> Rd;
bits<4> Rn;
bits<4> addr;
bits<4> Rt;
let Inst{11-8} = Rd;
let Inst{19-16} = Rn;
let Inst{19-16} = addr;
let Inst{15-12} = Rt;
}
def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd),
(ins rGPR:$Rt, rGPR:$Rt2, rGPR:$Rn),
(ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_reg:$addr),
AddrModeNone, Size4Bytes, NoItinerary,
"strexd", "\t$Rd, $Rt, $Rt2, [$Rn]", "", [],
"strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [],
{?, ?, ?, ?}> {
bits<4> Rt2;
let Inst{11-8} = Rt2;

View File

@ -350,6 +350,23 @@ public:
int64_t Value = CE->getValue();
return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
}
bool isMemMode7() const {
if (!isMemory() ||
getMemPreindexed() ||
getMemPostindexed() ||
getMemOffsetIsReg() ||
getMemNegative() ||
getMemWriteback())
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
if (!CE) return false;
if (CE->getValue())
return false;
return true;
}
bool isMemModeRegThumb() const {
if (!isMemory() || !getMemOffsetIsReg() || getMemWriteback())
return false;
@ -438,6 +455,15 @@ public:
Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
}
void addMemMode7Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && isMemMode7() && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
assert((CE || CE->getValue() == 0) &&
"No offset operand support in mode 7");
}
void addMemMode5Operands(MCInst &Inst, unsigned N) const {
assert(N == 2 && isMemMode5() && "Invalid number of operands!");

View File

@ -317,6 +317,12 @@ void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
O << "]";
}
void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &MO1 = MI->getOperand(OpNum);
O << "[" << getRegisterName(MO1.getReg()) << "]";
}
void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
unsigned OpNum,
raw_ostream &O) {

View File

@ -51,6 +51,7 @@ public:
void printLdStmModeOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode6Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode7Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode6OffsetOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O);

View File

@ -284,3 +284,28 @@
@ CHECK: add r1, r2, r3, lsl r4 @ encoding: [0x13,0x14,0x82,0xe0]
add r1, r2, r3, lsl r4
@ CHECK: strexb r0, r1, [r2] @ encoding: [0x91,0x0f,0xc2,0xe1]
strexb r0, r1, [r2]
@ CHECK: strexh r0, r1, [r2] @ encoding: [0x91,0x0f,0xe2,0xe1]
strexh r0, r1, [r2]
@ CHECK: strex r0, r1, [r2] @ encoding: [0x91,0x0f,0x82,0xe1]
strex r0, r1, [r2]
@ CHECK: strexd r0, r2, r3, [r1] @ encoding: [0x92,0x0f,0xa1,0xe1]
strexd r0, r2, r3, [r1]
@ CHECK: ldrexb r0, [r0] @ encoding: [0x9f,0x0f,0xd0,0xe1]
ldrexb r0, [r0]
@ CHECK: ldrexh r0, [r0] @ encoding: [0x9f,0x0f,0xf0,0xe1]
ldrexh r0, [r0]
@ CHECK: ldrex r0, [r0] @ encoding: [0x9f,0x0f,0x90,0xe1]
ldrex r0, [r0]
@ CHECK: ldrexd r0, r1, [r0] @ encoding: [0x9f,0x0f,0xb0,0xe1]
ldrexd r0, r1, [r0]

View File

@ -284,3 +284,19 @@
@ CHECK: msr cpsr_fsxc, r0 @ encoding: [0x80,0xf3,0x00,0x8f]
msr cpsr_fsxc, r0
@ CHECK: strexb r0, r1, [r2] @ encoding: [0xc2,0xe8,0x40,0x1f]
strexb r0, r1, [r2]
@ CHECK: strexh r0, r1, [r2] @ encoding: [0xc2,0xe8,0x50,0x1f]
strexh r0, r1, [r2]
@ CHECK: strex r0, r1, [r2] @ encoding: [0x42,0xe8,0x00,0x10]
strex r0, r1, [r2]
@ CHECK: strexd r0, r2, r3, [r1] @ encoding: [0xc1,0xe8,0x70,0x23]
strexd r0, r2, r3, [r1]
@ CHECK: ldrexb r0, [r0] @ encoding: [0xd0,0xe8,0x4f,0x0f]
ldrexb r0, [r0]
@ CHECK: ldrexh r0, [r0] @ encoding: [0xd0,0xe8,0x5f,0x0f]
ldrexh r0, [r0]
@ CHECK: ldrex r0, [r0] @ encoding: [0x50,0xe8,0x00,0x0f]
ldrex r0, [r0]
@ CHECK: ldrexd r0, r1, [r0] @ encoding: [0xd0,0xe8,0x7f,0x01]
ldrexd r0, r1, [r0]

View File

@ -637,10 +637,12 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I
MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I
MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I
MISC("addrmode7", "kOperandTypeARMAddrMode7"); // R
MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ...
MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ...
MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ...
MISC("it_mask", "kOperandTypeThumbITMask"); // I
MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R
MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I
@ -858,6 +860,7 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
operandTypes.addEntry("kOperandTypeARMAddrMode5");
operandTypes.addEntry("kOperandTypeARMAddrMode6");
operandTypes.addEntry("kOperandTypeARMAddrMode6Offset");
operandTypes.addEntry("kOperandTypeARMAddrMode7");
operandTypes.addEntry("kOperandTypeARMAddrModePC");
operandTypes.addEntry("kOperandTypeARMRegisterList");
operandTypes.addEntry("kOperandTypeARMDPRRegisterList");
@ -869,6 +872,7 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
operandTypes.addEntry("kOperandTypeThumbAddrModeRR");
operandTypes.addEntry("kOperandTypeThumbAddrModeSP");
operandTypes.addEntry("kOperandTypeThumbAddrModePC");
operandTypes.addEntry("kOperandTypeThumb2AddrModeReg");
operandTypes.addEntry("kOperandTypeThumb2SoReg");
operandTypes.addEntry("kOperandTypeThumb2SoImm");
operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8");