From ef324d704425a372aeba5fc91bee4d81635121f3 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Tue, 12 Oct 2010 23:53:58 +0000 Subject: [PATCH] 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 --- lib/Target/ARM/ARMCodeEmitter.cpp | 2 + lib/Target/ARM/ARMInstrInfo.td | 11 ++-- 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 a50872b06fc..d49a79d7f98 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 fe9094df05b..78eb0715970 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -313,6 +313,7 @@ def shift_imm : Operand { def so_reg : Operand, // reg reg imm ComplexPattern { + string EncoderMethod = "getSORegOpValue"; let PrintMethod = "printSORegOperand"; let MIOperandInfo = (ops GPR, GPR, i32imm); } @@ -498,14 +499,14 @@ multiclass AsI1_bin_irs opcod, string opc, let Inst{15-12} = Rd; let Inst{19-16} = Rn; } - def rs : AsI1 { + def rs : AsI1 { 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 8bb8b2616c8..6d9a45969d1 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 &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); } -- 2.34.1