diff options
author | Jim Grosbach <grosbach@apple.com> | 2011-09-19 22:21:13 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2011-09-19 22:21:13 +0000 |
commit | 7f739bee261debdf56bd89ac922b57eca53e91dc (patch) | |
tree | fe5281737d5a141000592658edc67fe7e5512ac3 | |
parent | 463158fdb89001d398520cfc1cbb5f1384623dd8 (diff) |
Thumb2 assembly parsing and encoding for TBB/TBH.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140078 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 26 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 24 | ||||
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 18 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 16 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 2 | ||||
-rw-r--r-- | test/MC/ARM/basic-thumb2-instructions.s | 18 | ||||
-rw-r--r-- | utils/TableGen/EDEmitter.cpp | 2 |
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; } |