diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index b068c64f63e..bc486066d2c 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -173,8 +173,12 @@ namespace { const { return 0; } unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getT2SOImmOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op) diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 6569664414f..3854b683184 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -31,6 +31,7 @@ def tb_addrmode : Operand { def t2_so_reg : Operand, // reg imm ComplexPattern { + string EncoderMethod = "getT2SORegOpValue"; let PrintMethod = "printT2SOOperand"; let MIOperandInfo = (ops rGPR, i32imm); } @@ -51,7 +52,9 @@ def t2_so_imm_neg_XFORM : SDNodeXForm, PatLeaf<(imm), [{ return Pred_t2_so_imm(N); }]>; +def t2_so_imm : Operand, PatLeaf<(imm), [{ return Pred_t2_so_imm(N); }]> { + string EncoderMethod = "getT2SOImmOpValue"; +} // t2_so_imm_not - Match an immediate that is a complement // of a t2_so_imm. @@ -167,6 +170,47 @@ def t2addrmode_so_reg : Operand, // Multiclass helpers... // +class T2TwoRegShiftedImm pattern> + : T2sI { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + + let Inst{11-8} = Rd{3-0}; + let Inst{19-16} = Rn{3-0}; + let Inst{26} = imm{11}; + let Inst{14-12} = imm{10-8}; + let Inst{7-0} = imm{7-0}; +} + +class T2ThreeReg pattern> + : T2sI { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + + let Inst{11-8} = Rd{3-0}; + let Inst{19-16} = Rn{3-0}; + let Inst{3-0} = Rm{3-0}; +} + +class T2TwoRegShiftedReg pattern> + : T2sI { + bits<4> Rd; + bits<4> Rn; + bits<12> ShiftedRm; + + let Inst{11-8} = Rd{3-0}; + let Inst{19-16} = Rn{3-0}; + let Inst{3-0} = ShiftedRm{3-0}; + let Inst{5-4} = ShiftedRm{6-5}; + let Inst{14-12} = ShiftedRm{11-9}; + let Inst{7-6} = ShiftedRm{8-7}; +} + /// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a /// unary operation that produces a value. These are predicable and can be /// changed to modify CPSR. @@ -399,9 +443,9 @@ let Uses = [CPSR] in { multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Commutable = 0> { // shifted imm - def ri : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, - opc, "\t$dst, $lhs, $rhs", - [(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_imm:$rhs))]>, + def ri : T2TwoRegShiftedImm<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), + IIC_iALUi, opc, "\t$Rd, $Rn, $imm", + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>, Requires<[IsThumb2]> { let Inst{31-27} = 0b11110; let Inst{25} = 0; @@ -410,9 +454,9 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, let Inst{15} = 0; } // register - def rr : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, rGPR:$rhs), IIC_iALUr, - opc, ".w\t$dst, $lhs, $rhs", - [(set rGPR:$dst, (opnode rGPR:$lhs, rGPR:$rhs))]>, + def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr, + opc, ".w\t$Rd, $Rn, $Rm", + [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>, Requires<[IsThumb2]> { let isCommutable = Commutable; let Inst{31-27} = 0b11101; @@ -424,9 +468,10 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, let Inst{5-4} = 0b00; // type } // shifted register - def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, - opc, ".w\t$dst, $lhs, $rhs", - [(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_reg:$rhs))]>, + def rs : T2TwoRegShiftedReg< + (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), + IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm", + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>, Requires<[IsThumb2]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; @@ -440,9 +485,10 @@ let Defs = [CPSR] in { multiclass T2I_adde_sube_s_irs opcod, string opc, PatFrag opnode, bit Commutable = 0> { // shifted imm - def ri : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, - opc, "\t$dst, $lhs, $rhs", - [(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_imm:$rhs))]>, + def ri : T2TwoRegShiftedImm< + (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi, + opc, "\t$Rd, $Rn, $imm", + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>, Requires<[IsThumb2]> { let Inst{31-27} = 0b11110; let Inst{25} = 0; @@ -451,9 +497,9 @@ multiclass T2I_adde_sube_s_irs opcod, string opc, PatFrag opnode, let Inst{15} = 0; } // register - def rr : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, rGPR:$rhs), IIC_iALUr, - opc, ".w\t$dst, $lhs, $rhs", - [(set rGPR:$dst, (opnode rGPR:$lhs, rGPR:$rhs))]>, + def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr, + opc, ".w\t$Rd, $Rn, $Rm", + [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>, Requires<[IsThumb2]> { let isCommutable = Commutable; let Inst{31-27} = 0b11101; @@ -465,9 +511,10 @@ multiclass T2I_adde_sube_s_irs opcod, string opc, PatFrag opnode, let Inst{5-4} = 0b00; // type } // shifted register - def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, - opc, ".w\t$dst, $lhs, $rhs", - [(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_reg:$rhs))]>, + def rs : T2TwoRegShiftedReg< + (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), + IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm", + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>, Requires<[IsThumb2]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 96da945f604..0b896edef53 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -136,10 +136,21 @@ public: Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); return Binary; } + + /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value. + unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + unsigned SoImm = MI.getOperand(Op).getImm(); + unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm); + assert(Encoded != ~0U && "Not a Thumb2 so_imm value?"); + return Encoded; + } /// getSORegOpValue - Return an encoded so_reg shifted register value. unsigned getSORegOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const; + unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; unsigned getRotImmOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const { @@ -548,6 +559,47 @@ getSORegOpValue(const MCInst &MI, unsigned OpIdx, return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7; } +unsigned ARMMCCodeEmitter:: +getT2SORegOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const { + // Sub-operands are [reg, imm]. The first register is Rm, the reg to be + // shifted. The second is the amount to shift by. + // + // {3-0} = Rm. + // {4} = 0 + // {6-5} = type + // {11-7} = imm + + const MCOperand &MO = MI.getOperand(OpIdx); + const MCOperand &MO1 = MI.getOperand(OpIdx + 1); + ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm()); + + // Encode Rm. + unsigned Binary = getARMRegisterNumbering(MO.getReg()); + + // Encode the shift opcode. + unsigned SBits = 0; + // Set shift operand (bit[6:4]). + // LSL - 000 + // LSR - 010 + // ASR - 100 + // ROR - 110 + switch (SOpc) { + default: llvm_unreachable("Unknown shift opc!"); + case ARM_AM::lsl: SBits = 0x0; break; + case ARM_AM::lsr: SBits = 0x2; break; + case ARM_AM::asr: SBits = 0x4; break; + case ARM_AM::ror: SBits = 0x6; break; + } + + Binary |= SBits << 4; + if (SOpc == ARM_AM::rrx) + return Binary; + + // Encode shift_imm bit[11:7]. + return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7; +} + unsigned ARMMCCodeEmitter:: getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const { diff --git a/test/MC/ARM/thumb2.s b/test/MC/ARM/thumb2.s new file mode 100644 index 00000000000..93c8472a236 --- /dev/null +++ b/test/MC/ARM/thumb2.s @@ -0,0 +1,14 @@ +@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s +@ XFAIL: * +.code 16 + +@ CHECK: adc r1, r1, #171 @ encoding: [0xab,0x01,0x41,0xf1] + adc r1, r1, #171 +@ CHECK: adc r1, r1, #1179666 @ encoding: [0x12,0x11,0x41,0xf1] + adc r1, r1, #1179666 +@ CHECK: adc r1, r1, #872428544 @ encoding: [0x34,0x21,0x41,0xf1] + adc r1, r1, #872428544 +@ CHECK: adc r1, r1, #1448498774 @ encoding: [0x56,0x31,0x41,0xf1] + adc r1, r1, #1448498774 +@ CHECK: adc r1, r1, #66846720 @ encoding: [0x7f,0x71,0x41,0xf1] + adc r1, r1, #66846720