R600/SI: SI support for 64bit ConstantFP
[oota-llvm.git] / lib / Target / R600 / SIInstrInfo.td
1 //===-- SIInstrInfo.td - SI Instruction Infos -------------*- 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 //===----------------------------------------------------------------------===//
11 // SI DAG Nodes
12 //===----------------------------------------------------------------------===//
13
14 // SMRD takes a 64bit memory address and can only add an 32bit offset
15 def SIadd64bit32bit : SDNode<"ISD::ADD",
16   SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisVT<0, i64>, SDTCisVT<2, i32>]>
17 >;
18
19 // Transformation function, extract the lower 32bit of a 64bit immediate
20 def LO32 : SDNodeXForm<imm, [{
21   return CurDAG->getTargetConstant(N->getZExtValue() & 0xffffffff, MVT::i32);
22 }]>;
23
24 def LO32f : SDNodeXForm<fpimm, [{
25   uint64_t val = N->getValueAPF().bitcastToAPInt().getZExtValue() & 0xffffffff;
26   float *fval = reinterpret_cast<float *>(&val);
27   return CurDAG->getTargetConstantFP(*fval, MVT::f32);
28 }]>;
29
30 // Transformation function, extract the upper 32bit of a 64bit immediate
31 def HI32 : SDNodeXForm<imm, [{
32   return CurDAG->getTargetConstant(N->getZExtValue() >> 32, MVT::i32);
33 }]>;
34
35 def HI32f : SDNodeXForm<fpimm, [{
36   uint64_t val = N->getValueAPF().bitcastToAPInt().getZExtValue() >> 32;
37   float *fval = reinterpret_cast<float *>(&val);
38   return CurDAG->getTargetConstantFP(*fval, MVT::f32);
39 }]>;
40
41 def IMM8bitDWORD : ImmLeaf <
42   i32, [{
43     return (Imm & ~0x3FC) == 0;
44   }], SDNodeXForm<imm, [{
45     return CurDAG->getTargetConstant(
46       N->getZExtValue() >> 2, MVT::i32);
47   }]>
48 >;
49
50 def as_i16imm : SDNodeXForm<imm, [{
51   return CurDAG->getTargetConstant(N->getSExtValue(), MVT::i16);
52 }]>;
53
54 def IMM12bit : PatLeaf <(imm),
55   [{return isUInt<12>(N->getZExtValue());}]
56 >;
57
58 class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{
59   return
60     (*(const SITargetLowering *)getTargetLowering()).analyzeImmediate(N) == 0;
61 }]>;
62
63 //===----------------------------------------------------------------------===//
64 // SI assembler operands
65 //===----------------------------------------------------------------------===//
66
67 def SIOperand {
68   int ZERO = 0x80;
69   int VCC = 0x6A;
70 }
71
72 include "SIInstrFormats.td"
73
74 //===----------------------------------------------------------------------===//
75 //
76 // SI Instruction multiclass helpers.
77 //
78 // Instructions with _32 take 32-bit operands.
79 // Instructions with _64 take 64-bit operands.
80 //
81 // VOP_* instructions can use either a 32-bit or 64-bit encoding.  The 32-bit
82 // encoding is the standard encoding, but instruction that make use of
83 // any of the instruction modifiers must use the 64-bit encoding.
84 //
85 // Instructions with _e32 use the 32-bit encoding.
86 // Instructions with _e64 use the 64-bit encoding.
87 //
88 //===----------------------------------------------------------------------===//
89
90 //===----------------------------------------------------------------------===//
91 // Scalar classes
92 //===----------------------------------------------------------------------===//
93
94 class SOP1_32 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
95   op, (outs SReg_32:$dst), (ins SSrc_32:$src0),
96   opName#" $dst, $src0", pattern
97 >;
98
99 class SOP1_64 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
100   op, (outs SReg_64:$dst), (ins SSrc_64:$src0),
101   opName#" $dst, $src0", pattern
102 >;
103
104 class SOP2_32 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
105   op, (outs SReg_32:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
106   opName#" $dst, $src0, $src1", pattern
107 >;
108
109 class SOP2_64 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
110   op, (outs SReg_64:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
111   opName#" $dst, $src0, $src1", pattern
112 >;
113
114 class SOPC_32 <bits<7> op, string opName, list<dag> pattern> : SOPC <
115   op, (outs SCCReg:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
116   opName#" $dst, $src0, $src1", pattern
117 >;
118
119 class SOPC_64 <bits<7> op, string opName, list<dag> pattern> : SOPC <
120   op, (outs SCCReg:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
121   opName#" $dst, $src0, $src1", pattern
122 >;
123
124 class SOPK_32 <bits<5> op, string opName, list<dag> pattern> : SOPK <
125   op, (outs SReg_32:$dst), (ins i16imm:$src0),
126   opName#" $dst, $src0", pattern
127 >;
128
129 class SOPK_64 <bits<5> op, string opName, list<dag> pattern> : SOPK <
130   op, (outs SReg_64:$dst), (ins i16imm:$src0),
131   opName#" $dst, $src0", pattern
132 >;
133
134 multiclass SMRD_Helper <bits<5> op, string asm, RegisterClass baseClass,
135                         RegisterClass dstClass> {
136   def _IMM : SMRD <
137     op, 1, (outs dstClass:$dst),
138     (ins baseClass:$sbase, i32imm:$offset),
139     asm#" $dst, $sbase, $offset", []
140   >;
141
142   def _SGPR : SMRD <
143     op, 0, (outs dstClass:$dst),
144     (ins baseClass:$sbase, SReg_32:$soff),
145     asm#" $dst, $sbase, $soff", []
146   >;
147 }
148
149 //===----------------------------------------------------------------------===//
150 // Vector ALU classes
151 //===----------------------------------------------------------------------===//
152
153 class VOP <string opName> {
154   string OpName = opName;
155 }
156
157 class VOP2_REV <string revOp, bit isOrig> {
158   string RevOp = revOp;
159   bit IsOrig = isOrig;
160 }
161
162 multiclass VOP1_Helper <bits<8> op, RegisterClass drc, RegisterClass src,
163                         string opName, list<dag> pattern> {
164
165   def _e32 : VOP1 <
166     op, (outs drc:$dst), (ins src:$src0),
167     opName#"_e32 $dst, $src0", pattern
168   >, VOP <opName>;
169
170   def _e64 : VOP3 <
171     {1, 1, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
172     (outs drc:$dst),
173     (ins src:$src0,
174          i32imm:$abs, i32imm:$clamp,
175          i32imm:$omod, i32imm:$neg),
176     opName#"_e64 $dst, $src0, $abs, $clamp, $omod, $neg", []
177   >, VOP <opName> {
178     let src1 = SIOperand.ZERO;
179     let src2 = SIOperand.ZERO;
180   }
181 }
182
183 multiclass VOP1_32 <bits<8> op, string opName, list<dag> pattern>
184   : VOP1_Helper <op, VReg_32, VSrc_32, opName, pattern>;
185
186 multiclass VOP1_64 <bits<8> op, string opName, list<dag> pattern>
187   : VOP1_Helper <op, VReg_64, VSrc_64, opName, pattern>;
188
189 multiclass VOP2_Helper <bits<6> op, RegisterClass vrc, RegisterClass arc,
190                         string opName, list<dag> pattern, string revOp> {
191   def _e32 : VOP2 <
192     op, (outs vrc:$dst), (ins arc:$src0, vrc:$src1),
193     opName#"_e32 $dst, $src0, $src1", pattern
194   >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
195
196   def _e64 : VOP3 <
197     {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
198     (outs vrc:$dst),
199     (ins arc:$src0, arc:$src1,
200          i32imm:$abs, i32imm:$clamp,
201          i32imm:$omod, i32imm:$neg),
202     opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
203   >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
204     let src2 = SIOperand.ZERO;
205   }
206 }
207
208 multiclass VOP2_32 <bits<6> op, string opName, list<dag> pattern,
209                     string revOp = opName>
210   : VOP2_Helper <op, VReg_32, VSrc_32, opName, pattern, revOp>;
211
212 multiclass VOP2_64 <bits<6> op, string opName, list<dag> pattern,
213                     string revOp = opName>
214   : VOP2_Helper <op, VReg_64, VSrc_64, opName, pattern, revOp>;
215
216 multiclass VOP2b_32 <bits<6> op, string opName, list<dag> pattern,
217                      string revOp = opName> {
218
219   def _e32 : VOP2 <
220     op, (outs VReg_32:$dst), (ins VSrc_32:$src0, VReg_32:$src1),
221     opName#"_e32 $dst, $src0, $src1", pattern
222   >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
223
224   def _e64 : VOP3b <
225     {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
226     (outs VReg_32:$dst),
227     (ins VSrc_32:$src0, VSrc_32:$src1,
228          i32imm:$abs, i32imm:$clamp,
229          i32imm:$omod, i32imm:$neg),
230     opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
231   >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
232     let src2 = SIOperand.ZERO;
233     /* the VOP2 variant puts the carry out into VCC, the VOP3 variant
234        can write it into any SGPR. We currently don't use the carry out,
235        so for now hardcode it to VCC as well */
236     let sdst = SIOperand.VCC;
237   }
238 }
239
240 multiclass VOPC_Helper <bits<8> op, RegisterClass vrc, RegisterClass arc,
241                         string opName, ValueType vt, PatLeaf cond> {
242
243   def _e32 : VOPC <
244     op, (ins arc:$src0, vrc:$src1),
245     opName#"_e32 $dst, $src0, $src1", []
246   >, VOP <opName>;
247
248   def _e64 : VOP3 <
249     {0, op{7}, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
250     (outs SReg_64:$dst),
251     (ins arc:$src0, arc:$src1,
252          InstFlag:$abs, InstFlag:$clamp,
253          InstFlag:$omod, InstFlag:$neg),
254     opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg",
255     !if(!eq(!cast<string>(cond), "COND_NULL"), []<dag>,
256       [(set SReg_64:$dst, (i1 (setcc (vt arc:$src0), arc:$src1, cond)))]
257     )
258   >, VOP <opName> {
259     let src2 = SIOperand.ZERO;
260   }
261 }
262
263 multiclass VOPC_32 <bits<8> op, string opName,
264   ValueType vt = untyped, PatLeaf cond = COND_NULL>
265   : VOPC_Helper <op, VReg_32, VSrc_32, opName, vt, cond>;
266
267 multiclass VOPC_64 <bits<8> op, string opName,
268   ValueType vt = untyped, PatLeaf cond = COND_NULL>
269   : VOPC_Helper <op, VReg_64, VSrc_64, opName, vt, cond>;
270
271 class VOP3_32 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
272   op, (outs VReg_32:$dst),
273   (ins VSrc_32:$src0, VSrc_32:$src1, VSrc_32:$src2,
274    InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
275   opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
276 >, VOP <opName>;
277
278 class VOP3_64_Shift <bits <9> op, string opName, list<dag> pattern> : VOP3 <
279   op, (outs VReg_64:$dst),
280   (ins VSrc_64:$src0, VSrc_32:$src1),
281   opName#" $dst, $src0, $src1", pattern
282 >, VOP <opName> {
283
284   let src2 = SIOperand.ZERO;
285   let abs = 0;
286   let clamp = 0;
287   let omod = 0;
288   let neg = 0;
289 }
290
291 class VOP3_64 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
292   op, (outs VReg_64:$dst),
293   (ins VSrc_64:$src0, VSrc_64:$src1, VSrc_64:$src2,
294    InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
295   opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
296 >, VOP <opName>;
297
298 //===----------------------------------------------------------------------===//
299 // Vector I/O classes
300 //===----------------------------------------------------------------------===//
301
302 class DS_Load_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
303   op,
304   (outs regClass:$vdst),
305   (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
306        i8imm:$offset0, i8imm:$offset1),
307   asm#" $vdst, $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
308   []> {
309   let mayLoad = 1;
310   let mayStore = 0;
311 }
312
313 class DS_Store_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
314   op,
315   (outs),
316   (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
317        i8imm:$offset0, i8imm:$offset1),
318   asm#" $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
319   []> {
320   let mayStore = 1;
321   let mayLoad = 0;
322   let vdst = 0;
323 }
324
325 class MTBUF_Store_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
326   op,
327   (outs),
328   (ins regClass:$vdata, i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc,
329    i1imm:$addr64, i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr,
330    SReg_128:$srsrc, i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
331   asm#" $vdata, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
332      #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
333   []> {
334   let mayStore = 1;
335   let mayLoad = 0;
336 }
337
338 multiclass MUBUF_Load_Helper <bits<7> op, string asm, RegisterClass regClass> {
339
340   let glc = 0, lds = 0, slc = 0, tfe = 0, soffset = 128 /* ZERO */,
341                                           mayLoad = 1 in {
342
343   let offen = 1, idxen = 0, addr64 = 0, offset = 0 in {
344     def _OFFEN  : MUBUF <op, (outs regClass:$vdata),
345                          (ins SReg_128:$srsrc, VReg_32:$vaddr),
346                          asm#" $vdata, $srsrc + $vaddr", []>;
347   }
348
349   let offen = 0, idxen = 1, addr64 = 0 in {
350     def _IDXEN  : MUBUF <op, (outs regClass:$vdata),
351                          (ins SReg_128:$srsrc, VReg_32:$vaddr, i16imm:$offset),
352                          asm#" $vdata, $srsrc[$vaddr] + $offset", []>;
353   }
354
355   let offen = 0, idxen = 0, addr64 = 1 in {
356     def _ADDR64 : MUBUF <op, (outs regClass:$vdata),
357                          (ins SReg_128:$srsrc, VReg_64:$vaddr, i16imm:$offset),
358                          asm#" $vdata, $srsrc + $vaddr + $offset", []>;
359   }
360   }
361 }
362
363 class MUBUF_Store_Helper <bits<7> op, string name, RegisterClass vdataClass,
364                          ValueType VT> :
365     MUBUF <op, (outs), (ins vdataClass:$vdata, SReg_128:$srsrc, VReg_64:$vaddr, i16imm:$offset),
366           name#" $vdata, $srsrc + $vaddr + $offset",
367          []> {
368
369   let mayLoad = 0;
370   let mayStore = 1;
371
372   // Encoding
373   let offen = 0;
374   let idxen = 0;
375   let glc = 0;
376   let addr64 = 1;
377   let lds = 0;
378   let slc = 0;
379   let tfe = 0;
380   let soffset = 128; // ZERO
381 }
382
383 class MTBUF_Load_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
384   op,
385   (outs regClass:$dst),
386   (ins i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc, i1imm:$addr64,
387        i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr, SReg_128:$srsrc,
388        i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
389   asm#" $dst, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
390      #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
391   []> {
392   let mayLoad = 1;
393   let mayStore = 0;
394 }
395
396 class MIMG_NoSampler_Helper <bits<7> op, string asm> : MIMG <
397   op,
398   (outs VReg_128:$vdata),
399   (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
400        i1imm:$tfe, i1imm:$lwe, i1imm:$slc, unknown:$vaddr,
401        SReg_256:$srsrc),
402   asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
403      #" $tfe, $lwe, $slc, $vaddr, $srsrc",
404   []> {
405   let SSAMP = 0;
406   let mayLoad = 1;
407   let mayStore = 0;
408   let hasPostISelHook = 1;
409 }
410
411 class MIMG_Sampler_Helper <bits<7> op, string asm> : MIMG <
412   op,
413   (outs VReg_128:$vdata),
414   (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
415        i1imm:$tfe, i1imm:$lwe, i1imm:$slc, unknown:$vaddr,
416        SReg_256:$srsrc, SReg_128:$ssamp),
417   asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
418      #" $tfe, $lwe, $slc, $vaddr, $srsrc, $ssamp",
419   []> {
420   let mayLoad = 1;
421   let mayStore = 0;
422   let hasPostISelHook = 1;
423 }
424
425 //===----------------------------------------------------------------------===//
426 // Vector instruction mappings
427 //===----------------------------------------------------------------------===//
428
429 // Maps an opcode in e32 form to its e64 equivalent
430 def getVOPe64 : InstrMapping {
431   let FilterClass = "VOP";
432   let RowFields = ["OpName"];
433   let ColFields = ["Size"];
434   let KeyCol = ["4"];
435   let ValueCols = [["8"]];
436 }
437
438 // Maps an original opcode to its commuted version
439 def getCommuteRev : InstrMapping {
440   let FilterClass = "VOP2_REV";
441   let RowFields = ["RevOp"];
442   let ColFields = ["IsOrig"];
443   let KeyCol = ["1"];
444   let ValueCols = [["0"]];
445 }
446
447 // Maps an commuted opcode to its original version
448 def getCommuteOrig : InstrMapping {
449   let FilterClass = "VOP2_REV";
450   let RowFields = ["RevOp"];
451   let ColFields = ["IsOrig"];
452   let KeyCol = ["0"];
453   let ValueCols = [["1"]];
454 }
455
456 // Test if the supplied opcode is an MIMG instruction
457 def isMIMG : InstrMapping {
458   let FilterClass = "MIMG";
459   let RowFields = ["Inst"];
460   let ColFields = ["Size"];
461   let KeyCol = ["8"];
462   let ValueCols = [["8"]];
463 }
464
465 include "SIInstructions.td"