kOperandTypeARMAddrMode5,
kOperandTypeARMAddrMode6,
kOperandTypeARMAddrMode6Offset,
+ kOperandTypeARMAddrMode7,
kOperandTypeARMAddrModePC,
kOperandTypeARMRegisterList,
kOperandTypeARMTBAddrMode,
kOperandTypeThumb2AddrModeImm12,
kOperandTypeThumb2AddrModeSoReg,
kOperandTypeThumb2AddrModeImm8s4,
- kOperandTypeThumb2AddrModeImm8s4Offset
+ kOperandTypeThumb2AddrModeImm8s4Offset,
+ kOperandTypeThumb2AddrModeReg
};
enum OperandFlags {
case kOperandTypeThumb2AddrModeImm8Offset:
case kOperandTypeARMTBAddrMode:
case kOperandTypeThumb2AddrModeImm8s4Offset:
+ case kOperandTypeARMAddrMode7:
+ case kOperandTypeThumb2AddrModeReg:
numMCOperands = 1;
break;
case kOperandTypeThumb2SoReg:
case kOperandTypeARMAddrMode4:
case kOperandTypeARMAddrMode5:
case kOperandTypeARMAddrMode6:
+ case kOperandTypeARMAddrMode7:
case kOperandTypeARMAddrModePC:
case kOperandTypeARMBranchTarget:
case kOperandTypeThumbAddrModeS1:
case kOperandTypeThumb2AddrModeImm12:
case kOperandTypeThumb2AddrModeSoReg:
case kOperandTypeThumb2AddrModeImm8s4:
+ case kOperandTypeThumb2AddrModeReg:
return 1;
}
}
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;
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";
}
}
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.
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...
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,
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;
}
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;
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;
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!");
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) {
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);
@ 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]
+
@ 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]
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
operandTypes.addEntry("kOperandTypeARMAddrMode5");
operandTypes.addEntry("kOperandTypeARMAddrMode6");
operandTypes.addEntry("kOperandTypeARMAddrMode6Offset");
+ operandTypes.addEntry("kOperandTypeARMAddrMode7");
operandTypes.addEntry("kOperandTypeARMAddrModePC");
operandTypes.addEntry("kOperandTypeARMRegisterList");
operandTypes.addEntry("kOperandTypeARMDPRRegisterList");
operandTypes.addEntry("kOperandTypeThumbAddrModeRR");
operandTypes.addEntry("kOperandTypeThumbAddrModeSP");
operandTypes.addEntry("kOperandTypeThumbAddrModePC");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeReg");
operandTypes.addEntry("kOperandTypeThumb2SoReg");
operandTypes.addEntry("kOperandTypeThumb2SoImm");
operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8");