1//===- MipsInstrFPU.td - Mips FPU Instruction Information --*- tablegen -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file describes the Mips FPU instruction set. 11// 12//===----------------------------------------------------------------------===// 13 14//===----------------------------------------------------------------------===// 15// Floating Point Instructions 16// ------------------------ 17// * 64bit fp: 18// - 32 64-bit registers (default mode) 19// - 16 even 32-bit registers (32-bit compatible mode) for 20// single and double access. 21// * 32bit fp: 22// - 16 even 32-bit registers - single and double (aliased) 23// - 32 32-bit registers (within single-only mode) 24//===----------------------------------------------------------------------===// 25 26// Floating Point Compare and Branch 27def SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>, 28 SDTCisVT<1, OtherVT>]>; 29def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, 30 SDTCisInt<2>]>; 31def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, 32 SDTCisSameAs<1, 2>]>; 33def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, 34 SDTCisVT<1, i32>, 35 SDTCisSameAs<1, 2>]>; 36def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, 37 SDTCisVT<1, f64>, 38 SDTCisVT<0, i32>]>; 39 40def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>; 41def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>; 42def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>; 43def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>; 44def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, 45 [SDNPHasChain, SDNPOptInGlue]>; 46def MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64", SDT_MipsBuildPairF64>; 47def MipsExtractElementF64 : SDNode<"MipsISD::ExtractElementF64", 48 SDT_MipsExtractElementF64>; 49 50// Operand for printing out a condition code. 51let PrintMethod = "printFCCOperand" in 52 def condcode : Operand<i32>; 53 54//===----------------------------------------------------------------------===// 55// Feature predicates. 56//===----------------------------------------------------------------------===// 57 58def In32BitMode : Predicate<"!Subtarget.isFP64bit()">; 59def IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">; 60def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">; 61def IsNotMipsI : Predicate<"!Subtarget.isMips1()">; 62 63//===----------------------------------------------------------------------===// 64// Instruction Class Templates 65// 66// A set of multiclasses is used to address the register usage. 67// 68// S32 - single precision in 16 32bit even fp registers 69// single precision in 32 32bit fp registers in SingleOnly mode 70// S64 - single precision in 32 64bit fp registers (In64BitMode) 71// D32 - double precision in 16 32bit even fp registers 72// D64 - double precision in 32 64bit fp registers (In64BitMode) 73// 74// Only S32 and D32 are supported right now. 75//===----------------------------------------------------------------------===// 76 77multiclass FFR1_1<bits<6> funct, string asmstr> 78{ 79 def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), 80 !strconcat(asmstr, ".s\t$fd, $fs"), []>; 81 82 def _D32 : FFR<0x11, funct, 0x1, (outs FGR32:$fd), (ins AFGR64:$fs), 83 !strconcat(asmstr, ".d\t$fd, $fs"), []>, Requires<[In32BitMode]>; 84} 85 86multiclass FFR1_2<bits<6> funct, string asmstr, SDNode FOp> 87{ 88 def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), 89 !strconcat(asmstr, ".s\t$fd, $fs"), 90 [(set FGR32:$fd, (FOp FGR32:$fs))]>; 91 92 def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs), 93 !strconcat(asmstr, ".d\t$fd, $fs"), 94 [(set AFGR64:$fd, (FOp AFGR64:$fs))]>, Requires<[In32BitMode]>; 95} 96 97class FFR1_3<bits<6> funct, bits<5> fmt, RegisterClass RcSrc, 98 RegisterClass RcDst, string asmstr>: 99 FFR<0x11, funct, fmt, (outs RcSrc:$fd), (ins RcDst:$fs), 100 !strconcat(asmstr, "\t$fd, $fs"), []>; 101 102 103multiclass FFR1_4<bits<6> funct, string asmstr, SDNode FOp, bit isComm = 0> { 104 let isCommutable = isComm in { 105 def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), 106 (ins FGR32:$fs, FGR32:$ft), 107 !strconcat(asmstr, ".s\t$fd, $fs, $ft"), 108 [(set FGR32:$fd, (FOp FGR32:$fs, FGR32:$ft))]>; 109 110 def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), 111 (ins AFGR64:$fs, AFGR64:$ft), 112 !strconcat(asmstr, ".d\t$fd, $fs, $ft"), 113 [(set AFGR64:$fd, (FOp AFGR64:$fs, AFGR64:$ft))]>, 114 Requires<[In32BitMode]>; 115 } 116} 117 118//===----------------------------------------------------------------------===// 119// Floating Point Instructions 120//===----------------------------------------------------------------------===// 121 122let ft = 0 in { 123 defm FLOOR_W : FFR1_1<0b001111, "floor.w">; 124 defm CEIL_W : FFR1_1<0b001110, "ceil.w">; 125 defm ROUND_W : FFR1_1<0b001100, "round.w">; 126 defm TRUNC_W : FFR1_1<0b001101, "trunc.w">; 127 defm CVTW : FFR1_1<0b100100, "cvt.w">; 128 129 defm FABS : FFR1_2<0b000101, "abs", fabs>; 130 defm FNEG : FFR1_2<0b000111, "neg", fneg>; 131 defm FSQRT : FFR1_2<0b000100, "sqrt", fsqrt>; 132 133 /// Convert to Single Precison 134 def CVTS_W32 : FFR1_3<0b100000, 0x2, FGR32, FGR32, "cvt.s.w">; 135 136 let Predicates = [IsNotSingleFloat] in { 137 /// Ceil to long signed integer 138 def CEIL_LS : FFR1_3<0b001010, 0x0, FGR32, FGR32, "ceil.l">; 139 def CEIL_LD : FFR1_3<0b001010, 0x1, AFGR64, AFGR64, "ceil.l">; 140 141 /// Round to long signed integer 142 def ROUND_LS : FFR1_3<0b001000, 0x0, FGR32, FGR32, "round.l">; 143 def ROUND_LD : FFR1_3<0b001000, 0x1, AFGR64, AFGR64, "round.l">; 144 145 /// Floor to long signed integer 146 def FLOOR_LS : FFR1_3<0b001011, 0x0, FGR32, FGR32, "floor.l">; 147 def FLOOR_LD : FFR1_3<0b001011, 0x1, AFGR64, AFGR64, "floor.l">; 148 149 /// Trunc to long signed integer 150 def TRUNC_LS : FFR1_3<0b001001, 0x0, FGR32, FGR32, "trunc.l">; 151 def TRUNC_LD : FFR1_3<0b001001, 0x1, AFGR64, AFGR64, "trunc.l">; 152 153 /// Convert to long signed integer 154 def CVTL_S : FFR1_3<0b100101, 0x0, FGR32, FGR32, "cvt.l">; 155 def CVTL_D : FFR1_3<0b100101, 0x1, AFGR64, AFGR64, "cvt.l">; 156 157 /// Convert to Double Precison 158 def CVTD_S32 : FFR1_3<0b100001, 0x0, AFGR64, FGR32, "cvt.d.s">; 159 def CVTD_W32 : FFR1_3<0b100001, 0x2, AFGR64, FGR32, "cvt.d.w">; 160 def CVTD_L32 : FFR1_3<0b100001, 0x3, AFGR64, AFGR64, "cvt.d.l">; 161 162 /// Convert to Single Precison 163 def CVTS_D32 : FFR1_3<0b100000, 0x1, FGR32, AFGR64, "cvt.s.d">; 164 def CVTS_L32 : FFR1_3<0b100000, 0x3, FGR32, AFGR64, "cvt.s.l">; 165 } 166} 167 168// The odd-numbered registers are only referenced when doing loads, 169// stores, and moves between floating-point and integer registers. 170// When defining instructions, we reference all 32-bit registers, 171// regardless of register aliasing. 172let fd = 0 in { 173 /// Move Control Registers From/To CPU Registers 174 def CFC1 : FFR<0x11, 0x0, 0x2, (outs CPURegs:$rt), (ins CCR:$fs), 175 "cfc1\t$rt, $fs", []>; 176 177 def CTC1 : FFR<0x11, 0x0, 0x6, (outs CCR:$rt), (ins CPURegs:$fs), 178 "ctc1\t$fs, $rt", []>; 179 180 def MFC1 : FFR<0x11, 0x00, 0x00, (outs CPURegs:$rt), (ins FGR32:$fs), 181 "mfc1\t$rt, $fs", []>; 182 183 def MTC1 : FFR<0x11, 0x00, 0x04, (outs FGR32:$fs), (ins CPURegs:$rt), 184 "mtc1\t$rt, $fs", []>; 185} 186 187def FMOV_S32 : FFR<0x11, 0b000110, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), 188 "mov.s\t$fd, $fs", []>; 189def FMOV_D32 : FFR<0x11, 0b000110, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs), 190 "mov.d\t$fd, $fs", []>; 191 192/// Floating Point Memory Instructions 193let Predicates = [IsNotSingleFloat, IsNotMipsI] in { 194 def LDC1 : FFI<0b110101, (outs AFGR64:$ft), (ins mem:$addr), 195 "ldc1\t$ft, $addr", [(set AFGR64:$ft, (load addr:$addr))]>; 196 197 def SDC1 : FFI<0b111101, (outs), (ins AFGR64:$ft, mem:$addr), 198 "sdc1\t$ft, $addr", [(store AFGR64:$ft, addr:$addr)]>; 199} 200 201// LWC1 and SWC1 can always be emitted with odd registers. 202def LWC1 : FFI<0b110001, (outs FGR32:$ft), (ins mem:$addr), "lwc1\t$ft, $addr", 203 [(set FGR32:$ft, (load addr:$addr))]>; 204def SWC1 : FFI<0b111001, (outs), (ins FGR32:$ft, mem:$addr), 205 "swc1\t$ft, $addr", [(store FGR32:$ft, addr:$addr)]>; 206 207/// Floating-point Aritmetic 208defm FADD : FFR1_4<0x10, "add", fadd, 1>; 209defm FDIV : FFR1_4<0x03, "div", fdiv>; 210defm FMUL : FFR1_4<0x02, "mul", fmul, 1>; 211defm FSUB : FFR1_4<0x01, "sub", fsub>; 212 213//===----------------------------------------------------------------------===// 214// Floating Point Branch Codes 215//===----------------------------------------------------------------------===// 216// Mips branch codes. These correspond to condcode in MipsInstrInfo.h. 217// They must be kept in synch. 218def MIPS_BRANCH_F : PatLeaf<(i32 0)>; 219def MIPS_BRANCH_T : PatLeaf<(i32 1)>; 220def MIPS_BRANCH_FL : PatLeaf<(i32 2)>; 221def MIPS_BRANCH_TL : PatLeaf<(i32 3)>; 222 223/// Floating Point Branch of False/True (Likely) 224let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in 225 class FBRANCH<PatLeaf op, string asmstr> : FFI<0x11, (outs), 226 (ins brtarget:$dst), !strconcat(asmstr, "\t$dst"), 227 [(MipsFPBrcond op, bb:$dst)]>; 228 229def BC1F : FBRANCH<MIPS_BRANCH_F, "bc1f">; 230def BC1T : FBRANCH<MIPS_BRANCH_T, "bc1t">; 231def BC1FL : FBRANCH<MIPS_BRANCH_FL, "bc1fl">; 232def BC1TL : FBRANCH<MIPS_BRANCH_TL, "bc1tl">; 233 234//===----------------------------------------------------------------------===// 235// Floating Point Flag Conditions 236//===----------------------------------------------------------------------===// 237// Mips condition codes. They must correspond to condcode in MipsInstrInfo.h. 238// They must be kept in synch. 239def MIPS_FCOND_F : PatLeaf<(i32 0)>; 240def MIPS_FCOND_UN : PatLeaf<(i32 1)>; 241def MIPS_FCOND_OEQ : PatLeaf<(i32 2)>; 242def MIPS_FCOND_UEQ : PatLeaf<(i32 3)>; 243def MIPS_FCOND_OLT : PatLeaf<(i32 4)>; 244def MIPS_FCOND_ULT : PatLeaf<(i32 5)>; 245def MIPS_FCOND_OLE : PatLeaf<(i32 6)>; 246def MIPS_FCOND_ULE : PatLeaf<(i32 7)>; 247def MIPS_FCOND_SF : PatLeaf<(i32 8)>; 248def MIPS_FCOND_NGLE : PatLeaf<(i32 9)>; 249def MIPS_FCOND_SEQ : PatLeaf<(i32 10)>; 250def MIPS_FCOND_NGL : PatLeaf<(i32 11)>; 251def MIPS_FCOND_LT : PatLeaf<(i32 12)>; 252def MIPS_FCOND_NGE : PatLeaf<(i32 13)>; 253def MIPS_FCOND_LE : PatLeaf<(i32 14)>; 254def MIPS_FCOND_NGT : PatLeaf<(i32 15)>; 255 256/// Floating Point Compare 257let hasDelaySlot = 1, Defs=[FCR31] in { 258 def FCMP_S32 : FCC<0x0, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc), 259 "c.$cc.s\t$fs, $ft", 260 [(MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc)]>; 261 262 def FCMP_D32 : FCC<0x1, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc), 263 "c.$cc.d\t$fs, $ft", 264 [(MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc)]>, 265 Requires<[In32BitMode]>; 266} 267 268 269// Conditional moves: 270// These instructions are expanded in 271// MipsISelLowering::EmitInstrWithCustomInserter if target does not have 272// conditional move instructions. 273// flag:int, data:float 274let usesCustomInserter = 1, Constraints = "$F = $dst" in 275class CondMovIntFP<RegisterClass RC, bits<5> fmt, bits<6> func, 276 string instr_asm> : 277 FFR<0x11, func, fmt, (outs RC:$dst), (ins RC:$T, CPURegs:$cond, RC:$F), 278 !strconcat(instr_asm, "\t$dst, $T, $cond"), []>; 279 280def MOVZ_S : CondMovIntFP<FGR32, 16, 18, "movz.s">; 281def MOVN_S : CondMovIntFP<FGR32, 16, 19, "movn.s">; 282 283let Predicates = [In32BitMode] in { 284 def MOVZ_D : CondMovIntFP<AFGR64, 17, 18, "movz.d">; 285 def MOVN_D : CondMovIntFP<AFGR64, 17, 19, "movn.d">; 286} 287 288defm : MovzPats<FGR32, MOVZ_S>; 289defm : MovnPats<FGR32, MOVN_S>; 290 291let Predicates = [In32BitMode] in { 292 defm : MovzPats<AFGR64, MOVZ_D>; 293 defm : MovnPats<AFGR64, MOVN_D>; 294} 295 296let usesCustomInserter = 1, Uses = [FCR31], Constraints = "$F = $dst" in { 297// flag:float, data:int 298class CondMovFPInt<SDNode cmov, bits<1> tf, string instr_asm> : 299 FCMOV<tf, (outs CPURegs:$dst), (ins CPURegs:$T, CPURegs:$F), 300 !strconcat(instr_asm, "\t$dst, $T, $$fcc0"), 301 [(set CPURegs:$dst, (cmov CPURegs:$T, CPURegs:$F))]>; 302 303// flag:float, data:float 304class CondMovFPFP<RegisterClass RC, SDNode cmov, bits<5> fmt, bits<1> tf, 305 string instr_asm> : 306 FFCMOV<fmt, tf, (outs RC:$dst), (ins RC:$T, RC:$F), 307 !strconcat(instr_asm, "\t$dst, $T, $$fcc0"), 308 [(set RC:$dst, (cmov RC:$T, RC:$F))]>; 309} 310 311def MOVT : CondMovFPInt<MipsCMovFP_T, 1, "movt">; 312def MOVF : CondMovFPInt<MipsCMovFP_F, 0, "movf">; 313def MOVT_S : CondMovFPFP<FGR32, MipsCMovFP_T, 16, 1, "movt.s">; 314def MOVF_S : CondMovFPFP<FGR32, MipsCMovFP_F, 16, 0, "movf.s">; 315 316let Predicates = [In32BitMode] in { 317 def MOVT_D : CondMovFPFP<AFGR64, MipsCMovFP_T, 17, 1, "movt.d">; 318 def MOVF_D : CondMovFPFP<AFGR64, MipsCMovFP_F, 17, 0, "movf.d">; 319} 320 321//===----------------------------------------------------------------------===// 322// Floating Point Pseudo-Instructions 323//===----------------------------------------------------------------------===// 324def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src), 325 "# MOVCCRToCCR", []>; 326 327// This pseudo instr gets expanded into 2 mtc1 instrs after register 328// allocation. 329def BuildPairF64 : 330 MipsPseudo<(outs AFGR64:$dst), 331 (ins CPURegs:$lo, CPURegs:$hi), "", 332 [(set AFGR64:$dst, (MipsBuildPairF64 CPURegs:$lo, CPURegs:$hi))]>; 333 334// This pseudo instr gets expanded into 2 mfc1 instrs after register 335// allocation. 336// if n is 0, lower part of src is extracted. 337// if n is 1, higher part of src is extracted. 338def ExtractElementF64 : 339 MipsPseudo<(outs CPURegs:$dst), 340 (ins AFGR64:$src, i32imm:$n), "", 341 [(set CPURegs:$dst, 342 (MipsExtractElementF64 AFGR64:$src, imm:$n))]>; 343 344//===----------------------------------------------------------------------===// 345// Floating Point Patterns 346//===----------------------------------------------------------------------===// 347def fpimm0 : PatLeaf<(fpimm), [{ 348 return N->isExactlyValue(+0.0); 349}]>; 350 351def fpimm0neg : PatLeaf<(fpimm), [{ 352 return N->isExactlyValue(-0.0); 353}]>; 354 355def : Pat<(f32 fpimm0), (MTC1 ZERO)>; 356def : Pat<(f32 fpimm0neg), (FNEG_S32 (MTC1 ZERO))>; 357 358def : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVTS_W32 (MTC1 CPURegs:$src))>; 359def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVTD_W32 (MTC1 CPURegs:$src))>; 360 361def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S32 FGR32:$src))>; 362def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>; 363 364def : Pat<(i32 (bitconvert FGR32:$src)), (MFC1 FGR32:$src)>; 365def : Pat<(f32 (bitconvert CPURegs:$src)), (MTC1 CPURegs:$src)>; 366 367let Predicates = [In32BitMode] in { 368 def : Pat<(f32 (fround AFGR64:$src)), (CVTS_D32 AFGR64:$src)>; 369 def : Pat<(f64 (fextend FGR32:$src)), (CVTD_S32 FGR32:$src)>; 370} 371 372// MipsFPRound is only emitted for MipsI targets. 373def : Pat<(f32 (MipsFPRound AFGR64:$src)), (CVTW_D32 AFGR64:$src)>; 374 375