diff options
| author | Jim Grosbach <grosbach@apple.com> | 2010-10-12 23:53:58 +0000 |
|---|---|---|
| committer | Jim Grosbach <grosbach@apple.com> | 2010-10-12 23:53:58 +0000 |
| commit | ef324d704425a372aeba5fc91bee4d81635121f3 (patch) | |
| tree | 3c34b65cac73ef0e4b0624fa10bd785299ab1766 | |
| parent | 8f9145b0eb54f9b054733cfb88c2439893e404ae (diff) | |
| download | external_llvm-ef324d704425a372aeba5fc91bee4d81635121f3.zip external_llvm-ef324d704425a372aeba5fc91bee4d81635121f3.tar.gz external_llvm-ef324d704425a372aeba5fc91bee4d81635121f3.tar.bz2 | |
Add the rest of the ARM so_reg encoding options (register shifted register)
and move to a custom operand encoder. Remove the last of the special handling
stuff from ARMMCCodeEmitter::EncodeInstruction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116377 91177308-0d34-0410-b5e6-96231b3b80d8
| -rw-r--r-- | lib/Target/ARM/ARMCodeEmitter.cpp | 2 | ||||
| -rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 11 | ||||
| -rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 92 |
3 files changed, 82 insertions, 23 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index a50872b..d49a79d 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -168,6 +168,8 @@ namespace { const { return 0; } unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } /// getMovi32Value - Return binary encoding of operand for movw/movt. If the /// machine operand requires relocation, record the relocation and return diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index fe9094d..78eb071 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -313,6 +313,7 @@ def shift_imm : Operand<i32> { def so_reg : Operand<i32>, // reg reg imm ComplexPattern<i32, 3, "SelectShifterOperandReg", [shl,srl,sra,rotr]> { + string EncoderMethod = "getSORegOpValue"; let PrintMethod = "printSORegOperand"; let MIOperandInfo = (ops GPR, GPR, i32imm); } @@ -498,14 +499,14 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc, let Inst{15-12} = Rd; let Inst{19-16} = Rn; } - def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, - iis, opc, "\t$dst, $a, $b", - [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]> { + def rs : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm, + iis, opc, "\t$Rd, $Rn, $shift", + [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> { bits<4> Rd; bits<4> Rn; - bits<4> Rm; + bits<12> shift; let Inst{25} = 0; - let Inst{3-0} = Rm; + let Inst{11-0} = shift; let Inst{15-12} = Rd; let Inst{19-16} = Rn; } diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 8bb8b26..6d9a459 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -55,6 +55,7 @@ public: // '1' respectively. return MI.getOperand(Op).getReg() == ARM::CPSR; } + /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value. unsigned getSOImmOpValue(const MCInst &MI, unsigned Op) const { unsigned SoImm = MI.getOperand(Op).getImm(); @@ -70,6 +71,9 @@ public: return Binary; } + /// getSORegOpValue - Return an encoded so_reg shifted register value. + unsigned getSORegOpValue(const MCInst &MI, unsigned Op) const; + unsigned getNumFixupKinds() const { assert(0 && "ARMMCCodeEmitter::getNumFixupKinds() not yet implemented."); return 0; @@ -137,6 +141,76 @@ unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI, return 0; } + +unsigned ARMMCCodeEmitter::getSORegOpValue(const MCInst &MI, + unsigned OpIdx) 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: + // {7} = 0 + // {11-8} = Rs + // else (imm shift) + // {11-7} = imm + + const MCOperand &MO = MI.getOperand(OpIdx); + const MCOperand &MO1 = MI.getOperand(OpIdx + 1); + const MCOperand &MO2 = MI.getOperand(OpIdx + 2); + ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm()); + + // Encode Rm. + unsigned Binary = getARMRegisterNumbering(MO.getReg()); + + // Encode the shift opcode. + unsigned SBits = 0; + unsigned Rs = MO1.getReg(); + if (Rs) { + // Set shift operand (bit[7:4]). + // LSL - 0001 + // 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 shift_imm bit[11:7]. + return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7; +} + void ARMMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const { @@ -151,27 +225,9 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, return; ++MCNumEmitted; // Keep track of the # of mi's emitted - // FIXME: TableGen doesn't deal well with operands that expand to multiple - // machine instruction operands, so for now we'll fix those up here. - // Similarly, operands that are encoded as other than their literal - // values in the MI. unsigned Value = getBinaryCodeForInstr(MI); switch (Opcode) { default: break; - case ARM::ADDrs: - case ARM::ANDrs: - case ARM::BICrs: - case ARM::EORrs: - case ARM::ORRrs: - case ARM::SUBrs: { - // The so_reg operand needs the shift ammount encoded. - unsigned ShVal = MI.getOperand(4).getImm(); - unsigned ShType = ARM_AM::getShiftOpcEncoding(ARM_AM::getSORegShOp(ShVal)); - unsigned ShAmt = ARM_AM::getSORegOffset(ShVal); - Value |= ShType << ARMII::ShiftTypeShift; - Value |= ShAmt << ARMII::ShiftShift; - break; - } } EmitConstant(Value, 4, CurByte, OS); } |
