diff options
author | Evan Cheng <evan.cheng@apple.com> | 2008-11-11 19:40:26 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2008-11-11 19:40:26 +0000 |
commit | 9d3cc18099051234d17dedbd15dfd486b89b9a25 (patch) | |
tree | ddab754451ba7f2aac4f46d983c8bf25f3033dd8 /lib | |
parent | dd00c153ba6c58a556f96688f64a26855b020465 (diff) | |
download | external_llvm-9d3cc18099051234d17dedbd15dfd486b89b9a25.zip external_llvm-9d3cc18099051234d17dedbd15dfd486b89b9a25.tar.gz external_llvm-9d3cc18099051234d17dedbd15dfd486b89b9a25.tar.bz2 |
Encode VFP conversion instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59074 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM/ARMCodeEmitter.cpp | 47 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 21 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.h | 8 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrVFP.td | 85 |
4 files changed, 126 insertions, 35 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index b39ab7f8..29a8f31 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/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" diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index c898aca..5efa76d 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -39,7 +39,9 @@ def ExtFrm : Format<14>; def VFPFrm : Format<15>; def VFPUnaryFrm : Format<16>; def VFPBinaryFrm: Format<17>; -def ThumbFrm : Format<18>; +def VFPConv1Frm : Format<18>; +def VFPConv2Frm : Format<19>; +def ThumbFrm : Format<20>; // Misc flag for data processing instructions that indicates whether // the instruction has a Rn register operand. @@ -798,6 +800,23 @@ class ASbI<bits<8> opcod, dag oops, dag iops, string opc, let Inst{11-8} = 0b1010; } +class AVConv1I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc, + string asm, list<dag> pattern> + : AI<oops, iops, VFPConv1Frm, opc, asm, pattern> { + let Inst{27-20} = opcod1; + let Inst{11-8} = opcod2; + let Inst{4} = 1; +} + +class AVConv2I<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3, + dag oops, dag iops, string opc, string asm, list<dag> pattern> + : AI<oops, iops, VFPConv1Frm, opc, asm, pattern> { + let Inst{27-20} = opcod1; + let Inst{19-16} = opcod2; + let Inst{11-8} = opcod3; + let Inst{6} = 1; +} + // Special cases. class AXSI<dag oops, dag iops, string asm, list<dag> pattern> : XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index 323e6e7..ccaeac5 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -70,7 +70,7 @@ namespace ARMII { // Instruction encoding formats. // FormShift = 10, - FormMask = 0xf << FormShift, + FormMask = 0x1f << FormShift, // Pseudo instructions Pseudo = 1 << FormShift, @@ -104,9 +104,11 @@ namespace ARMII { VPFFrm = 15 << FormShift, VFPUnaryFrm = 16 << FormShift, VFPBinaryFrm = 17 << FormShift, + VFPConv1Frm = 18 << FormShift, + VFPConv2Frm = 19 << FormShift, // Thumb format - ThumbFrm = 18 << FormShift, + ThumbFrm = 20 << FormShift, //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating @@ -119,10 +121,8 @@ namespace ARMII { ExtRotImmShift = 10, RegRdLoShift = 12, RegRdShift = 12, - RegFdShift = 12, RegRdHiShift = 16, RegRnShift = 16, - RegFnShift = 16, S_BitShift = 20, W_BitShift = 21, AM3_I_BitShift = 22, diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 5ba7094..2dc3f0b 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -211,23 +211,23 @@ def FSQRTS : ASuI<0b11101011, 0b0001, 0b1100, (outs SPR:$dst), (ins SPR:$a), // FP <-> GPR Copies. Int <-> FP Conversions. // -def FMRS : ASI<(outs GPR:$dst), (ins SPR:$src), +def FMRS : AVConv1I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src), "fmrs", " $dst, $src", [(set GPR:$dst, (bitconvert SPR:$src))]>; -def FMSR : ASI<(outs SPR:$dst), (ins GPR:$src), +def FMSR : AVConv1I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src), "fmsr", " $dst, $src", [(set SPR:$dst, (bitconvert GPR:$src))]>; - -def FMRRD : ADI<(outs GPR:$dst1, GPR:$dst2), (ins DPR:$src), +def FMRRD : AVConv1I<0b11000101, 0b1011, + (outs GPR:$dst1, GPR:$dst2), (ins DPR:$src), "fmrrd", " $dst1, $dst2, $src", [/* FIXME: Can't write pattern for multiple result instr*/]>; // FMDHR: GPR -> SPR // FMDLR: GPR -> SPR -def FMDRR : ADI<(outs DPR:$dst), (ins GPR:$src1, GPR:$src2), +def FMDRR : AVConv1I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2), "fmdrr", " $dst, $src1, $src2", [(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>; @@ -238,48 +238,65 @@ def FMDRR : ADI<(outs DPR:$dst), (ins GPR:$src1, GPR:$src2), // FMSRR: GPR -> SPR -let Defs = [CPSR] in -def FMSTAT : ASI<(outs), (ins), "fmstat", "", [(arm_fmstat)]>; - // FMXR: GPR -> VFP Sstem reg // Int to FP: -def FSITOD : ADI<(outs DPR:$dst), (ins SPR:$a), +def FSITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), "fsitod", " $dst, $a", - [(set DPR:$dst, (arm_sitof SPR:$a))]>; + [(set DPR:$dst, (arm_sitof SPR:$a))]> { + let Inst{7} = 1; // Z bit +} -def FSITOS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FSITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), "fsitos", " $dst, $a", - [(set SPR:$dst, (arm_sitof SPR:$a))]>; + [(set SPR:$dst, (arm_sitof SPR:$a))]> { + let Inst{7} = 1; // Z bit +} -def FUITOD : ADI<(outs DPR:$dst), (ins SPR:$a), +def FUITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), "fuitod", " $dst, $a", - [(set DPR:$dst, (arm_uitof SPR:$a))]>; + [(set DPR:$dst, (arm_uitof SPR:$a))]> { + let Inst{7} = 0; // Z bit +} -def FUITOS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FUITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), "fuitos", " $dst, $a", - [(set SPR:$dst, (arm_uitof SPR:$a))]>; + [(set SPR:$dst, (arm_uitof SPR:$a))]> { + let Inst{7} = 1; // Z bit +} // FP to Int: // Always set Z bit in the instruction, i.e. "round towards zero" variants. -def FTOSIZD : ADI<(outs SPR:$dst), (ins DPR:$a), +def FTOSIZD : AVConv2I<0b11101011, 0b1101, 0b1011, + (outs SPR:$dst), (ins DPR:$a), "ftosizd", " $dst, $a", - [(set SPR:$dst, (arm_ftosi DPR:$a))]>; + [(set SPR:$dst, (arm_ftosi DPR:$a))]> { + let Inst{7} = 1; // Z bit +} -def FTOSIZS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FTOSIZS : AVConv2I<0b11101011, 0b1101, 0b1010, + (outs SPR:$dst), (ins SPR:$a), "ftosizs", " $dst, $a", - [(set SPR:$dst, (arm_ftosi SPR:$a))]>; + [(set SPR:$dst, (arm_ftosi SPR:$a))]> { + let Inst{7} = 1; // Z bit +} -def FTOUIZD : ADI<(outs SPR:$dst), (ins DPR:$a), +def FTOUIZD : AVConv2I<0b11101011, 0b1100, 0b1011, + (outs SPR:$dst), (ins DPR:$a), "ftouizd", " $dst, $a", - [(set SPR:$dst, (arm_ftoui DPR:$a))]>; + [(set SPR:$dst, (arm_ftoui DPR:$a))]> { + let Inst{7} = 1; // Z bit +} -def FTOUIZS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FTOUIZS : AVConv2I<0b11101011, 0b1100, 0b1010, + (outs SPR:$dst), (ins SPR:$a), "ftouizs", " $dst, $a", - [(set SPR:$dst, (arm_ftoui SPR:$a))]>; + [(set SPR:$dst, (arm_ftoui SPR:$a))]> { + let Inst{7} = 1; // Z bit +} //===----------------------------------------------------------------------===// // FP FMA Operations. @@ -337,22 +354,34 @@ def FNMSCS : ASbI<0b11100001, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), // FP Conditional moves. // -def FCPYDcc : ADI<(outs DPR:$dst), (ins DPR:$false, DPR:$true), +def FCPYDcc : ADuI<0b11101011, 0b0000, 0b0100, + (outs DPR:$dst), (ins DPR:$false, DPR:$true), "fcpyd", " $dst, $true", [/*(set DPR:$dst, (ARMcmov DPR:$false, DPR:$true, imm:$cc))*/]>, RegConstraint<"$false = $dst">; -def FCPYScc : ASI<(outs SPR:$dst), (ins SPR:$false, SPR:$true), +def FCPYScc : ASuI<0b11101011, 0b0000, 0b0100, + (outs SPR:$dst), (ins SPR:$false, SPR:$true), "fcpys", " $dst, $true", [/*(set SPR:$dst, (ARMcmov SPR:$false, SPR:$true, imm:$cc))*/]>, RegConstraint<"$false = $dst">; -def FNEGDcc : ADI<(outs DPR:$dst), (ins DPR:$false, DPR:$true), +def FNEGDcc : ADuI<0b11101011, 0b0001, 0b0100, + (outs DPR:$dst), (ins DPR:$false, DPR:$true), "fnegd", " $dst, $true", [/*(set DPR:$dst, (ARMcneg DPR:$false, DPR:$true, imm:$cc))*/]>, RegConstraint<"$false = $dst">; -def FNEGScc : ASI<(outs SPR:$dst), (ins SPR:$false, SPR:$true), +def FNEGScc : ASuI<0b11101011, 0b0001, 0b0100, + (outs SPR:$dst), (ins SPR:$false, SPR:$true), "fnegs", " $dst, $true", [/*(set SPR:$dst, (ARMcneg SPR:$false, SPR:$true, imm:$cc))*/]>, RegConstraint<"$false = $dst">; + + +//===----------------------------------------------------------------------===// +// Misc. +// + +let Defs = [CPSR] in +def FMSTAT : ASI<(outs), (ins), "fmstat", "", [(arm_fmstat)]>; |