From d06d48d2b593958a4822ef6f7f3f6b51d177124c Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 12 Nov 2008 02:19:38 +0000 Subject: [PATCH] Fix encoding of single-precision VFP registers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59102 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMCodeEmitter.cpp | 134 ++++++++++++++++++++--------- lib/Target/ARM/ARMInstrVFP.td | 2 +- lib/Target/ARM/ARMRegisterInfo.cpp | 74 ++++++++++++++++ lib/Target/ARM/ARMRegisterInfo.h | 4 + 4 files changed, 174 insertions(+), 40 deletions(-) diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 5b7bc97986e..d6d98148818 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -1053,9 +1053,16 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { (Binary & ARMII::M_BitShift) == 0 && "VFP encoding bug!"); // Encode Dd / Sd. - unsigned RegD = getMachineOpValue(MI, OpIdx++); - Binary |= (RegD & 0x0f) << ARMII::RegRdShift; - Binary |= (RegD & 0x10) << ARMII::D_BitShift; + unsigned RegD = MI.getOperand(OpIdx++).getReg(); + bool isSPVFP = false; + RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP); + if (!isSPVFP) + Binary |= RegD << ARMII::RegRdShift; + else { + Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; + Binary |= (RegD & 0x01) << ARMII::D_BitShift; + } + // If this is a two-address operand, skip it, e.g. FMACD. if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) @@ -1063,15 +1070,27 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { // Encode Dn / Sn. if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) { - unsigned RegN = getMachineOpValue(MI, OpIdx++); - Binary |= (RegN & 0x0f) << ARMII::RegRnShift; - Binary |= (RegN & 0x10) << ARMII::N_BitShift; + unsigned RegN = MI.getOperand(OpIdx++).getReg(); + isSPVFP = false; + RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP); + if (!isSPVFP) + Binary |= RegN << ARMII::RegRnShift; + else { + Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; + Binary |= (RegN & 0x01) << ARMII::N_BitShift; + } } // Encode Dm / Sm. - unsigned RegM = getMachineOpValue(MI, OpIdx++); - Binary |= (RegM & 0x0f); - Binary |= (RegM & 0x10) << ARMII::M_BitShift; + unsigned RegM = MI.getOperand(OpIdx++).getReg(); + isSPVFP = false; + RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP); + if (!isSPVFP) + Binary |= RegM; + else { + Binary |= ((RegM & 0x1E) >> 1); + Binary |= (RegM & 0x01) << ARMII::M_BitShift; + } emitWordLE(Binary); } @@ -1087,41 +1106,65 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { // FMDRR encodes registers in reverse order. unsigned Form = TID.TSFlags & ARMII::FormMask; - unsigned OpIdx = (Form == ARMII::VFPConv2Frm) ? 2 : 0; + unsigned OpIdx = (Form == ARMII::VFPConv2Frm) + ? MI.findFirstPredOperandIdx()-1 : 0; // Encode Dd / Sd. - unsigned RegD = getMachineOpValue(MI, OpIdx); - Binary |= (RegD & 0x0f) << ARMII::RegRdShift; - Binary |= (RegD & 0x10) << ARMII::D_BitShift; + unsigned RegD = MI.getOperand(OpIdx).getReg(); + bool isSPVFP = false; + RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP); + if (!isSPVFP) + Binary |= RegD << ARMII::RegRdShift; + else { + Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; + Binary |= (RegD & 0x01) << ARMII::D_BitShift; + } if (Form == ARMII::VFPConv2Frm) --OpIdx; else ++OpIdx; + if (Form == ARMII::VFPConv3Frm) { + unsigned RegM = MI.getOperand(OpIdx).getReg(); + isSPVFP = false; + RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP); + if (!isSPVFP) + Binary |= RegM; + else { + Binary |= ((RegM & 0x1E) >> 1); + Binary |= (RegM & 0x01) << ARMII::M_BitShift; + } + + emitWordLE(Binary); + return; + } + // Encode Dn / Sn. - if (Form == ARMII::VFPConv1Frm || Form == ARMII::VFPConv2Frm) { - unsigned RegN = getMachineOpValue(MI, OpIdx); - Binary |= (RegN & 0x0f) << ARMII::RegRnShift; - Binary |= (RegN & 0x10) << ARMII::N_BitShift; - if (Form == ARMII::VFPConv2Frm) - --OpIdx; - else - ++OpIdx; + unsigned RegN = MI.getOperand(OpIdx).getReg(); + isSPVFP = false; + RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP); + if (!isSPVFP) + Binary |= RegN << ARMII::RegRnShift; + else { + Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; + Binary |= (RegN & 0x01) << ARMII::N_BitShift; + } + if (Form == ARMII::VFPConv2Frm) + --OpIdx; + else + ++OpIdx; - // FMRS / FMSR do not have Rm. - if (TID.getNumOperands() > OpIdx && MI.getOperand(OpIdx).isReg()) { - unsigned RegM = getMachineOpValue(MI, OpIdx); - Binary |= (RegM & 0x0f); - Binary |= (RegM & 0x10) << ARMII::M_BitShift; - } else if (Form == ARMII::VFPConv2Frm) { - // FMDRR encodes definition register in Dm field. - Binary |= getMachineOpValue(MI, 0); + // FMRS / FMSR do not have Rm. + if (TID.getNumOperands() > OpIdx && MI.getOperand(OpIdx).isReg()) { + unsigned RegM = MI.getOperand(OpIdx).getReg(); + isSPVFP = false; + RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP); + if (!isSPVFP) + Binary |= RegM; + else { + Binary |= ((RegM & 0x1E) >> 1); + Binary |= (RegM & 0x01) << ARMII::M_BitShift; } - } else { - assert(Form == ARMII::VFPConv3Frm && "Unsupported format!"); - unsigned RegM = getMachineOpValue(MI, OpIdx); - Binary |= (RegM & 0x0f); - Binary |= (RegM & 0x10) << ARMII::M_BitShift; } emitWordLE(Binary); @@ -1137,9 +1180,15 @@ void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) { unsigned OpIdx = 0; // Encode Dd / Sd. - unsigned RegD = getMachineOpValue(MI, OpIdx++); - Binary |= (RegD & 0x0f) << ARMII::RegRdShift; - Binary |= (RegD & 0x10) << ARMII::D_BitShift; + unsigned RegD = MI.getOperand(OpIdx++).getReg(); + bool isSPVFP = false; + RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP); + if (!isSPVFP) + Binary |= RegD << ARMII::RegRdShift; + else { + Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; + Binary |= (RegD & 0x01) << ARMII::D_BitShift; + } // Encode address base. const MachineOperand &Base = MI.getOperand(OpIdx++); @@ -1184,8 +1233,15 @@ ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) { Binary |= 0x1 << ARMII::W_BitShift; // First register is encoded in Dd. - unsigned FirstReg = MI.getOperand(4).getReg(); - Binary |= ARMRegisterInfo::getRegisterNumbering(FirstReg)<< ARMII::RegRdShift; + unsigned RegD = MI.getOperand(4).getReg(); + bool isSPVFP = false; + RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP); + if (!isSPVFP) + Binary |= RegD << ARMII::RegRdShift; + else { + Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; + Binary |= (RegD & 0x01) << ARMII::D_BitShift; + } // Number of registers are encoded in offset field. unsigned NumRegs = 1; diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 7409eb0decd..b4e665c3f52 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -223,7 +223,7 @@ def FMRS : AVConv1I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src), "fmrs", " $dst, $src", [(set GPR:$dst, (bitconvert SPR:$src))]>; -def FMSR : AVConv1I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src), +def FMSR : AVConv2I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src), "fmsr", " $dst, $src", [(set SPR:$dst, (bitconvert GPR:$src))]>; diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index 2091899f008..b85daa13f5f 100644 --- a/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -81,6 +81,80 @@ unsigned ARMRegisterInfo::getRegisterNumbering(unsigned RegEnum) { } } +unsigned ARMRegisterInfo::getRegisterNumbering(unsigned RegEnum, + bool &isSPVFP) { + isSPVFP = false; + + using namespace ARM; + switch (RegEnum) { + default: + assert(0 && "Unknown ARM register!"); + abort(); + case R0: case D0: return 0; + case R1: case D1: return 1; + case R2: case D2: return 2; + case R3: case D3: return 3; + case R4: case D4: return 4; + case R5: case D5: return 5; + case R6: case D6: return 6; + case R7: case D7: return 7; + case R8: case D8: return 8; + case R9: case D9: return 9; + case R10: case D10: return 10; + case R11: case D11: return 11; + case R12: case D12: return 12; + case SP: case D13: return 13; + case LR: case D14: return 14; + case PC: case D15: return 15; + + case S0: case S1: case S2: case S3: + case S4: case S5: case S6: case S7: + case S8: case S9: case S10: case S11: + case S12: case S13: case S14: case S15: + case S16: case S17: case S18: case S19: + case S20: case S21: case S22: case S23: + case S24: case S25: case S26: case S27: + case S28: case S29: case S30: case S31: { + isSPVFP = true; + switch (RegEnum) { + default: return 0; // Avoid compile time warning. + case S0: return 0; + case S1: return 1; + case S2: return 2; + case S3: return 3; + case S4: return 4; + case S5: return 5; + case S6: return 6; + case S7: return 7; + case S8: return 8; + case S9: return 9; + case S10: return 10; + case S11: return 11; + case S12: return 12; + case S13: return 13; + case S14: return 14; + case S15: return 15; + case S16: return 16; + case S17: return 17; + case S18: return 18; + case S19: return 19; + case S20: return 20; + case S21: return 21; + case S22: return 22; + case S23: return 23; + case S24: return 24; + case S25: return 25; + case S26: return 26; + case S27: return 27; + case S28: return 28; + case S29: return 29; + case S30: return 30; + case S31: return 31; + } + } + } +} + ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii, const ARMSubtarget &sti) : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), diff --git a/lib/Target/ARM/ARMRegisterInfo.h b/lib/Target/ARM/ARMRegisterInfo.h index 5c75230cb12..bb4cb5b469d 100644 --- a/lib/Target/ARM/ARMRegisterInfo.h +++ b/lib/Target/ARM/ARMRegisterInfo.h @@ -44,6 +44,10 @@ public: /// ARM::LR, return the number that it corresponds to (e.g. 14). static unsigned getRegisterNumbering(unsigned RegEnum); + /// Same as previous getRegisterNumbering except it returns true in isSPVFP + /// if the register is a single precision VFP register. + static unsigned getRegisterNumbering(unsigned RegEnum, bool &isSPVFP); + /// Code Generation virtual methods... const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; -- 2.34.1