diff options
Diffstat (limited to 'llvm/lib/Target/ARM/ARMCodeEmitter.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/ARMCodeEmitter.cpp | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index b39ab7f833d..29a8f31a514 100644 --- a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -122,6 +122,8 @@ namespace { void emitVFPArithInstruction(const MachineInstr &MI); + void emitVFPConversionInstruction(const MachineInstr &MI); + /// getBinaryCodeForInstr - This function, generated by the /// CodeEmitterGenerator using TableGen, produces the binary encoding for /// machine instructions. @@ -320,6 +322,10 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { case ARMII::VFPBinaryFrm: emitVFPArithInstruction(MI); break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + emitVFPConversionInstruction(MI); + break; } } @@ -999,7 +1005,7 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { // Encode Dd / Sd. unsigned RegD = getMachineOpValue(MI, OpIdx++); - Binary |= (RegD & 0x0f) << ARMII::RegFdShift; + Binary |= (RegD & 0x0f) << ARMII::RegRdShift; Binary |= (RegD & 0x10) << ARMII::D_BitShift; // If this is a two-address operand, skip it, e.g. FMACD. @@ -1009,7 +1015,7 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { // Encode Dn / Sn. if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) { unsigned RegN = getMachineOpValue(MI, OpIdx++); - Binary |= (RegN & 0x0f); + Binary |= (RegN & 0x0f) << ARMII::RegRnShift; Binary |= (RegN & 0x10) << ARMII::N_BitShift; } @@ -1021,4 +1027,41 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { emitWordLE(Binary); } +void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Dd / Sd. + unsigned RegD = getMachineOpValue(MI, OpIdx++); + Binary |= (RegD & 0x0f) << ARMII::RegRdShift; + Binary |= (RegD & 0x10) << ARMII::D_BitShift; + + // Encode Dn / Sn. + if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPConv1Frm) { + unsigned RegN = getMachineOpValue(MI, OpIdx++); + Binary |= (RegN & 0x0f) << ARMII::RegRnShift; + Binary |= (RegN & 0x10) << ARMII::N_BitShift; + + // FMRS / FMSR do not have Rm. + if (!TID.OpInfo[2].isPredicate()) { + unsigned RegM = getMachineOpValue(MI, OpIdx++); + Binary |= (RegM & 0x0f); + Binary |= (RegM & 0x10) << ARMII::M_BitShift; + } + } else { + unsigned RegM = getMachineOpValue(MI, OpIdx++); + Binary |= (RegM & 0x0f); + Binary |= (RegM & 0x10) << ARMII::M_BitShift; + } + + emitWordLE(Binary); +} + #include "ARMGenCodeEmitter.inc" |