summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td26
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp24
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassembler.cpp18
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp16
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.h2
-rw-r--r--test/MC/ARM/basic-thumb2-instructions.s18
-rw-r--r--utils/TableGen/EDEmitter.cpp2
7 files changed, 102 insertions, 4 deletions
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index dacd29f1a0..ac6ef7af59 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -203,6 +203,20 @@ def t2addrmode_so_reg : Operand<i32>,
let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
}
+// Addresses for the TBB/TBH instructions.
+def addrmode_tbb_asmoperand : AsmOperandClass { let Name = "MemTBB"; }
+def addrmode_tbb : Operand<i32> {
+ let PrintMethod = "printAddrModeTBB";
+ let ParserMatchClass = addrmode_tbb_asmoperand;
+ let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm);
+}
+def addrmode_tbh_asmoperand : AsmOperandClass { let Name = "MemTBH"; }
+def addrmode_tbh : Operand<i32> {
+ let PrintMethod = "printAddrModeTBH";
+ let ParserMatchClass = addrmode_tbh_asmoperand;
+ let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm);
+}
+
//===----------------------------------------------------------------------===//
// Multiclass helpers...
//
@@ -3135,8 +3149,8 @@ def t2TBB_JT : t2PseudoInst<(outs),
def t2TBH_JT : t2PseudoInst<(outs),
(ins GPR:$index, i32imm:$jt, i32imm:$id), 0, IIC_Br, []>;
-def t2TBB : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
- "tbb", "\t[$Rn, $Rm]", []> {
+def t2TBB : T2I<(outs), (ins addrmode_tbb:$addr), IIC_Br,
+ "tbb", "\t$addr", []> {
bits<4> Rn;
bits<4> Rm;
let Inst{31-20} = 0b111010001101;
@@ -3144,10 +3158,12 @@ def t2TBB : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
let Inst{15-5} = 0b11110000000;
let Inst{4} = 0; // B form
let Inst{3-0} = Rm;
+
+ let DecoderMethod = "DecodeThumbTableBranch";
}
-def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
- "tbh", "\t[$Rn, $Rm, lsl #1]", []> {
+def t2TBH : T2I<(outs), (ins addrmode_tbh:$addr), IIC_Br,
+ "tbh", "\t$addr", []> {
bits<4> Rn;
bits<4> Rm;
let Inst{31-20} = 0b111010001101;
@@ -3155,6 +3171,8 @@ def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
let Inst{15-5} = 0b11110000000;
let Inst{4} = 1; // H form
let Inst{3-0} = Rm;
+
+ let DecoderMethod = "DecodeThumbTableBranch";
}
} // isNotDuplicable, isIndirectBranch
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 46b0589cc5..ce3f747f2f 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -687,6 +687,18 @@ public:
return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Val == INT32_MIN;
}
+ bool isMemTBB() const {
+ if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
+ Mem.ShiftType != ARM_AM::no_shift)
+ return false;
+ return true;
+ }
+ bool isMemTBH() const {
+ if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
+ Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm != 1)
+ return false;
+ return true;
+ }
bool isMemRegOffset() const {
if (Kind != Memory || !Mem.OffsetRegNum)
return false;
@@ -1205,6 +1217,18 @@ public:
Inst.addOperand(MCOperand::CreateImm(Val));
}
+ void addMemTBBOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
+ }
+
+ void addMemTBHOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
+ }
+
void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
assert(N == 3 && "Invalid number of operands!");
unsigned Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add,
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 6cbe863d0e..dea38bf00a 100644
--- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -287,6 +287,8 @@ static DecodeStatus DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbTableBranch(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
@@ -2899,6 +2901,22 @@ static DecodeStatus DecodeCoprocessor(llvm::MCInst &Inst, unsigned Val,
}
static DecodeStatus
+DecodeThumbTableBranch(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+
+ if (Rn == ARM::SP) S = MCDisassembler::SoftFail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ return S;
+}
+
+static DecodeStatus
DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 0cae477627..5bbd19fd75 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -307,6 +307,22 @@ void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
<< " #" << ShImm;
}
+void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(Op);
+ const MCOperand &MO2 = MI->getOperand(Op+1);
+ O << "[" << getRegisterName(MO1.getReg()) << ", "
+ << getRegisterName(MO2.getReg()) << "]";
+}
+
+void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(Op);
+ const MCOperand &MO2 = MI->getOperand(Op+1);
+ O << "[" << getRegisterName(MO1.getReg()) << ", "
+ << getRegisterName(MO2.getReg()) << ", lsl #1]";
+}
+
void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
raw_ostream &O) {
const MCOperand &MO1 = MI->getOperand(Op);
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
index a411e92f3b..4f18958e5c 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
@@ -41,6 +41,8 @@ public:
void printSORegRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printSORegImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printAddrModeTBB(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printAddrModeTBH(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAM2PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,
diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s
index 2551d846b1..5de471551c 100644
--- a/test/MC/ARM/basic-thumb2-instructions.s
+++ b/test/MC/ARM/basic-thumb2-instructions.s
@@ -2615,6 +2615,24 @@ _func:
@------------------------------------------------------------------------------
+@ TBB/TBH
+@------------------------------------------------------------------------------
+ tbb [r3, r8]
+ tbh [r3, r8, lsl #1]
+ it eq
+ tbbeq [r3, r8]
+ it cs
+ tbhcs [r3, r8, lsl #1]
+
+@ CHECK: tbb [r3, r8] @ encoding: [0xd3,0xe8,0x08,0xf0]
+@ CHECK: tbh [r3, r8, lsl #1] @ encoding: [0xd3,0xe8,0x18,0xf0]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: tbbeq [r3, r8] @ encoding: [0xd3,0xe8,0x08,0xf0]
+@ CHECK: it hs @ encoding: [0x28,0xbf]
+@ CHECK: tbhhs [r3, r8, lsl #1] @ encoding: [0xd3,0xe8,0x18,0xf0]
+
+
+@------------------------------------------------------------------------------
@ TEQ
@------------------------------------------------------------------------------
teq r5, #0xf000
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 1974a8af48..9a0039f33b 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -686,6 +686,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R
MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I
MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I
+ MISC("addrmode_tbb", "kOperandTypeThumbAddrModeRR"); // R, R
+ MISC("addrmode_tbh", "kOperandTypeThumbAddrModeRR"); // R, R
return 1;
}