MipsInstrFPU.td revision 234982
1218822Sdim//===-- MipsInstrFPU.td - Mips FPU Instruction Information -*- tablegen -*-===// 2218822Sdim// 3218822Sdim// The LLVM Compiler Infrastructure 4218822Sdim// 5218822Sdim// This file is distributed under the University of Illinois Open Source 6218822Sdim// License. See LICENSE.TXT for details. 7218822Sdim// 8218822Sdim//===----------------------------------------------------------------------===// 9218822Sdim// 10218822Sdim// This file describes the Mips FPU instruction set. 11218822Sdim// 12218822Sdim//===----------------------------------------------------------------------===// 13218822Sdim 14218822Sdim//===----------------------------------------------------------------------===// 15218822Sdim// Floating Point Instructions 16218822Sdim// ------------------------ 17218822Sdim// * 64bit fp: 18218822Sdim// - 32 64-bit registers (default mode) 19218822Sdim// - 16 even 32-bit registers (32-bit compatible mode) for 20130561Sobrien// single and double access. 21130561Sobrien// * 32bit fp: 22130561Sobrien// - 16 even 32-bit registers - single and double (aliased) 23130561Sobrien// - 32 32-bit registers (within single-only mode) 24130561Sobrien//===----------------------------------------------------------------------===// 25130561Sobrien 26130561Sobrien// Floating Point Compare and Branch 27130561Sobriendef SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>, 28130561Sobrien SDTCisVT<1, OtherVT>]>; 29130561Sobriendef SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, 30130561Sobrien SDTCisVT<2, i32>]>; 31130561Sobriendef SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, 32130561Sobrien SDTCisSameAs<1, 2>]>; 33130561Sobriendef SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, 34130561Sobrien SDTCisVT<1, i32>, 35130561Sobrien SDTCisSameAs<1, 2>]>; 36130561Sobriendef SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, 37130561Sobrien SDTCisVT<1, f64>, 38130561Sobrien SDTCisVT<2, i32>]>; 39130561Sobrien 40130561Sobriendef MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>; 41130561Sobriendef MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>; 42130561Sobriendef MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>; 43130561Sobriendef MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, 44130561Sobrien [SDNPHasChain, SDNPOptInGlue]>; 45130561Sobriendef MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64", SDT_MipsBuildPairF64>; 46130561Sobriendef MipsExtractElementF64 : SDNode<"MipsISD::ExtractElementF64", 47130561Sobrien SDT_MipsExtractElementF64>; 48130561Sobrien 49130561Sobrien// Operand for printing out a condition code. 50130561Sobrienlet PrintMethod = "printFCCOperand", DecoderMethod = "DecodeCondCode" in 51130561Sobrien def condcode : Operand<i32>; 52130561Sobrien 53130561Sobrien//===----------------------------------------------------------------------===// 54130561Sobrien// Feature predicates. 55130561Sobrien//===----------------------------------------------------------------------===// 56130561Sobrien 57130561Sobriendef IsFP64bit : Predicate<"Subtarget.isFP64bit()">, AssemblerPredicate<"FeatureFP64Bit">; 58130561Sobriendef NotFP64bit : Predicate<"!Subtarget.isFP64bit()">, AssemblerPredicate<"!FeatureFP64Bit">; 59130561Sobriendef IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">, AssemblerPredicate<"FeatureSingleFloat">; 60130561Sobriendef IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">, AssemblerPredicate<"!FeatureSingleFloat">; 61130561Sobrien 62130561Sobrien// FP immediate patterns. 63130561Sobriendef fpimm0 : PatLeaf<(fpimm), [{ 64130561Sobrien return N->isExactlyValue(+0.0); 65130561Sobrien}]>; 66130561Sobrien 67130561Sobriendef fpimm0neg : PatLeaf<(fpimm), [{ 68130561Sobrien return N->isExactlyValue(-0.0); 69130561Sobrien}]>; 70130561Sobrien 71130561Sobrien//===----------------------------------------------------------------------===// 72130561Sobrien// Instruction Class Templates 73130561Sobrien// 74130561Sobrien// A set of multiclasses is used to address the register usage. 75130561Sobrien// 76130561Sobrien// S32 - single precision in 16 32bit even fp registers 77130561Sobrien// single precision in 32 32bit fp registers in SingleOnly mode 78130561Sobrien// S64 - single precision in 32 64bit fp registers (In64BitMode) 79130561Sobrien// D32 - double precision in 16 32bit even fp registers 80130561Sobrien// D64 - double precision in 32 64bit fp registers (In64BitMode) 81130561Sobrien// 82130561Sobrien// Only S32 and D32 are supported right now. 83130561Sobrien//===----------------------------------------------------------------------===// 84130561Sobrien 85130561Sobrien// FP load. 86130561Sobrienlet DecoderMethod = "DecodeFMem" in { 87130561Sobrienclass FPLoad<bits<6> op, string opstr, RegisterClass RC, Operand MemOpnd>: 88130561Sobrien FMem<op, (outs RC:$ft), (ins MemOpnd:$addr), 89130561Sobrien !strconcat(opstr, "\t$ft, $addr"), [(set RC:$ft, (load_a addr:$addr))], 90130561Sobrien IILoad>; 91130561Sobrien 92130561Sobrien// FP store. 93130561Sobrienclass FPStore<bits<6> op, string opstr, RegisterClass RC, Operand MemOpnd>: 94130561Sobrien FMem<op, (outs), (ins RC:$ft, MemOpnd:$addr), 95130561Sobrien !strconcat(opstr, "\t$ft, $addr"), [(store_a RC:$ft, addr:$addr)], 96130561Sobrien IIStore>; 97130561Sobrien} 98130561Sobrien// FP indexed load. 99130561Sobrienclass FPIdxLoad<bits<6> funct, string opstr, RegisterClass DRC, 100130561Sobrien RegisterClass PRC, PatFrag FOp>: 101130561Sobrien FFMemIdx<funct, (outs DRC:$fd), (ins PRC:$base, PRC:$index), 102130561Sobrien !strconcat(opstr, "\t$fd, $index($base)"), 103130561Sobrien [(set DRC:$fd, (FOp (add PRC:$base, PRC:$index)))]> { 104130561Sobrien let fs = 0; 105130561Sobrien} 106130561Sobrien 107130561Sobrien// FP indexed store. 108130561Sobrienclass FPIdxStore<bits<6> funct, string opstr, RegisterClass DRC, 109130561Sobrien RegisterClass PRC, PatFrag FOp>: 110130561Sobrien FFMemIdx<funct, (outs), (ins DRC:$fs, PRC:$base, PRC:$index), 111130561Sobrien !strconcat(opstr, "\t$fs, $index($base)"), 112130561Sobrien [(FOp DRC:$fs, (add PRC:$base, PRC:$index))]> { 113130561Sobrien let fd = 0; 114130561Sobrien} 115130561Sobrien 116130561Sobrien// Instructions that convert an FP value to 32-bit fixed point. 117130561Sobrienmulticlass FFR1_W_M<bits<6> funct, string opstr> { 118130561Sobrien def _S : FFR1<funct, 16, opstr, "w.s", FGR32, FGR32>; 119130561Sobrien def _D32 : FFR1<funct, 17, opstr, "w.d", FGR32, AFGR64>, 120130561Sobrien Requires<[NotFP64bit]>; 121130561Sobrien def _D64 : FFR1<funct, 17, opstr, "w.d", FGR32, FGR64>, 122130561Sobrien Requires<[IsFP64bit]> { 123130561Sobrien let DecoderNamespace = "Mips64"; 124130561Sobrien } 125130561Sobrien} 126130561Sobrien 127130561Sobrien// Instructions that convert an FP value to 64-bit fixed point. 128130561Sobrienlet Predicates = [IsFP64bit], DecoderNamespace = "Mips64" in 129130561Sobrienmulticlass FFR1_L_M<bits<6> funct, string opstr> { 130130561Sobrien def _S : FFR1<funct, 16, opstr, "l.s", FGR64, FGR32>; 131130561Sobrien def _D64 : FFR1<funct, 17, opstr, "l.d", FGR64, FGR64>; 132130561Sobrien} 133130561Sobrien 134130561Sobrien// FP-to-FP conversion instructions. 135130561Sobrienmulticlass FFR1P_M<bits<6> funct, string opstr, SDNode OpNode> { 136130561Sobrien def _S : FFR1P<funct, 16, opstr, "s", FGR32, FGR32, OpNode>; 137130561Sobrien def _D32 : FFR1P<funct, 17, opstr, "d", AFGR64, AFGR64, OpNode>, 138130561Sobrien Requires<[NotFP64bit]>; 139130561Sobrien def _D64 : FFR1P<funct, 17, opstr, "d", FGR64, FGR64, OpNode>, 140130561Sobrien Requires<[IsFP64bit]> { 141130561Sobrien let DecoderNamespace = "Mips64"; 142130561Sobrien } 143130561Sobrien} 144130561Sobrien 145130561Sobrienmulticlass FFR2P_M<bits<6> funct, string opstr, SDNode OpNode, bit isComm = 0> { 146130561Sobrien let isCommutable = isComm in { 147130561Sobrien def _S : FFR2P<funct, 16, opstr, "s", FGR32, OpNode>; 148130561Sobrien def _D32 : FFR2P<funct, 17, opstr, "d", AFGR64, OpNode>, 149130561Sobrien Requires<[NotFP64bit]>; 150130561Sobrien def _D64 : FFR2P<funct, 17, opstr, "d", FGR64, OpNode>, 151130561Sobrien Requires<[IsFP64bit]> { 152130561Sobrien let DecoderNamespace = "Mips64"; 153130561Sobrien } 154130561Sobrien} 155130561Sobrien} 156130561Sobrien 157130561Sobrien// FP madd/msub/nmadd/nmsub instruction classes. 158130561Sobrienclass FMADDSUB<bits<3> funct, bits<3> fmt, string opstr, string fmtstr, 159130561Sobrien SDNode OpNode, RegisterClass RC> : 160130561Sobrien FFMADDSUB<funct, fmt, (outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), 161130561Sobrien !strconcat(opstr, ".", fmtstr, "\t$fd, $fr, $fs, $ft"), 162130561Sobrien [(set RC:$fd, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr))]>; 163130561Sobrien 164130561Sobrienclass FNMADDSUB<bits<3> funct, bits<3> fmt, string opstr, string fmtstr, 165130561Sobrien SDNode OpNode, RegisterClass RC> : 166130561Sobrien FFMADDSUB<funct, fmt, (outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), 167130561Sobrien !strconcat(opstr, ".", fmtstr, "\t$fd, $fr, $fs, $ft"), 168130561Sobrien [(set RC:$fd, (fsub fpimm0, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr)))]>; 169130561Sobrien 170130561Sobrien//===----------------------------------------------------------------------===// 171130561Sobrien// Floating Point Instructions 172130561Sobrien//===----------------------------------------------------------------------===// 173130561Sobriendefm ROUND_W : FFR1_W_M<0xc, "round">; 174130561Sobriendefm ROUND_L : FFR1_L_M<0x8, "round">; 175130561Sobriendefm TRUNC_W : FFR1_W_M<0xd, "trunc">; 176130561Sobriendefm TRUNC_L : FFR1_L_M<0x9, "trunc">; 177130561Sobriendefm CEIL_W : FFR1_W_M<0xe, "ceil">; 178130561Sobriendefm CEIL_L : FFR1_L_M<0xa, "ceil">; 179130561Sobriendefm FLOOR_W : FFR1_W_M<0xf, "floor">; 180130561Sobriendefm FLOOR_L : FFR1_L_M<0xb, "floor">; 181130561Sobriendefm CVT_W : FFR1_W_M<0x24, "cvt">; 182130561Sobrien//defm CVT_L : FFR1_L_M<0x25, "cvt">; 183130561Sobrien 184130561Sobriendef CVT_S_W : FFR1<0x20, 20, "cvt", "s.w", FGR32, FGR32>; 185130561Sobriendef CVT_L_S : FFR1<0x25, 16, "cvt", "l.s", FGR64, FGR32>; 186130561Sobriendef CVT_L_D64: FFR1<0x25, 17, "cvt", "l.d", FGR64, FGR64>; 187130561Sobrien 188130561Sobrienlet Predicates = [NotFP64bit] in { 189130561Sobrien def CVT_S_D32 : FFR1<0x20, 17, "cvt", "s.d", FGR32, AFGR64>; 190130561Sobrien def CVT_D32_W : FFR1<0x21, 20, "cvt", "d.w", AFGR64, FGR32>; 191130561Sobrien def CVT_D32_S : FFR1<0x21, 16, "cvt", "d.s", AFGR64, FGR32>; 192130561Sobrien} 193130561Sobrien 194130561Sobrienlet Predicates = [IsFP64bit], DecoderNamespace = "Mips64" in { 195130561Sobrien def CVT_S_D64 : FFR1<0x20, 17, "cvt", "s.d", FGR32, FGR64>; 196130561Sobrien def CVT_S_L : FFR1<0x20, 21, "cvt", "s.l", FGR32, FGR64>; 197130561Sobrien def CVT_D64_W : FFR1<0x21, 20, "cvt", "d.w", FGR64, FGR32>; 198130561Sobrien def CVT_D64_S : FFR1<0x21, 16, "cvt", "d.s", FGR64, FGR32>; 199130561Sobrien def CVT_D64_L : FFR1<0x21, 21, "cvt", "d.l", FGR64, FGR64>; 200130561Sobrien} 201130561Sobrien 202130561Sobrienlet Predicates = [NoNaNsFPMath] in { 203130561Sobrien defm FABS : FFR1P_M<0x5, "abs", fabs>; 204130561Sobrien defm FNEG : FFR1P_M<0x7, "neg", fneg>; 205130561Sobrien} 206130561Sobriendefm FSQRT : FFR1P_M<0x4, "sqrt", fsqrt>; 207130561Sobrien 208130561Sobrien// The odd-numbered registers are only referenced when doing loads, 209130561Sobrien// stores, and moves between floating-point and integer registers. 210130561Sobrien// When defining instructions, we reference all 32-bit registers, 211130561Sobrien// regardless of register aliasing. 212130561Sobrien 213130561Sobrienclass FFRGPR<bits<5> _fmt, dag outs, dag ins, string asmstr, list<dag> pattern>: 214130561Sobrien FFR<0x11, 0x0, _fmt, outs, ins, asmstr, pattern> { 215130561Sobrien bits<5> rt; 216130561Sobrien let ft = rt; 217130561Sobrien let fd = 0; 218130561Sobrien} 219130561Sobrien 220130561Sobrien/// Move Control Registers From/To CPU Registers 221130561Sobriendef CFC1 : FFRGPR<0x2, (outs CPURegs:$rt), (ins CCR:$fs), 222130561Sobrien "cfc1\t$rt, $fs", []>; 223130561Sobrien 224130561Sobriendef CTC1 : FFRGPR<0x6, (outs CCR:$fs), (ins CPURegs:$rt), 225130561Sobrien "ctc1\t$rt, $fs", []>; 226130561Sobrien 227130561Sobriendef MFC1 : FFRGPR<0x00, (outs CPURegs:$rt), (ins FGR32:$fs), 228130561Sobrien "mfc1\t$rt, $fs", 229130561Sobrien [(set CPURegs:$rt, (bitconvert FGR32:$fs))]>; 230130561Sobrien 231130561Sobriendef MTC1 : FFRGPR<0x04, (outs FGR32:$fs), (ins CPURegs:$rt), 232130561Sobrien "mtc1\t$rt, $fs", 233130561Sobrien [(set FGR32:$fs, (bitconvert CPURegs:$rt))]>; 234130561Sobrien 235130561Sobriendef DMFC1 : FFRGPR<0x01, (outs CPU64Regs:$rt), (ins FGR64:$fs), 236130561Sobrien "dmfc1\t$rt, $fs", 237130561Sobrien [(set CPU64Regs:$rt, (bitconvert FGR64:$fs))]>; 238130561Sobrien 239130561Sobriendef DMTC1 : FFRGPR<0x05, (outs FGR64:$fs), (ins CPU64Regs:$rt), 240130561Sobrien "dmtc1\t$rt, $fs", 241130561Sobrien [(set FGR64:$fs, (bitconvert CPU64Regs:$rt))]>; 242130561Sobrien 243130561Sobriendef FMOV_S : FFR1<0x6, 16, "mov", "s", FGR32, FGR32>; 244130561Sobriendef FMOV_D32 : FFR1<0x6, 17, "mov", "d", AFGR64, AFGR64>, 245130561Sobrien Requires<[NotFP64bit]>; 246130561Sobriendef FMOV_D64 : FFR1<0x6, 17, "mov", "d", FGR64, FGR64>, 247130561Sobrien Requires<[IsFP64bit]> { 248130561Sobrien let DecoderNamespace = "Mips64"; 249130561Sobrien} 250130561Sobrien 251130561Sobrien/// Floating Point Memory Instructions 252130561Sobrienlet Predicates = [IsN64], DecoderNamespace = "Mips64" in { 253130561Sobrien def LWC1_P8 : FPLoad<0x31, "lwc1", FGR32, mem64>; 254130561Sobrien def SWC1_P8 : FPStore<0x39, "swc1", FGR32, mem64>; 255130561Sobrien def LDC164_P8 : FPLoad<0x35, "ldc1", FGR64, mem64> { 256130561Sobrien let isCodeGenOnly =1; 257130561Sobrien } 258130561Sobrien def SDC164_P8 : FPStore<0x3d, "sdc1", FGR64, mem64> { 259130561Sobrien let isCodeGenOnly =1; 260130561Sobrien } 261130561Sobrien} 262130561Sobrien 263130561Sobrienlet Predicates = [NotN64] in { 264130561Sobrien def LWC1 : FPLoad<0x31, "lwc1", FGR32, mem>; 265130561Sobrien def SWC1 : FPStore<0x39, "swc1", FGR32, mem>; 266130561Sobrien} 267130561Sobrien 268130561Sobrienlet Predicates = [NotN64, HasMips64], DecoderNamespace = "Mips64" in { 269130561Sobrien def LDC164 : FPLoad<0x35, "ldc1", FGR64, mem>; 270130561Sobrien def SDC164 : FPStore<0x3d, "sdc1", FGR64, mem>; 271130561Sobrien} 272130561Sobrien 273130561Sobrienlet Predicates = [NotN64, NotMips64] in { 274130561Sobrien def LDC1 : FPLoad<0x35, "ldc1", AFGR64, mem>; 275130561Sobrien def SDC1 : FPStore<0x3d, "sdc1", AFGR64, mem>; 276130561Sobrien} 277130561Sobrien 278130561Sobrien// Indexed loads and stores. 279130561Sobrienlet Predicates = [HasMips32r2Or64] in { 280130561Sobrien def LWXC1 : FPIdxLoad<0x0, "lwxc1", FGR32, CPURegs, load_a>; 281130561Sobrien def LUXC1 : FPIdxLoad<0x5, "luxc1", FGR32, CPURegs, load_u>; 282130561Sobrien def SWXC1 : FPIdxStore<0x8, "swxc1", FGR32, CPURegs, store_a>; 283130561Sobrien def SUXC1 : FPIdxStore<0xd, "suxc1", FGR32, CPURegs, store_u>; 284130561Sobrien} 285130561Sobrien 286130561Sobrienlet Predicates = [HasMips32r2, NotMips64] in { 287130561Sobrien def LDXC1 : FPIdxLoad<0x1, "ldxc1", AFGR64, CPURegs, load_a>; 288130561Sobrien def SDXC1 : FPIdxStore<0x9, "sdxc1", AFGR64, CPURegs, store_a>; 289130561Sobrien} 290130561Sobrien 291130561Sobrienlet Predicates = [HasMips64, NotN64], DecoderNamespace="Mips64" in { 292130561Sobrien def LDXC164 : FPIdxLoad<0x1, "ldxc1", FGR64, CPURegs, load_a>; 293130561Sobrien def SDXC164 : FPIdxStore<0x9, "sdxc1", FGR64, CPURegs, store_a>; 294130561Sobrien} 295130561Sobrien 296130561Sobrien// n64 297130561Sobrienlet Predicates = [IsN64], isCodeGenOnly=1 in { 298130561Sobrien def LWXC1_P8 : FPIdxLoad<0x0, "lwxc1", FGR32, CPU64Regs, load_a>; 299130561Sobrien def LUXC1_P8 : FPIdxLoad<0x5, "luxc1", FGR32, CPU64Regs, load_u>; 300130561Sobrien def LDXC164_P8 : FPIdxLoad<0x1, "ldxc1", FGR64, CPU64Regs, load_a>; 301130561Sobrien def SWXC1_P8 : FPIdxStore<0x8, "swxc1", FGR32, CPU64Regs, store_a>; 302130561Sobrien def SUXC1_P8 : FPIdxStore<0xd, "suxc1", FGR32, CPU64Regs, store_u>; 303130561Sobrien def SDXC164_P8 : FPIdxStore<0x9, "sdxc1", FGR64, CPU64Regs, store_a>; 304130561Sobrien} 305130561Sobrien 306130561Sobrien/// Floating-point Aritmetic 307130561Sobriendefm FADD : FFR2P_M<0x00, "add", fadd, 1>; 308130561Sobriendefm FDIV : FFR2P_M<0x03, "div", fdiv>; 309130561Sobriendefm FMUL : FFR2P_M<0x02, "mul", fmul, 1>; 310130561Sobriendefm FSUB : FFR2P_M<0x01, "sub", fsub>; 311130561Sobrien 312130561Sobrienlet Predicates = [HasMips32r2] in { 313130561Sobrien def MADD_S : FMADDSUB<0x4, 0, "madd", "s", fadd, FGR32>; 314130561Sobrien def MSUB_S : FMADDSUB<0x5, 0, "msub", "s", fsub, FGR32>; 315130561Sobrien} 316130561Sobrien 317130561Sobrienlet Predicates = [HasMips32r2, NoNaNsFPMath] in { 318130561Sobrien def NMADD_S : FNMADDSUB<0x6, 0, "nmadd", "s", fadd, FGR32>; 319130561Sobrien def NMSUB_S : FNMADDSUB<0x7, 0, "nmsub", "s", fsub, FGR32>; 320130561Sobrien} 321130561Sobrien 322130561Sobrienlet Predicates = [HasMips32r2, NotFP64bit] in { 323130561Sobrien def MADD_D32 : FMADDSUB<0x4, 1, "madd", "d", fadd, AFGR64>; 324130561Sobrien def MSUB_D32 : FMADDSUB<0x5, 1, "msub", "d", fsub, AFGR64>; 325130561Sobrien} 326130561Sobrien 327130561Sobrienlet Predicates = [HasMips32r2, NotFP64bit, NoNaNsFPMath] in { 328130561Sobrien def NMADD_D32 : FNMADDSUB<0x6, 1, "nmadd", "d", fadd, AFGR64>; 329130561Sobrien def NMSUB_D32 : FNMADDSUB<0x7, 1, "nmsub", "d", fsub, AFGR64>; 330130561Sobrien} 331130561Sobrien 332130561Sobrienlet Predicates = [HasMips32r2, IsFP64bit], isCodeGenOnly=1 in { 333130561Sobrien def MADD_D64 : FMADDSUB<0x4, 1, "madd", "d", fadd, FGR64>; 334130561Sobrien def MSUB_D64 : FMADDSUB<0x5, 1, "msub", "d", fsub, FGR64>; 335130561Sobrien} 336130561Sobrien 337130561Sobrienlet Predicates = [HasMips32r2, IsFP64bit, NoNaNsFPMath], isCodeGenOnly=1 in { 338130561Sobrien def NMADD_D64 : FNMADDSUB<0x6, 1, "nmadd", "d", fadd, FGR64>; 339130561Sobrien def NMSUB_D64 : FNMADDSUB<0x7, 1, "nmsub", "d", fsub, FGR64>; 340130561Sobrien} 341130561Sobrien 342130561Sobrien//===----------------------------------------------------------------------===// 343130561Sobrien// Floating Point Branch Codes 344130561Sobrien//===----------------------------------------------------------------------===// 345130561Sobrien// Mips branch codes. These correspond to condcode in MipsInstrInfo.h. 346130561Sobrien// They must be kept in synch. 347130561Sobriendef MIPS_BRANCH_F : PatLeaf<(i32 0)>; 348130561Sobriendef MIPS_BRANCH_T : PatLeaf<(i32 1)>; 349130561Sobrien 350130561Sobrien/// Floating Point Branch of False/True (Likely) 351130561Sobrienlet isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in 352130561Sobrien class FBRANCH<bits<1> nd, bits<1> tf, PatLeaf op, string asmstr> : 353130561Sobrien FFI<0x11, (outs), (ins brtarget:$dst), !strconcat(asmstr, "\t$dst"), 354130561Sobrien [(MipsFPBrcond op, bb:$dst)]> { 355130561Sobrien let Inst{20-18} = 0; 356130561Sobrien let Inst{17} = nd; 357130561Sobrien let Inst{16} = tf; 358130561Sobrien} 359130561Sobrien 360130561Sobrienlet DecoderMethod = "DecodeBC1" in { 361130561Sobriendef BC1F : FBRANCH<0, 0, MIPS_BRANCH_F, "bc1f">; 362130561Sobriendef BC1T : FBRANCH<0, 1, MIPS_BRANCH_T, "bc1t">; 363130561Sobrien} 364130561Sobrien//===----------------------------------------------------------------------===// 365130561Sobrien// Floating Point Flag Conditions 366130561Sobrien//===----------------------------------------------------------------------===// 367130561Sobrien// Mips condition codes. They must correspond to condcode in MipsInstrInfo.h. 368130561Sobrien// They must be kept in synch. 369130561Sobriendef MIPS_FCOND_F : PatLeaf<(i32 0)>; 370130561Sobriendef MIPS_FCOND_UN : PatLeaf<(i32 1)>; 371130561Sobriendef MIPS_FCOND_OEQ : PatLeaf<(i32 2)>; 372130561Sobriendef MIPS_FCOND_UEQ : PatLeaf<(i32 3)>; 373130561Sobriendef MIPS_FCOND_OLT : PatLeaf<(i32 4)>; 374130561Sobriendef MIPS_FCOND_ULT : PatLeaf<(i32 5)>; 375130561Sobriendef MIPS_FCOND_OLE : PatLeaf<(i32 6)>; 376130561Sobriendef MIPS_FCOND_ULE : PatLeaf<(i32 7)>; 377130561Sobriendef MIPS_FCOND_SF : PatLeaf<(i32 8)>; 378130561Sobriendef MIPS_FCOND_NGLE : PatLeaf<(i32 9)>; 379130561Sobriendef MIPS_FCOND_SEQ : PatLeaf<(i32 10)>; 380130561Sobriendef MIPS_FCOND_NGL : PatLeaf<(i32 11)>; 381130561Sobriendef MIPS_FCOND_LT : PatLeaf<(i32 12)>; 382130561Sobriendef MIPS_FCOND_NGE : PatLeaf<(i32 13)>; 383130561Sobriendef MIPS_FCOND_LE : PatLeaf<(i32 14)>; 384130561Sobriendef MIPS_FCOND_NGT : PatLeaf<(i32 15)>; 385130561Sobrien 386130561Sobrienclass FCMP<bits<5> fmt, RegisterClass RC, string typestr> : 387130561Sobrien FCC<fmt, (outs), (ins RC:$fs, RC:$ft, condcode:$cc), 388130561Sobrien !strconcat("c.$cc.", typestr, "\t$fs, $ft"), 389130561Sobrien [(MipsFPCmp RC:$fs, RC:$ft, imm:$cc)]>; 390130561Sobrien 391130561Sobrien/// Floating Point Compare 392130561Sobrienlet Defs=[FCR31] in { 393130561Sobrien def FCMP_S32 : FCMP<0x10, FGR32, "s">; 394130561Sobrien def FCMP_D32 : FCMP<0x11, AFGR64, "d">, Requires<[NotFP64bit]>; 395130561Sobrien def FCMP_D64 : FCMP<0x11, FGR64, "d">, Requires<[IsFP64bit]> { 396130561Sobrien let DecoderNamespace = "Mips64"; 397130561Sobrien } 398130561Sobrien} 399130561Sobrien 400130561Sobrien//===----------------------------------------------------------------------===// 401130561Sobrien// Floating Point Pseudo-Instructions 402130561Sobrien//===----------------------------------------------------------------------===// 403130561Sobriendef MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src), 404130561Sobrien "# MOVCCRToCCR", []>; 405130561Sobrien 406130561Sobrien// This pseudo instr gets expanded into 2 mtc1 instrs after register 407130561Sobrien// allocation. 408130561Sobriendef BuildPairF64 : 409130561Sobrien MipsPseudo<(outs AFGR64:$dst), 410130561Sobrien (ins CPURegs:$lo, CPURegs:$hi), "", 411130561Sobrien [(set AFGR64:$dst, (MipsBuildPairF64 CPURegs:$lo, CPURegs:$hi))]>; 412130561Sobrien 413130561Sobrien// This pseudo instr gets expanded into 2 mfc1 instrs after register 414130561Sobrien// allocation. 415130561Sobrien// if n is 0, lower part of src is extracted. 416130561Sobrien// if n is 1, higher part of src is extracted. 417130561Sobriendef ExtractElementF64 : 418130561Sobrien MipsPseudo<(outs CPURegs:$dst), 419130561Sobrien (ins AFGR64:$src, i32imm:$n), "", 420130561Sobrien [(set CPURegs:$dst, 421130561Sobrien (MipsExtractElementF64 AFGR64:$src, imm:$n))]>; 422130561Sobrien 423130561Sobrien//===----------------------------------------------------------------------===// 424130561Sobrien// Floating Point Patterns 425130561Sobrien//===----------------------------------------------------------------------===// 426130561Sobriendef : Pat<(f32 fpimm0), (MTC1 ZERO)>; 427130561Sobriendef : Pat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>; 428130561Sobrien 429130561Sobriendef : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVT_S_W (MTC1 CPURegs:$src))>; 430130561Sobriendef : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S FGR32:$src))>; 431130561Sobrien 432130561Sobrienlet Predicates = [NotFP64bit] in { 433130561Sobrien def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D32_W (MTC1 CPURegs:$src))>; 434130561Sobrien def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>; 435130561Sobrien def : Pat<(f32 (fround AFGR64:$src)), (CVT_S_D32 AFGR64:$src)>; 436130561Sobrien def : Pat<(f64 (fextend FGR32:$src)), (CVT_D32_S FGR32:$src)>; 437130561Sobrien} 438130561Sobrien 439130561Sobrienlet Predicates = [IsFP64bit] in { 440130561Sobrien def : Pat<(f64 fpimm0), (DMTC1 ZERO_64)>; 441130561Sobrien def : Pat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>; 442130561Sobrien 443130561Sobrien def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D64_W (MTC1 CPURegs:$src))>; 444130561Sobrien def : Pat<(f32 (sint_to_fp CPU64Regs:$src)), 445130561Sobrien (CVT_S_L (DMTC1 CPU64Regs:$src))>; 446130561Sobrien def : Pat<(f64 (sint_to_fp CPU64Regs:$src)), 447130561Sobrien (CVT_D64_L (DMTC1 CPU64Regs:$src))>; 448130561Sobrien 449130561Sobrien def : Pat<(i32 (fp_to_sint FGR64:$src)), (MFC1 (TRUNC_W_D64 FGR64:$src))>; 450130561Sobrien def : Pat<(i64 (fp_to_sint FGR32:$src)), (DMFC1 (TRUNC_L_S FGR32:$src))>; 451130561Sobrien def : Pat<(i64 (fp_to_sint FGR64:$src)), (DMFC1 (TRUNC_L_D64 FGR64:$src))>; 452130561Sobrien 453130561Sobrien def : Pat<(f32 (fround FGR64:$src)), (CVT_S_D64 FGR64:$src)>; 454130561Sobrien def : Pat<(f64 (fextend FGR32:$src)), (CVT_D64_S FGR32:$src)>; 455130561Sobrien} 456130561Sobrien 457130561Sobrien// Patterns for unaligned floating point loads and stores. 458130561Sobrienlet Predicates = [HasMips32r2Or64, NotN64] in { 459130561Sobrien def : Pat<(f32 (load_u CPURegs:$addr)), (LUXC1 CPURegs:$addr, ZERO)>; 460130561Sobrien def : Pat<(store_u FGR32:$src, CPURegs:$addr), 461130561Sobrien (SUXC1 FGR32:$src, CPURegs:$addr, ZERO)>; 462130561Sobrien} 463130561Sobrien 464130561Sobrienlet Predicates = [IsN64] in { 465130561Sobrien def : Pat<(f32 (load_u CPU64Regs:$addr)), (LUXC1_P8 CPU64Regs:$addr, ZERO_64)>; 466130561Sobrien def : Pat<(store_u FGR32:$src, CPU64Regs:$addr), 467130561Sobrien (SUXC1_P8 FGR32:$src, CPU64Regs:$addr, ZERO_64)>; 468130561Sobrien} 469130561Sobrien