diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index ddd2564d9ef..b39ab7f833d 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -120,6 +120,8 @@ namespace { void emitMiscBranchInstruction(const MachineInstr &MI); + void emitVFPArithInstruction(const MachineInstr &MI); + /// getBinaryCodeForInstr - This function, generated by the /// CodeEmitterGenerator using TableGen, produces the binary encoding for /// machine instructions. @@ -313,6 +315,11 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { case ARMII::BrMiscFrm: emitMiscBranchInstruction(MI); break; + // VFP instructions. + case ARMII::VFPUnaryFrm: + case ARMII::VFPBinaryFrm: + emitVFPArithInstruction(MI); + break; } } @@ -976,4 +983,42 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { emitWordLE(Binary); } +void ARMCodeEmitter::emitVFPArithInstruction(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; + assert((Binary & ARMII::D_BitShift) == 0 && + (Binary & ARMII::N_BitShift) == 0 && + (Binary & ARMII::M_BitShift) == 0 && "VFP encoding bug!"); + + // Encode Dd / Sd. + unsigned RegD = getMachineOpValue(MI, OpIdx++); + Binary |= (RegD & 0x0f) << ARMII::RegFdShift; + Binary |= (RegD & 0x10) << ARMII::D_BitShift; + + // If this is a two-address operand, skip it, e.g. FMACD. + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + // Encode Dn / Sn. + if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) { + unsigned RegN = getMachineOpValue(MI, OpIdx++); + Binary |= (RegN & 0x0f); + Binary |= (RegN & 0x10) << ARMII::N_BitShift; + } + + // Encode Dm / Sm. + 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 9fe56d79d26..c898acae041 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -36,8 +36,10 @@ def StMulFrm : Format<12>; def ArithMiscFrm: Format<13>; def ExtFrm : Format<14>; -def ThumbFrm : Format<15>; -def VFPFrm : Format<16>; +def VFPFrm : Format<15>; +def VFPUnaryFrm : Format<16>; +def VFPBinaryFrm: Format<17>; +def ThumbFrm : Format<18>; // Misc flag for data processing instructions that indicates whether // the instruction has a Rn register operand. @@ -728,6 +730,100 @@ class TJTI pattern> : ThumbI; +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ARM VFP Instruction templates. +// + +// ARM Float Instruction +class ASI pattern> + : AI { + // TODO: Mark the instructions with the appropriate subtarget info. +} + +class ASI5 pattern> + : I { + // TODO: Mark the instructions with the appropriate subtarget info. +} + +// ARM Double Instruction +class ADI pattern> + : AI { + // TODO: Mark the instructions with the appropriate subtarget info. +} + +class ADI5 pattern> + : I { + // TODO: Mark the instructions with the appropriate subtarget info. +} + +// Double precision, unary +class ADuI 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} = 0b1011; + let Inst{7-4} = opcod3; +} + +// Double precision, binary +class ADbI opcod, dag oops, dag iops, string opc, + string asm, list pattern> + : AI { + let Inst{27-20} = opcod; + let Inst{11-8} = 0b1011; +} + +// Single precision, unary +class ASuI opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops, + string opc, string asm, list pattern> + : AI { + // Bits 22 (D bit) and 5 (M bit) will be changed during instruction encoding. + let Inst{27-20} = opcod1; + let Inst{19-16} = opcod2; + let Inst{11-8} = 0b1010; + let Inst{7-4} = opcod3; +} + +// Single precision, binary +class ASbI opcod, dag oops, dag iops, string opc, + string asm, list pattern> + : AI { + // Bit 22 (D bit) can be changed during instruction encoding. + let Inst{27-20} = opcod; + let Inst{11-8} = 0b1010; +} + +// Special cases. +class AXSI pattern> + : XI { + // TODO: Mark the instructions with the appropriate subtarget info. +} + +class AXSI5 pattern> + : XI { + // TODO: Mark the instructions with the appropriate subtarget info. +} + +class AXDI pattern> + : XI { + // TODO: Mark the instructions with the appropriate subtarget info. +} + +class AXDI5 pattern> + : XI { + // TODO: Mark the instructions with the appropriate subtarget info. +} + + //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index 0a8432ce985..323e6e742ab 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -100,26 +100,33 @@ namespace ARMII { // Extend instructions ExtFrm = 14 << FormShift, - // Thumb format - ThumbFrm = 15 << FormShift, + // VFP formats + VPFFrm = 15 << FormShift, + VFPUnaryFrm = 16 << FormShift, + VFPBinaryFrm = 17 << FormShift, - // VFP format - VPFFrm = 16 << FormShift, + // Thumb format + ThumbFrm = 18 << FormShift, //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating // machine instructions. + M_BitShift = 5, ShiftShift = 7, + N_BitShift = 7, SoRotImmShift = 8, RegRsShift = 8, ExtRotImmShift = 10, RegRdLoShift = 12, RegRdShift = 12, + RegFdShift = 12, RegRdHiShift = 16, RegRnShift = 16, + RegFnShift = 16, S_BitShift = 20, W_BitShift = 21, AM3_I_BitShift = 22, + D_BitShift = 22, U_BitShift = 23, P_BitShift = 24, I_BitShift = 25, diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 7e6c4d2a247..5ba7094571c 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -11,60 +11,6 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// ARM VFP Instruction templates. -// - -// ARM Float Instruction -class ASI pattern> - : AI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class ASI5 pattern> - : I { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -// ARM Double Instruction -class ADI pattern> - : AI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class ADI5 pattern> - : I { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -// Special cases. -class AXSI pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class AXSI5 pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class AXDI pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class AXDI5 pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - - def SDT_FTOI : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>; def SDT_ITOF : @@ -75,14 +21,14 @@ def SDT_FMDRR : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; -def arm_ftoui : SDNode<"ARMISD::FTOUI", SDT_FTOI>; -def arm_ftosi : SDNode<"ARMISD::FTOSI", SDT_FTOI>; -def arm_sitof : SDNode<"ARMISD::SITOF", SDT_ITOF>; -def arm_uitof : SDNode<"ARMISD::UITOF", SDT_ITOF>; +def arm_ftoui : SDNode<"ARMISD::FTOUI", SDT_FTOI>; +def arm_ftosi : SDNode<"ARMISD::FTOSI", SDT_FTOI>; +def arm_sitof : SDNode<"ARMISD::SITOF", SDT_ITOF>; +def arm_uitof : SDNode<"ARMISD::UITOF", SDT_ITOF>; def arm_fmstat : SDNode<"ARMISD::FMSTAT", SDTNone, [SDNPInFlag,SDNPOutFlag]>; -def arm_cmpfp : SDNode<"ARMISD::CMPFP", SDT_ARMCmp, [SDNPOutFlag]>; -def arm_cmpfp0 : SDNode<"ARMISD::CMPFPw0", SDT_CMPFP0, [SDNPOutFlag]>; -def arm_fmdrr : SDNode<"ARMISD::FMDRR", SDT_FMDRR>; +def arm_cmpfp : SDNode<"ARMISD::CMPFP", SDT_ARMCmp, [SDNPOutFlag]>; +def arm_cmpfp0 : SDNode<"ARMISD::CMPFPw0",SDT_CMPFP0, [SDNPOutFlag]>; +def arm_fmdrr : SDNode<"ARMISD::FMDRR", SDT_FMDRR>; //===----------------------------------------------------------------------===// // Load / store Instructions. @@ -140,45 +86,55 @@ def FSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$src1, // FP Binary Operations. // -def FADDD : ADI<(outs DPR:$dst), (ins DPR:$a, DPR:$b), +def FADDD : ADbI<0b11100011, (outs DPR:$dst), (ins DPR:$a, DPR:$b), "faddd", " $dst, $a, $b", [(set DPR:$dst, (fadd DPR:$a, DPR:$b))]>; -def FADDS : ASI<(outs SPR:$dst), (ins SPR:$a, SPR:$b), +def FADDS : ASbI<0b11100011, (outs SPR:$dst), (ins SPR:$a, SPR:$b), "fadds", " $dst, $a, $b", [(set SPR:$dst, (fadd SPR:$a, SPR:$b))]>; -def FCMPED : ADI<(outs), (ins DPR:$a, DPR:$b), +def FCMPED : ADbI<0b11101011, (outs), (ins DPR:$a, DPR:$b), "fcmped", " $a, $b", - [(arm_cmpfp DPR:$a, DPR:$b)]>; + [(arm_cmpfp DPR:$a, DPR:$b)]> { + let Inst{19-16} = 0b0100; + let Inst{7-6} = 0b11; +} -def FCMPES : ASI<(outs), (ins SPR:$a, SPR:$b), +def FCMPES : ASbI<0b11101011, (outs), (ins SPR:$a, SPR:$b), "fcmpes", " $a, $b", - [(arm_cmpfp SPR:$a, SPR:$b)]>; + [(arm_cmpfp SPR:$a, SPR:$b)]> { + let Inst{19-16} = 0b0100; + let Inst{7-6} = 0b11; +} -def FDIVD : ADI<(outs DPR:$dst), (ins DPR:$a, DPR:$b), +def FDIVD : ADbI<0b11101000, (outs DPR:$dst), (ins DPR:$a, DPR:$b), "fdivd", " $dst, $a, $b", [(set DPR:$dst, (fdiv DPR:$a, DPR:$b))]>; -def FDIVS : ASI<(outs SPR:$dst), (ins SPR:$a, SPR:$b), +def FDIVS : ASbI<0b11101000, (outs SPR:$dst), (ins SPR:$a, SPR:$b), "fdivs", " $dst, $a, $b", [(set SPR:$dst, (fdiv SPR:$a, SPR:$b))]>; -def FMULD : ADI<(outs DPR:$dst), (ins DPR:$a, DPR:$b), +def FMULD : ADbI<0b11100010, (outs DPR:$dst), (ins DPR:$a, DPR:$b), "fmuld", " $dst, $a, $b", [(set DPR:$dst, (fmul DPR:$a, DPR:$b))]>; -def FMULS : ASI<(outs SPR:$dst), (ins SPR:$a, SPR:$b), +def FMULS : ASbI<0b11100010, (outs SPR:$dst), (ins SPR:$a, SPR:$b), "fmuls", " $dst, $a, $b", [(set SPR:$dst, (fmul SPR:$a, SPR:$b))]>; -def FNMULD : ADI<(outs DPR:$dst), (ins DPR:$a, DPR:$b), +def FNMULD : ADbI<0b11100010, (outs DPR:$dst), (ins DPR:$a, DPR:$b), "fnmuld", " $dst, $a, $b", - [(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]>; + [(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]> { + let Inst{6} = 1; +} -def FNMULS : ASI<(outs SPR:$dst), (ins SPR:$a, SPR:$b), +def FNMULS : ASbI<0b11100010, (outs SPR:$dst), (ins SPR:$a, SPR:$b), "fnmuls", " $dst, $a, $b", - [(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]>; + [(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]> { + let Inst{6} = 1; +} // Match reassociated forms only if not sign dependent rounding. def : Pat<(fmul (fneg DPR:$a), DPR:$b), @@ -187,11 +143,11 @@ def : Pat<(fmul (fneg SPR:$a), SPR:$b), (FNMULS SPR:$a, SPR:$b)>, Requires<[NoHonorSignDependentRounding]>; -def FSUBD : ADI<(outs DPR:$dst), (ins DPR:$a, DPR:$b), +def FSUBD : ADbI<0b11100011, (outs DPR:$dst), (ins DPR:$a, DPR:$b), "fsubd", " $dst, $a, $b", [(set DPR:$dst, (fsub DPR:$a, DPR:$b))]>; -def FSUBS : ASI<(outs SPR:$dst), (ins SPR:$a, SPR:$b), +def FSUBS : ASbI<0b11100011, (outs SPR:$dst), (ins SPR:$a, SPR:$b), "fsubs", " $dst, $a, $b", [(set SPR:$dst, (fsub SPR:$a, SPR:$b))]>; @@ -199,49 +155,55 @@ def FSUBS : ASI<(outs SPR:$dst), (ins SPR:$a, SPR:$b), // FP Unary Operations. // -def FABSD : ADI<(outs DPR:$dst), (ins DPR:$a), +def FABSD : ADuI<0b11101011, 0b0000, 0b1100, (outs DPR:$dst), (ins DPR:$a), "fabsd", " $dst, $a", [(set DPR:$dst, (fabs DPR:$a))]>; -def FABSS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FABSS : ASuI<0b11101011, 0b0000, 0b1100, (outs SPR:$dst), (ins SPR:$a), "fabss", " $dst, $a", [(set SPR:$dst, (fabs SPR:$a))]>; -def FCMPEZD : ADI<(outs), (ins DPR:$a), +def FCMPEZD : ADuI<0b11101011, 0b0101, 0b1100, (outs), (ins DPR:$a), "fcmpezd", " $a", [(arm_cmpfp0 DPR:$a)]>; -def FCMPEZS : ASI<(outs), (ins SPR:$a), +def FCMPEZS : ASuI<0b11101011, 0b0101, 0b1100, (outs), (ins SPR:$a), "fcmpezs", " $a", [(arm_cmpfp0 SPR:$a)]>; -def FCVTDS : ADI<(outs DPR:$dst), (ins SPR:$a), +def FCVTDS : ASuI<0b11101011, 0b0111, 0b1100, (outs DPR:$dst), (ins SPR:$a), "fcvtds", " $dst, $a", [(set DPR:$dst, (fextend SPR:$a))]>; -def FCVTSD : ADI<(outs SPR:$dst), (ins DPR:$a), +// Special case encoding: bits 11-8 is 0b1011. +def FCVTSD : AI<(outs SPR:$dst), (ins DPR:$a), VFPUnaryFrm, "fcvtsd", " $dst, $a", - [(set SPR:$dst, (fround DPR:$a))]>; + [(set SPR:$dst, (fround DPR:$a))]> { + let Inst{27-23} = 0b11101; + let Inst{21-16} = 0b110111; + let Inst{11-8} = 0b1011; + let Inst{7-4} = 0b1100; +} -def FCPYD : ADI<(outs DPR:$dst), (ins DPR:$a), +def FCPYD : ADuI<0b11101011, 0b0000, 0b0100, (outs DPR:$dst), (ins DPR:$a), "fcpyd", " $dst, $a", []>; -def FCPYS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FCPYS : ASuI<0b11101011, 0b0000, 0b0100, (outs SPR:$dst), (ins SPR:$a), "fcpys", " $dst, $a", []>; -def FNEGD : ADI<(outs DPR:$dst), (ins DPR:$a), +def FNEGD : ADuI<0b11101011, 0b0001, 0b0100, (outs DPR:$dst), (ins DPR:$a), "fnegd", " $dst, $a", [(set DPR:$dst, (fneg DPR:$a))]>; -def FNEGS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FNEGS : ASuI<0b11101011, 0b0001, 0b0100, (outs SPR:$dst), (ins SPR:$a), "fnegs", " $dst, $a", [(set SPR:$dst, (fneg SPR:$a))]>; -def FSQRTD : ADI<(outs DPR:$dst), (ins DPR:$a), +def FSQRTD : ADuI<0b11101011, 0b0001, 0b1100, (outs DPR:$dst), (ins DPR:$a), "fsqrtd", " $dst, $a", [(set DPR:$dst, (fsqrt DPR:$a))]>; -def FSQRTS : ASI<(outs SPR:$dst), (ins SPR:$a), +def FSQRTS : ASuI<0b11101011, 0b0001, 0b1100, (outs SPR:$dst), (ins SPR:$a), "fsqrts", " $dst, $a", [(set SPR:$dst, (fsqrt SPR:$a))]>; @@ -323,45 +285,53 @@ def FTOUIZS : ASI<(outs SPR:$dst), (ins SPR:$a), // FP FMA Operations. // -def FMACD : ADI<(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), +def FMACD : ADbI<0b11100000, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), "fmacd", " $dst, $a, $b", [(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), DPR:$dstin))]>, RegConstraint<"$dstin = $dst">; -def FMACS : ASI<(outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), +def FMACS : ASbI<0b11100000, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), "fmacs", " $dst, $a, $b", [(set SPR:$dst, (fadd (fmul SPR:$a, SPR:$b), SPR:$dstin))]>, RegConstraint<"$dstin = $dst">; -def FMSCD : ADI<(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), +def FMSCD : ADbI<0b11100001, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), "fmscd", " $dst, $a, $b", [(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), DPR:$dstin))]>, RegConstraint<"$dstin = $dst">; -def FMSCS : ASI<(outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), +def FMSCS : ASbI<0b11100001, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), "fmscs", " $dst, $a, $b", [(set SPR:$dst, (fsub (fmul SPR:$a, SPR:$b), SPR:$dstin))]>, RegConstraint<"$dstin = $dst">; -def FNMACD : ADI<(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), +def FNMACD : ADbI<0b11100000, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), "fnmacd", " $dst, $a, $b", [(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>, - RegConstraint<"$dstin = $dst">; + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} -def FNMACS : ASI<(outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), +def FNMACS : ASbI<0b11100000, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), "fnmacs", " $dst, $a, $b", [(set SPR:$dst, (fadd (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>, - RegConstraint<"$dstin = $dst">; + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} -def FNMSCD : ADI<(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), +def FNMSCD : ADbI<0b11100001, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), "fnmscd", " $dst, $a, $b", [(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>, - RegConstraint<"$dstin = $dst">; + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} -def FNMSCS : ASI<(outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), +def FNMSCS : ASbI<0b11100001, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), "fnmscs", " $dst, $a, $b", [(set SPR:$dst, (fsub (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>, - RegConstraint<"$dstin = $dst">; + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} //===----------------------------------------------------------------------===// // FP Conditional moves.