]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/Target/Mips/MipsInstrFPU.td
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / lib / Target / Mips / MipsInstrFPU.td
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
27 def SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>,
28                                             SDTCisVT<1, OtherVT>]>;
29 def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>,
30                                          SDTCisInt<2>]>;
31 def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
32                                           SDTCisSameAs<1, 2>]>;
33 def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>,
34                                                 SDTCisVT<1, i32>,
35                                                 SDTCisSameAs<1, 2>]>;
36 def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>,
37                                                      SDTCisVT<1, f64>,
38                                                      SDTCisVT<0, i32>]>;
39
40 def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>;
41 def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>;
42 def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>;
43 def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>;
44 def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond,
45                           [SDNPHasChain, SDNPOptInGlue]>;
46 def MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64", SDT_MipsBuildPairF64>;
47 def MipsExtractElementF64 : SDNode<"MipsISD::ExtractElementF64",
48                                    SDT_MipsExtractElementF64>;
49
50 // Operand for printing out a condition code.
51 let PrintMethod = "printFCCOperand" in
52   def condcode : Operand<i32>;
53
54 //===----------------------------------------------------------------------===//
55 // Feature predicates.
56 //===----------------------------------------------------------------------===//
57
58 def In32BitMode      : Predicate<"!Subtarget.isFP64bit()">;
59 def IsSingleFloat    : Predicate<"Subtarget.isSingleFloat()">;
60 def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">;
61 def 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
77 multiclass 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
86 multiclass 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
97 class 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
103 multiclass 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
122 let 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.
172 let 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
187 def FMOV_S32 : FFR<0x11, 0b000110, 0x0, (outs FGR32:$fd), (ins FGR32:$fs),
188                    "mov.s\t$fd, $fs", []>;
189 def FMOV_D32 : FFR<0x11, 0b000110, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs),
190                    "mov.d\t$fd, $fs", []>;
191
192 /// Floating Point Memory Instructions
193 let 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.
202 def LWC1  : FFI<0b110001, (outs FGR32:$ft), (ins mem:$addr), "lwc1\t$ft, $addr",
203                [(set FGR32:$ft, (load addr:$addr))]>;
204 def SWC1  : FFI<0b111001, (outs), (ins FGR32:$ft, mem:$addr),
205                "swc1\t$ft, $addr", [(store FGR32:$ft, addr:$addr)]>;
206
207 /// Floating-point Aritmetic
208 defm FADD : FFR1_4<0x10, "add", fadd, 1>;
209 defm FDIV : FFR1_4<0x03, "div", fdiv>;
210 defm FMUL : FFR1_4<0x02, "mul", fmul, 1>;
211 defm 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.
218 def MIPS_BRANCH_F  : PatLeaf<(i32 0)>;
219 def MIPS_BRANCH_T  : PatLeaf<(i32 1)>;
220 def MIPS_BRANCH_FL : PatLeaf<(i32 2)>;
221 def MIPS_BRANCH_TL : PatLeaf<(i32 3)>;
222
223 /// Floating Point Branch of False/True (Likely)
224 let 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
229 def BC1F  : FBRANCH<MIPS_BRANCH_F,  "bc1f">;
230 def BC1T  : FBRANCH<MIPS_BRANCH_T,  "bc1t">;
231 def BC1FL : FBRANCH<MIPS_BRANCH_FL, "bc1fl">;
232 def 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.
239 def MIPS_FCOND_F    : PatLeaf<(i32 0)>;
240 def MIPS_FCOND_UN   : PatLeaf<(i32 1)>;
241 def MIPS_FCOND_OEQ  : PatLeaf<(i32 2)>;
242 def MIPS_FCOND_UEQ  : PatLeaf<(i32 3)>;
243 def MIPS_FCOND_OLT  : PatLeaf<(i32 4)>;
244 def MIPS_FCOND_ULT  : PatLeaf<(i32 5)>;
245 def MIPS_FCOND_OLE  : PatLeaf<(i32 6)>;
246 def MIPS_FCOND_ULE  : PatLeaf<(i32 7)>;
247 def MIPS_FCOND_SF   : PatLeaf<(i32 8)>;
248 def MIPS_FCOND_NGLE : PatLeaf<(i32 9)>;
249 def MIPS_FCOND_SEQ  : PatLeaf<(i32 10)>;
250 def MIPS_FCOND_NGL  : PatLeaf<(i32 11)>;
251 def MIPS_FCOND_LT   : PatLeaf<(i32 12)>;
252 def MIPS_FCOND_NGE  : PatLeaf<(i32 13)>;
253 def MIPS_FCOND_LE   : PatLeaf<(i32 14)>;
254 def MIPS_FCOND_NGT  : PatLeaf<(i32 15)>;
255
256 /// Floating Point Compare
257 let 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
274 let usesCustomInserter = 1, Constraints = "$F = $dst" in
275 class 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
280 def MOVZ_S : CondMovIntFP<FGR32, 16, 18, "movz.s">;
281 def MOVN_S : CondMovIntFP<FGR32, 16, 19, "movn.s">;
282
283 let 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
288 defm : MovzPats<FGR32, MOVZ_S>;
289 defm : MovnPats<FGR32, MOVN_S>;
290
291 let Predicates = [In32BitMode] in {
292   defm : MovzPats<AFGR64, MOVZ_D>;
293   defm : MovnPats<AFGR64, MOVN_D>;
294 }
295
296 let usesCustomInserter = 1, Uses = [FCR31], Constraints = "$F = $dst" in {
297 // flag:float, data:int
298 class 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
304 class 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
311 def MOVT : CondMovFPInt<MipsCMovFP_T, 1, "movt">;
312 def MOVF : CondMovFPInt<MipsCMovFP_F, 0, "movf">;
313 def MOVT_S : CondMovFPFP<FGR32, MipsCMovFP_T, 16, 1, "movt.s">;
314 def MOVF_S : CondMovFPFP<FGR32, MipsCMovFP_F, 16, 0, "movf.s">;
315
316 let 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 //===----------------------------------------------------------------------===//
324 def 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.
329 def 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.
338 def 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 //===----------------------------------------------------------------------===//
347 def fpimm0 : PatLeaf<(fpimm), [{
348   return N->isExactlyValue(+0.0);
349 }]>;
350
351 def fpimm0neg : PatLeaf<(fpimm), [{
352   return N->isExactlyValue(-0.0);
353 }]>;
354
355 def : Pat<(f32 fpimm0), (MTC1 ZERO)>;
356 def : Pat<(f32 fpimm0neg), (FNEG_S32 (MTC1 ZERO))>;
357
358 def : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVTS_W32 (MTC1 CPURegs:$src))>;
359 def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVTD_W32 (MTC1 CPURegs:$src))>;
360
361 def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S32 FGR32:$src))>;
362 def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>;
363
364 def : Pat<(i32 (bitconvert FGR32:$src)),  (MFC1 FGR32:$src)>;
365 def : Pat<(f32 (bitconvert CPURegs:$src)), (MTC1 CPURegs:$src)>;
366
367 let 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.
373 def : Pat<(f32 (MipsFPRound AFGR64:$src)), (CVTW_D32 AFGR64:$src)>;
374