From: Evan Cheng Date: Tue, 11 Nov 2008 22:46:12 +0000 (+0000) Subject: Fix FMDRR encoding. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=0a0ab1387a3923769990e91cce8e098366c4a920;p=oota-llvm.git Fix FMDRR encoding. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59088 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 08372cefd61..7e1e8046faf 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -342,6 +342,7 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { break; case ARMII::VFPConv1Frm: case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: emitVFPConversionInstruction(MI); break; case ARMII::VFPLdStFrm: @@ -1080,27 +1081,41 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << ARMII::CondShift; - unsigned OpIdx = 0; + // FMDRR encodes registers in reverse order. + unsigned Form = TID.TSFlags & ARMII::FormMask; + unsigned OpIdx = (Form == ARMII::VFPConv2Frm) ? 2 : 0; // Encode Dd / Sd. - unsigned RegD = getMachineOpValue(MI, OpIdx++); + unsigned RegD = getMachineOpValue(MI, OpIdx); Binary |= (RegD & 0x0f) << ARMII::RegRdShift; Binary |= (RegD & 0x10) << ARMII::D_BitShift; + if (Form == ARMII::VFPConv2Frm) + --OpIdx; + else + ++OpIdx; // Encode Dn / Sn. - if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPConv1Frm) { - unsigned RegN = getMachineOpValue(MI, OpIdx++); + 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; // FMRS / FMSR do not have Rm. - if (!TID.OpInfo[2].isPredicate()) { - unsigned RegM = getMachineOpValue(MI, OpIdx++); + 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); } } else { - unsigned RegM = getMachineOpValue(MI, OpIdx++); + assert(Form == ARMII::VFPConv3Frm && "Unsupported format!"); + unsigned RegM = getMachineOpValue(MI, OpIdx); Binary |= (RegM & 0x0f); Binary |= (RegM & 0x10) << ARMII::M_BitShift; } diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index b59af13cd9e..1db0838d07b 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -41,11 +41,12 @@ def VFPUnaryFrm : Format<15>; def VFPBinaryFrm : Format<16>; def VFPConv1Frm : Format<17>; def VFPConv2Frm : Format<18>; -def VFPLdStFrm : Format<19>; -def VFPLdStMulFrm : Format<20>; -def VFPMiscFrm : Format<21>; +def VFPConv3Frm : Format<19>; +def VFPLdStFrm : Format<20>; +def VFPLdStMulFrm : Format<21>; +def VFPMiscFrm : Format<22>; -def ThumbFrm : Format<22>; +def ThumbFrm : Format<23>; // Misc flag for data processing instructions that indicates whether // the instruction has a Rn register operand. @@ -827,9 +828,17 @@ class AVConv1I opcod1, bits<4> opcod2, dag oops, dag iops, string opc, let Inst{4} = 1; } -class AVConv2I opcod1, bits<4> opcod2, bits<4> opcod3, +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; +} + +class AVConv3I opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops, string opc, string asm, list pattern> - : AI { + : AI { let Inst{27-20} = opcod1; let Inst{19-16} = opcod2; let Inst{11-8} = opcod3; diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index c77a6288f6f..1da9678c03e 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -105,12 +105,13 @@ namespace ARMII { VFPBinaryFrm = 16 << FormShift, VFPConv1Frm = 17 << FormShift, VFPConv2Frm = 18 << FormShift, - VFPLdStFrm = 19 << FormShift, - VFPLdStMulFrm = 20 << FormShift, - VFPMiscFrm = 21 << FormShift, + VFPConv3Frm = 19 << FormShift, + VFPLdStFrm = 20 << FormShift, + VFPLdStMulFrm = 21 << FormShift, + VFPMiscFrm = 22 << FormShift, // Thumb format - ThumbFrm = 22 << FormShift, + ThumbFrm = 23 << FormShift, //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 442c12abcb9..7409eb0decd 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -235,7 +235,7 @@ def FMRRD : AVConv1I<0b11000101, 0b1011, // FMDHR: GPR -> SPR // FMDLR: GPR -> SPR -def FMDRR : AVConv1I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2), +def FMDRR : AVConv2I<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 : AVConv1I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$s // Int to FP: -def FSITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), +def FSITOD : AVConv3I<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 : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), +def FSITOS : AVConv3I<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 : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), +def FUITOD : AVConv3I<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 : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), +def FUITOS : AVConv3I<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 : AVConv2I<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 : AVConv2I<0b11101011, 0b1101, 0b1011, +def FTOSIZD : AVConv3I<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 : AVConv2I<0b11101011, 0b1101, 0b1010, +def FTOSIZS : AVConv3I<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 : AVConv2I<0b11101011, 0b1100, 0b1011, +def FTOUIZD : AVConv3I<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 : AVConv2I<0b11101011, 0b1100, 0b1010, +def FTOUIZS : AVConv3I<0b11101011, 0b1100, 0b1010, (outs SPR:$dst), (ins SPR:$a), "ftouizs", " $dst, $a", [(set SPR:$dst, (arm_ftoui SPR:$a))]> {