diff --git a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index d6d98148818f..e36f0e1cb785 100644 --- a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -347,6 +347,8 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { case ARMII::VFPConv1Frm: case ARMII::VFPConv2Frm: case ARMII::VFPConv3Frm: + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: emitVFPConversionInstruction(MI); break; case ARMII::VFPLdStFrm: @@ -1095,22 +1097,9 @@ 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; - - // FMDRR encodes registers in reverse order. - unsigned Form = TID.TSFlags & ARMII::FormMask; - unsigned OpIdx = (Form == ARMII::VFPConv2Frm) - ? MI.findFirstPredOperandIdx()-1 : 0; - - // Encode Dd / Sd. +static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) { unsigned RegD = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; bool isSPVFP = false; RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP); if (!isSPVFP) @@ -1119,29 +1108,13 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; Binary |= (RegD & 0x01) << ARMII::D_BitShift; } - if (Form == ARMII::VFPConv2Frm) - --OpIdx; - else - ++OpIdx; + return Binary; +} - 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. +static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) { unsigned RegN = MI.getOperand(OpIdx).getReg(); - isSPVFP = false; + unsigned Binary = 0; + bool isSPVFP = false; RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP); if (!isSPVFP) Binary |= RegN << ARMII::RegRnShift; @@ -1149,23 +1122,74 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; Binary |= (RegN & 0x01) << ARMII::N_BitShift; } - if (Form == ARMII::VFPConv2Frm) - --OpIdx; - else - ++OpIdx; + return Binary; +} - // 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; - } +static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegM = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = false; + RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP); + if (!isSPVFP) + Binary |= RegM; + else { + Binary |= ((RegM & 0x1E) >> 1); + Binary |= (RegM & 0x01) << ARMII::M_BitShift; } + return Binary; +} + +void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 0); + break; + case ARMII::VFPConv4Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 0); + break; + case ARMII::VFPConv5Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 0); + break; + } + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 1); + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 1); + break; + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 1); + break; + } + + if (Form == ARMII::VFPConv5Frm) + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 2); + else if (Form == ARMII::VFPConv3Frm) + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 2); emitWordLE(Binary); } diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 1db0838d07b8..6ca931d69390 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -42,11 +42,13 @@ def VFPBinaryFrm : Format<16>; def VFPConv1Frm : Format<17>; def VFPConv2Frm : Format<18>; def VFPConv3Frm : Format<19>; -def VFPLdStFrm : Format<20>; -def VFPLdStMulFrm : Format<21>; -def VFPMiscFrm : Format<22>; +def VFPConv4Frm : Format<20>; +def VFPConv5Frm : Format<21>; +def VFPLdStFrm : Format<22>; +def VFPLdStMulFrm : Format<23>; +def VFPMiscFrm : Format<24>; -def ThumbFrm : Format<23>; +def ThumbFrm : Format<25>; // Misc flag for data processing instructions that indicates whether // the instruction has a Rn register operand. @@ -820,30 +822,39 @@ class ASbI opcod, dag oops, dag iops, string opc, let Inst{11-8} = 0b1010; } -class AVConv1I opcod1, bits<4> opcod2, dag oops, dag iops, string opc, - string asm, list pattern> +// VFP conversion instructions +class AVConv1I opcod1, bits<4> opcod2, bits<4> opcod3, + dag oops, dag iops, string opc, string asm, list pattern> : AI { let Inst{27-20} = opcod1; + let Inst{19-16} = opcod2; + let Inst{11-8} = opcod3; + let Inst{6} = 1; +} + +class AVConvXI opcod1, bits<4> opcod2, dag oops, dag iops, Format f, + string opc, string asm, list pattern> + : AI { + let Inst{27-20} = opcod1; let Inst{11-8} = opcod2; let Inst{4} = 1; } class AVConv2I opcod1, bits<4> opcod2, dag oops, dag iops, string opc, - string asm, list pattern> - : AI { - let Inst{27-20} = opcod1; - let Inst{11-8} = opcod2; - let Inst{4} = 1; -} + string asm, list pattern> + : AVConvXI; -class AVConv3I opcod1, bits<4> opcod2, bits<4> opcod3, - dag oops, dag iops, string opc, string asm, list pattern> - : AI { - let Inst{27-20} = opcod1; - let Inst{19-16} = opcod2; - let Inst{11-8} = opcod3; - let Inst{6} = 1; -} +class AVConv3I opcod1, bits<4> opcod2, dag oops, dag iops, string opc, + string asm, list pattern> + : AVConvXI; + +class AVConv4I opcod1, bits<4> opcod2, dag oops, dag iops, string opc, + string asm, list pattern> + : AVConvXI; + +class AVConv5I opcod1, bits<4> opcod2, dag oops, dag iops, string opc, + string asm, list pattern> + : AVConvXI; //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.h b/llvm/lib/Target/ARM/ARMInstrInfo.h index 1da9678c03ec..d9ee5fcc9954 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.h +++ b/llvm/lib/Target/ARM/ARMInstrInfo.h @@ -106,12 +106,14 @@ namespace ARMII { VFPConv1Frm = 17 << FormShift, VFPConv2Frm = 18 << FormShift, VFPConv3Frm = 19 << FormShift, - VFPLdStFrm = 20 << FormShift, - VFPLdStMulFrm = 21 << FormShift, - VFPMiscFrm = 22 << FormShift, + VFPConv4Frm = 20 << FormShift, + VFPConv5Frm = 21 << FormShift, + VFPLdStFrm = 22 << FormShift, + VFPLdStMulFrm = 23 << FormShift, + VFPMiscFrm = 24 << FormShift, // Thumb format - ThumbFrm = 23 << FormShift, + ThumbFrm = 25 << FormShift, //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating diff --git a/llvm/lib/Target/ARM/ARMInstrVFP.td b/llvm/lib/Target/ARM/ARMInstrVFP.td index b4e665c3f525..5c5b9e28f9bc 100644 --- a/llvm/lib/Target/ARM/ARMInstrVFP.td +++ b/llvm/lib/Target/ARM/ARMInstrVFP.td @@ -219,15 +219,15 @@ def FSQRTS : ASuI<0b11101011, 0b0001, 0b1100, (outs SPR:$dst), (ins SPR:$a), // FP <-> GPR Copies. Int <-> FP Conversions. // -def FMRS : AVConv1I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src), +def FMRS : AVConv2I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src), "fmrs", " $dst, $src", [(set GPR:$dst, (bitconvert SPR:$src))]>; -def FMSR : AVConv2I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src), +def FMSR : AVConv4I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src), "fmsr", " $dst, $src", [(set SPR:$dst, (bitconvert GPR:$src))]>; -def FMRRD : AVConv1I<0b11000101, 0b1011, +def FMRRD : AVConv3I<0b11000101, 0b1011, (outs GPR:$dst1, GPR:$dst2), (ins DPR:$src), "fmrrd", " $dst1, $dst2, $src", [/* FIXME: Can't write pattern for multiple result instr*/]>; @@ -235,7 +235,7 @@ def FMRRD : AVConv1I<0b11000101, 0b1011, // FMDHR: GPR -> SPR // FMDLR: GPR -> SPR -def FMDRR : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2), +def FMDRR : AVConv5I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2), "fmdrr", " $dst, $src1, $src2", [(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>; @@ -251,25 +251,25 @@ def FMDRR : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$s // Int to FP: -def FSITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), +def FSITOD : AVConv1I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), "fsitod", " $dst, $a", [(set DPR:$dst, (arm_sitof SPR:$a))]> { let Inst{7} = 1; // Z bit } -def FSITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), +def FSITOS : AVConv1I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), "fsitos", " $dst, $a", [(set SPR:$dst, (arm_sitof SPR:$a))]> { let Inst{7} = 1; // Z bit } -def FUITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), +def FUITOD : AVConv1I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), "fuitod", " $dst, $a", [(set DPR:$dst, (arm_uitof SPR:$a))]> { let Inst{7} = 0; // Z bit } -def FUITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), +def FUITOS : AVConv1I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), "fuitos", " $dst, $a", [(set SPR:$dst, (arm_uitof SPR:$a))]> { let Inst{7} = 1; // Z bit @@ -278,28 +278,28 @@ def FUITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), // FP to Int: // Always set Z bit in the instruction, i.e. "round towards zero" variants. -def FTOSIZD : AVConv3I<0b11101011, 0b1101, 0b1011, +def FTOSIZD : AVConv1I<0b11101011, 0b1101, 0b1011, (outs SPR:$dst), (ins DPR:$a), "ftosizd", " $dst, $a", [(set SPR:$dst, (arm_ftosi DPR:$a))]> { let Inst{7} = 1; // Z bit } -def FTOSIZS : AVConv3I<0b11101011, 0b1101, 0b1010, +def FTOSIZS : AVConv1I<0b11101011, 0b1101, 0b1010, (outs SPR:$dst), (ins SPR:$a), "ftosizs", " $dst, $a", [(set SPR:$dst, (arm_ftosi SPR:$a))]> { let Inst{7} = 1; // Z bit } -def FTOUIZD : AVConv3I<0b11101011, 0b1100, 0b1011, +def FTOUIZD : AVConv1I<0b11101011, 0b1100, 0b1011, (outs SPR:$dst), (ins DPR:$a), "ftouizd", " $dst, $a", [(set SPR:$dst, (arm_ftoui DPR:$a))]> { let Inst{7} = 1; // Z bit } -def FTOUIZS : AVConv3I<0b11101011, 0b1100, 0b1010, +def FTOUIZS : AVConv1I<0b11101011, 0b1100, 0b1010, (outs SPR:$dst), (ins SPR:$a), "ftouizs", " $dst, $a", [(set SPR:$dst, (arm_ftoui SPR:$a))]> {