diff options
author | Owen Anderson <resistor@mac.com> | 2011-07-21 23:38:37 +0000 |
---|---|---|
committer | Owen Anderson <resistor@mac.com> | 2011-07-21 23:38:37 +0000 |
commit | 152d4a4bb6b75de740b4b8a9f48abb9069d50c17 (patch) | |
tree | 75a3b965a0f354f467e1d6e4b4930deaad0530e8 /lib | |
parent | 856e13ddace4174ad1b07f65ebb18b2fd835ed57 (diff) | |
download | external_llvm-152d4a4bb6b75de740b4b8a9f48abb9069d50c17.zip external_llvm-152d4a4bb6b75de740b4b8a9f48abb9069d50c17.tar.gz external_llvm-152d4a4bb6b75de740b4b8a9f48abb9069d50c17.tar.bz2 |
Get rid of the extraneous GPR operand on so_reg_imm operands, which in turn necessitates a lot of changes to related bits.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135722 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM/ARMCodeEmitter.cpp | 4 | ||||
-rw-r--r-- | lib/Target/ARM/ARMExpandPseudoInsts.cpp | 23 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 20 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 3 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 86 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 77 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 6 | ||||
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp | 70 | ||||
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassemblerCore.h | 5 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 59 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 3 |
11 files changed, 258 insertions, 98 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 818c5ac..61a49a8 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -195,7 +195,9 @@ namespace { const { return 0; } unsigned getT2SOImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } - unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op) + unsigned getSORegRegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getSORegImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getThumbAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 3c760f8..d400ceb 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -741,9 +741,22 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } - case ARM::MOVCCsi: + case ARM::MOVCCsi: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi), + (MI.getOperand(1).getReg())) + .addReg(MI.getOperand(2).getReg(), + getKillRegState(MI.getOperand(2).isKill())) + .addImm(MI.getOperand(3).getImm()) + .addImm(MI.getOperand(4).getImm()) // 'pred' + .addReg(MI.getOperand(5).getReg()) + .addReg(0); // 's' bit + + MI.eraseFromParent(); + return true; + } + case ARM::MOVCCsr: { - BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsr), (MI.getOperand(1).getReg())) .addReg(MI.getOperand(2).getReg(), getKillRegState(MI.getOperand(2).isKill())) @@ -838,10 +851,9 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, case ARM::MOVsrl_flag: case ARM::MOVsra_flag: { // These are just fancy MOVs insructions. - AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi), MI.getOperand(0).getReg()) .addOperand(MI.getOperand(1)) - .addReg(0) .addImm(ARM_AM::getSORegOpc((Opcode == ARM::MOVsrl_flag ? ARM_AM::lsr : ARM_AM::asr), 1))) @@ -852,10 +864,9 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, case ARM::RRX: { // This encodes as "MOVs Rd, Rm, rrx MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi), MI.getOperand(0).getReg()) .addOperand(MI.getOperand(1)) - .addOperand(MI.getOperand(1)) .addImm(ARM_AM::getSORegOpc(ARM_AM::rrx, 0))) .addReg(0); TransferImpOps(MI, MIB, MIB); diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index ea30597..467b082 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -94,16 +94,16 @@ public: SDValue &B, SDValue &C, bool CheckProfitability = true); bool SelectImmShifterOperand(SDValue N, SDValue &A, - SDValue &B, SDValue &C, - bool CheckProfitability = true); - bool SelectShiftShifterOperandReg(SDValue N, SDValue &A, + SDValue &B, bool CheckProfitability = true); + bool SelectShiftRegShifterOperand(SDValue N, SDValue &A, SDValue &B, SDValue &C) { // Don't apply the profitability check - if (SelectImmShifterOperand(N, A, B, C, false)) - return true; - else if (SelectRegShifterOperand(N, A, B, C, false)) - return true; - return false; + return SelectRegShifterOperand(N, A, B, C, false); + } + bool SelectShiftImmShifterOperand(SDValue N, SDValue &A, + SDValue &B) { + // Don't apply the profitability check + return SelectImmShifterOperand(N, A, B, false); } bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); @@ -374,7 +374,6 @@ bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift, bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N, SDValue &BaseReg, - SDValue &ShReg, SDValue &Opc, bool CheckProfitability) { if (DisableShifterOp) @@ -390,7 +389,6 @@ bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N, unsigned ShImmVal = 0; ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); if (!RHS) return false; - ShReg = CurDAG->getRegister(0, MVT::i32); ShImmVal = RHS->getZExtValue() & 31; Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), MVT::i32); @@ -2067,7 +2065,7 @@ SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, SDValue CPTmp0; SDValue CPTmp1; SDValue CPTmp2; - if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) { + if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp2)) { SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 7); diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 3b0e17f..e673fe7 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -25,7 +25,7 @@ def BrFrm : Format<2>; def BrMiscFrm : Format<3>; def DPFrm : Format<4>; -def DPSoRegFrm : Format<5>; +def DPSoRegRegFrm : Format<5>; def LdFrm : Format<6>; def StFrm : Format<7>; @@ -68,6 +68,7 @@ def N3RegVShFrm : Format<38>; def NVExtFrm : Format<39>; def NVMulSLFrm : Format<40>; def NVTBLFrm : Format<41>; +def DPSoRegImmFrm : Format<42>; // Misc flags. diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 2c26ae0..faf74a2 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -431,30 +431,40 @@ def ShiftedImmAsmOperand : AsmOperandClass { def so_reg_reg : Operand<i32>, // reg reg imm ComplexPattern<i32, 3, "SelectRegShifterOperand", [shl, srl, sra, rotr]> { - let EncoderMethod = "getSORegOpValue"; - let PrintMethod = "printSORegOperand"; + let EncoderMethod = "getSORegRegOpValue"; + let PrintMethod = "printSORegRegOperand"; let ParserMatchClass = ShiftedRegAsmOperand; let MIOperandInfo = (ops GPR, GPR, shift_imm); } def so_reg_imm : Operand<i32>, // reg imm - ComplexPattern<i32, 3, "SelectImmShifterOperand", + ComplexPattern<i32, 2, "SelectImmShifterOperand", [shl, srl, sra, rotr]> { - let EncoderMethod = "getSORegOpValue"; - let PrintMethod = "printSORegOperand"; + let EncoderMethod = "getSORegImmOpValue"; + let PrintMethod = "printSORegImmOperand"; let ParserMatchClass = ShiftedImmAsmOperand; - let MIOperandInfo = (ops GPR, GPR, shift_imm); + let MIOperandInfo = (ops GPR, shift_imm); } // FIXME: Does this need to be distinct from so_reg? -def shift_so_reg : Operand<i32>, // reg reg imm - ComplexPattern<i32, 3, "SelectShiftShifterOperandReg", +def shift_so_reg_reg : Operand<i32>, // reg reg imm + ComplexPattern<i32, 3, "SelectShiftRegShifterOperand", [shl,srl,sra,rotr]> { - let EncoderMethod = "getSORegOpValue"; - let PrintMethod = "printSORegOperand"; + let EncoderMethod = "getSORegRegOpValue"; + let PrintMethod = "printSORegRegOperand"; let MIOperandInfo = (ops GPR, GPR, shift_imm); } +// FIXME: Does this need to be distinct from so_reg? +def shift_so_reg_imm : Operand<i32>, // reg reg imm + ComplexPattern<i32, 2, "SelectShiftImmShifterOperand", + [shl,srl,sra,rotr]> { + let EncoderMethod = "getSORegImmOpValue"; + let PrintMethod = "printSORegImmOperand"; + let MIOperandInfo = (ops GPR, shift_imm); +} + + // so_imm - Match a 32-bit shifter_operand immediate operand, which is an // 8-bit immediate rotated by an arbitrary number of bits. def SOImmAsmOperand: AsmOperandClass { let Name = "ARMSOImm"; } @@ -772,7 +782,7 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc, } def rsi : AsI1<opcod, (outs GPR:$Rd), - (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegFrm, + (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis, opc, "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]> { bits<4> Rd; @@ -787,7 +797,7 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc, } def rsr : AsI1<opcod, (outs GPR:$Rd), - (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegFrm, + (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis, opc, "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]> { bits<4> Rd; @@ -861,7 +871,7 @@ multiclass AI1_bin_s_irs<bits<4> opcod, string opc, let Inst{3-0} = Rm; } def rsi : AI1<opcod, (outs GPR:$Rd), - (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegFrm, + (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis, opc, "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]> { bits<4> Rd; @@ -877,7 +887,7 @@ multiclass AI1_bin_s_irs<bits<4> opcod, string opc, } def rsr : AI1<opcod, (outs GPR:$Rd), - (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegFrm, + (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis, opc, "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]> { bits<4> Rd; @@ -928,7 +938,7 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc, let Inst{3-0} = Rm; } def rsi : AI1<opcod, (outs), - (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegFrm, iis, + (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis, opc, "\t$Rn, $shift", [(opnode GPR:$Rn, so_reg_imm:$shift)]> { bits<4> Rn; @@ -942,7 +952,7 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc, let Inst{3-0} = shift{3-0}; } def rsr : AI1<opcod, (outs), - (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegFrm, iis, + (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis, opc, "\t$Rn, $shift", [(opnode GPR:$Rn, so_reg_reg:$shift)]> { bits<4> Rn; @@ -1094,7 +1104,7 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode, } def rsi : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift), - DPSoRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift", + DPSoRegImmFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]>, Requires<[IsARM]> { bits<4> Rd; @@ -1109,7 +1119,7 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode, } def rsr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift), - DPSoRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift", + DPSoRegRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]>, Requires<[IsARM]> { bits<4> Rd; @@ -2215,18 +2225,38 @@ def MOVr_TC : AsI1<0b1101, (outs tcGPR:$Rd), (ins tcGPR:$Rm), DPFrm, let Inst{15-12} = Rd; } -def MOVs : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg:$src), - DPSoRegFrm, IIC_iMOVsr, - "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg:$src)]>, +def MOVsr : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg_reg:$src), + DPSoRegRegFrm, IIC_iMOVsr, + "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg_reg:$src)]>, UnaryDP { bits<4> Rd; bits<12> src; let Inst{15-12} = Rd; let Inst{19-16} = 0b0000; - let Inst{11-0} = src; + let Inst{11-8} = src{11-8}; + let Inst{7} = 0; + let Inst{6-5} = src{6-5}; + let Inst{4} = 1; + let Inst{3-0} = src{3-0}; let Inst{25} = 0; } +def MOVsi : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg_imm:$src), + DPSoRegImmFrm, IIC_iMOVsr, + "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg_imm:$src)]>, + UnaryDP { + bits<4> Rd; + bits<12> src; + let Inst{15-12} = Rd; + let Inst{19-16} = 0b0000; + let Inst{11-5} = src{11-5}; + let Inst{4} = 0; + let Inst{3-0} = src{3-0}; + let Inst{25} = 0; +} + + + let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi, "mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP { @@ -2450,7 +2480,7 @@ def RSBrr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, } def RSBrsi : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift), - DPSoRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift", + DPSoRegImmFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (sub so_reg_imm:$shift, GPR:$Rn))]> { bits<4> Rd; bits<4> Rn; @@ -2464,7 +2494,7 @@ def RSBrsi : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift), } def RSBrsr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift), - DPSoRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift", + DPSoRegRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (sub so_reg_reg:$shift, GPR:$Rn))]> { bits<4> Rd; bits<4> Rn; @@ -2524,7 +2554,7 @@ def RSCrr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), let Inst{19-16} = Rn; } def RSCrsi : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift), - DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift", + DPSoRegImmFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (sube_dead_carry so_reg_imm:$shift, GPR:$Rn))]>, Requires<[IsARM]> { bits<4> Rd; @@ -2538,7 +2568,7 @@ def RSCrsi : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift), let Inst{3-0} = shift{3-0}; } def RSCrsr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift), - DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift", + DPSoRegRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift", [(set GPR:$Rd, (sube_dead_carry so_reg_reg:$shift, GPR:$Rn))]>, Requires<[IsARM]> { bits<4> Rd; @@ -2838,7 +2868,7 @@ def MVNr : AsI1<0b1111, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMVNr, let Inst{15-12} = Rd; let Inst{3-0} = Rm; } -def MVNsi : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_imm:$shift), DPSoRegFrm, +def MVNsi : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_imm:$shift), DPSoRegImmFrm, IIC_iMVNsr, "mvn", "\t$Rd, $shift", [(set GPR:$Rd, (not so_reg_imm:$shift))]>, UnaryDP { bits<4> Rd; @@ -2850,7 +2880,7 @@ def MVNsi : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_imm:$shift), DPSoRegFrm, let Inst{4} = 0; let Inst{3-0} = shift{3-0}; } -def MVNsr : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_reg:$shift), DPSoRegFrm, +def MVNsr : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_reg:$shift), DPSoRegRegFrm, IIC_iMVNsr, "mvn", "\t$Rd, $shift", [(set GPR:$Rd, (not so_reg_reg:$shift))]>, UnaryDP { bits<4> Rd; diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index b76ad7b..43eb5e3 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -251,7 +251,9 @@ public: SmallVectorImpl<MCFixup> &Fixups) const; /// getSORegOpValue - Return an encoded so_reg shifted register value. - unsigned getSORegOpValue(const MCInst &MI, unsigned Op, + unsigned getSORegRegOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getSORegImmOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const; unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const; @@ -934,7 +936,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, } unsigned ARMMCCodeEmitter:: -getSORegOpValue(const MCInst &MI, unsigned OpIdx, +getSORegRegOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const { // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be // shifted. The second is either Rs, the amount to shift by, or reg0 in which @@ -966,45 +968,72 @@ getSORegOpValue(const MCInst &MI, unsigned OpIdx, // LSR - 0011 // ASR - 0101 // ROR - 0111 - // RRX - 0110 and bit[11:8] clear. switch (SOpc) { default: llvm_unreachable("Unknown shift opc!"); case ARM_AM::lsl: SBits = 0x1; break; case ARM_AM::lsr: SBits = 0x3; break; case ARM_AM::asr: SBits = 0x5; break; case ARM_AM::ror: SBits = 0x7; break; - case ARM_AM::rrx: SBits = 0x6; break; - } - } else { - // 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 the shift operation Rs or shift_imm (except rrx). - if (Rs) { - // Encode Rs bit[11:8]. - assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); - return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift); + // Encode Rs bit[11:8]. + assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); + return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift); +} + +unsigned ARMMCCodeEmitter:: +getSORegImmOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const { + // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be + // shifted. The second is either Rs, the amount to shift by, or reg0 in which + // case the imm contains the amount to shift by. + // + // {3-0} = Rm. + // {4} = 1 if reg shift, 0 if imm shift + // {6-5} = type + // If reg shift: + // {11-8} = Rs + // {7} = 0 + // else (imm shift) + // {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 + // RRX - 110 and bit[11:8] clear. + 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; + case ARM_AM::rrx: + Binary |= 0x60; + return Binary; } // Encode shift_imm bit[11:7]. - return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7; + Binary |= SBits << 4; + return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7; } + unsigned ARMMCCodeEmitter:: getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups) const { diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 827ad0f..fd8f815 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -626,13 +626,9 @@ public: } void addShiftedImmOperands(MCInst &Inst, unsigned N) const { - assert(N == 3 && "Invalid number of operands!"); + assert(N == 2 && "Invalid number of operands!"); assert(isShiftedImm() && "addShiftedImmOperands() on non ShiftedImm!"); Inst.addOperand(MCOperand::CreateReg(ShiftedImm.SrcReg)); - if (ShiftedImm.ShiftTy == ARM_AM::rrx) - Inst.addOperand(MCOperand::CreateReg(ShiftedImm.SrcReg)); - else - Inst.addOperand(MCOperand::CreateReg(0)); Inst.addOperand(MCOperand::CreateImm( ARM_AM::getSORegOpc(ShiftedImm.ShiftTy, ShiftedImm.ShiftImm))); } diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index d40a9f7..40e4812 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -1090,7 +1090,7 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } -static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, +static bool DisassembleDPSoRegRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { const MCInstrDesc &MCID = ARMInsts[Opcode]; @@ -1180,6 +1180,69 @@ static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } +static bool DisassembleDPSoRegImmFrm(MCInst &MI, unsigned Opcode, uint32_t insn, + unsigned short NumOps, unsigned &NumOpsAdded, BO B) { + + const MCInstrDesc &MCID = ARMInsts[Opcode]; + unsigned short NumDefs = MCID.getNumDefs(); + bool isUnary = isUnaryDP(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; + unsigned &OpIdx = NumOpsAdded; + + OpIdx = 0; + + // Disassemble register def if there is one. + if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) { + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + decodeRd(insn)))); + ++OpIdx; + } + + // Disassemble the src operands. + if (OpIdx >= NumOps) + return false; + + // BinaryDP has an Rn operand. + if (!isUnary) { + assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && + "Reg operand expected"); + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + decodeRn(insn)))); + ++OpIdx; + } + + // If this is a two-address operand, skip it, e.g., MOVCCs operand 1. + if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { + MI.addOperand(MCOperand::CreateReg(0)); + ++OpIdx; + } + + // Disassemble operand 2, which consists of two components. + if (OpIdx + 1 >= NumOps) + return false; + + assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) && + (OpInfo[OpIdx+1].RegClass < 0) && + "Expect 2 reg operands"); + + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + decodeRm(insn)))); + + // Inst{6-5} encodes the shift opcode. + ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5)); + // Inst{11-7} encodes the imm5 shift amount. + unsigned ShImm = slice(insn, 11, 7); + + // A8.4.1. Possible rrx or shift amount of 32... + getImmShiftSE(ShOp, ShImm); + MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm))); + + OpIdx += 2; + + return true; +} + + static bool BadRegsLdStFrm(unsigned Opcode, uint32_t insn, bool Store, bool WBack, bool Imm) { const StringRef Name = ARMInsts[Opcode].Name; @@ -3484,7 +3547,7 @@ static const DisassembleFP FuncPtrs[] = { &DisassembleBrFrm, &DisassembleBrMiscFrm, &DisassembleDPFrm, - &DisassembleDPSoRegFrm, + &DisassembleDPSoRegRegFrm, &DisassembleLdFrm, &DisassembleStFrm, &DisassembleLdMiscFrm, @@ -3552,6 +3615,9 @@ static const DisassembleFP FuncPtrs[] = { // values in a table and generate a new vector. &DisassembleNVTBLFrm, + &DisassembleDPSoRegImmFrm, + + NULL }; diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h index a7ba141..c1ebd3e 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h @@ -51,7 +51,7 @@ public: ENTRY(ARM_FORMAT_BRFRM, 2) \ ENTRY(ARM_FORMAT_BRMISCFRM, 3) \ ENTRY(ARM_FORMAT_DPFRM, 4) \ - ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \ + ENTRY(ARM_FORMAT_DPSOREGREGFRM, 5) \ ENTRY(ARM_FORMAT_LDFRM, 6) \ ENTRY(ARM_FORMAT_STFRM, 7) \ ENTRY(ARM_FORMAT_LDMISCFRM, 8) \ @@ -87,7 +87,8 @@ public: ENTRY(ARM_FORMAT_N3RegVecSh, 38) \ ENTRY(ARM_FORMAT_NVecExtract, 39) \ ENTRY(ARM_FORMAT_NVecMulScalar, 40) \ - ENTRY(ARM_FORMAT_NVTBL, 41) + ENTRY(ARM_FORMAT_NVTBL, 41) \ + ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42) // ARM instruction format specifies the encoding used by the instruction. #define ENTRY(n, v) n = v, diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index fc12d46..e50f3b2 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -37,7 +37,7 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { unsigned Opcode = MI->getOpcode(); // Check for MOVs and print canonical forms, instead. - if (Opcode == ARM::MOVs) { + if (Opcode == ARM::MOVsr) { // FIXME: Thumb variants? const MCOperand &Dst = MI->getOperand(0); const MCOperand &MO1 = MI->getOperand(1); @@ -51,20 +51,32 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { O << '\t' << getRegisterName(Dst.getReg()) << ", " << getRegisterName(MO1.getReg()); - if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx) - return; + O << ", " << getRegisterName(MO2.getReg()); + assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); + return; + } - O << ", "; + if (Opcode == ARM::MOVsi) { + // FIXME: Thumb variants? + const MCOperand &Dst = MI->getOperand(0); + const MCOperand &MO1 = MI->getOperand(1); + const MCOperand &MO2 = MI->getOperand(2); - if (MO2.getReg()) { - O << getRegisterName(MO2.getReg()); - assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); - } else { - O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); - } + O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm())); + printSBitModifierOperand(MI, 5, O); + printPredicateOperand(MI, 3, O); + + O << '\t' << getRegisterName(Dst.getReg()) + << ", " << getRegisterName(MO1.getReg()); + + if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) + return; + + O << ", #" << ARM_AM::getSORegOffset(MO2.getImm()); return; } + // A8.6.123 PUSH if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) && MI->getOperand(0).getReg() == ARM::SP) { @@ -154,7 +166,7 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, // REG 0 0 - e.g. R5 // REG REG 0,SH_OPC - e.g. R5, ROR R3 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3 -void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, +void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -167,14 +179,27 @@ void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, O << ", " << ARM_AM::getShiftOpcStr(ShOpc); if (ShOpc == ARM_AM::rrx) return; - if (MO2.getReg()) { - O << ' ' << getRegisterName(MO2.getReg()); - assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); - } else if (ShOpc != ARM_AM::rrx) { - O << " #" << ARM_AM::getSORegOffset(MO3.getImm()); - } + + O << ' ' << getRegisterName(MO2.getReg()); + assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); } +void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + + O << getRegisterName(MO1.getReg()); + + // Print the shift opc. + ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); + O << ", " << ARM_AM::getShiftOpcStr(ShOpc); + if (ShOpc == ARM_AM::rrx) + return; + O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); +} + + //===--------------------------------------------------------------------===// // Addressing Mode #2 //===--------------------------------------------------------------------===// diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index 8f31729..bb225f2 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -38,7 +38,8 @@ public: void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); - void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printSORegRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printSORegImmOperand(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); |