Merge remote branch 'origin/master' into nv50-compiler
[mesa.git] / src / gallium / drivers / nv50 / nv50_pc.h
1 /*
2 * Copyright 2010 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #ifndef __NV50_COMPILER_H__
24 #define __NV50_COMPILER_H__
25
26 #ifdef NV50PC_DEBUG
27 # define NV50_DBGMSG(args...) debug_printf(args)
28 #else
29 # define NV50_DBGMSG(args...)
30 #endif
31
32 #include "pipe/p_defines.h"
33 #include "util/u_inlines.h"
34 #include "util/u_memory.h"
35
36 #define NV_OP_PHI 0
37 #define NV_OP_EXTRACT 1
38 #define NV_OP_COMBINE 2
39 #define NV_OP_LDA 3
40 #define NV_OP_STA 4
41 #define NV_OP_MOV 5
42 #define NV_OP_ADD 6
43 #define NV_OP_SUB 7
44 #define NV_OP_NEG 8
45 #define NV_OP_MUL 9
46 #define NV_OP_MAD 10
47 #define NV_OP_CVT 11
48 #define NV_OP_SAT 12
49 #define NV_OP_NOT 13
50 #define NV_OP_AND 14
51 #define NV_OP_OR 15
52 #define NV_OP_XOR 16
53 #define NV_OP_SHL 17
54 #define NV_OP_SHR 18
55 #define NV_OP_RCP 19
56 #define NV_OP_UNDEF 20
57 #define NV_OP_RSQ 21
58 #define NV_OP_LG2 22
59 #define NV_OP_SIN 23
60 #define NV_OP_COS 24
61 #define NV_OP_EX2 25
62 #define NV_OP_PRESIN 26
63 #define NV_OP_PREEX2 27
64 #define NV_OP_MIN 28
65 #define NV_OP_MAX 29
66 #define NV_OP_SET 30
67 #define NV_OP_SAD 31
68 #define NV_OP_KIL 32
69 #define NV_OP_BRA 33
70 #define NV_OP_CALL 34
71 #define NV_OP_RET 35
72 #define NV_OP_BREAK 36
73 #define NV_OP_BREAKADDR 37
74 #define NV_OP_JOINAT 38
75 #define NV_OP_TEX 39
76 #define NV_OP_TXB 40
77 #define NV_OP_TXL 41
78 #define NV_OP_TXF 42
79 #define NV_OP_TXQ 43
80 #define NV_OP_DFDX 44
81 #define NV_OP_DFDY 45
82 #define NV_OP_QUADOP 46
83 #define NV_OP_LINTERP 47
84 #define NV_OP_PINTERP 48
85 #define NV_OP_ABS 49
86 #define NV_OP_CEIL 50
87 #define NV_OP_FLOOR 51
88 #define NV_OP_TRUNC 52
89 #define NV_OP_NOP 53
90 #define NV_OP_SELECT 54
91 #define NV_OP_EXPORT 55
92 #define NV_OP_JOIN 56
93 #define NV_OP_COUNT 57
94
95 #define NV_FILE_GPR 0
96 #define NV_FILE_OUT 1
97 #define NV_FILE_ADDR 2
98 #define NV_FILE_FLAGS 3
99 #define NV_FILE_IMM 16
100 #define NV_FILE_MEM_S 32
101 #define NV_FILE_MEM_P 33
102 #define NV_FILE_MEM_V 34
103 #define NV_FILE_MEM_L 48
104 #define NV_FILE_MEM_G(i) (64 + i)
105 #define NV_FILE_MEM_C(i) (80 + i)
106
107 #define NV_MOD_NEG 1
108 #define NV_MOD_ABS 2
109 #define NV_MOD_NOT 4
110 #define NV_MOD_SAT 8
111
112 #define NV_TYPE_U8 0x00
113 #define NV_TYPE_S8 0x01
114 #define NV_TYPE_U16 0x02
115 #define NV_TYPE_S16 0x03
116 #define NV_TYPE_U32 0x04
117 #define NV_TYPE_S32 0x05
118 #define NV_TYPE_P32 0x07
119 #define NV_TYPE_F32 0x09
120 #define NV_TYPE_F64 0x0b
121 #define NV_TYPE_VEC(x, n) (NV_TYPE_##x | (n << 4))
122 #define NV_TYPE_LO 0x00
123 #define NV_TYPE_HI 0x80
124 #define NV_TYPE_ANY 0xff
125
126 #define NV_TYPE_ISINT(t) ((t) <= 5)
127 #define NV_TYPE_ISFLT(t) ((t) & 0x08)
128
129 /* $cX registers contain 4 bits: OCSZ (Z is bit 0) */
130 #define NV_CC_FL 0x0
131 #define NV_CC_LT 0x1
132 #define NV_CC_EQ 0x2
133 #define NV_CC_LE 0x3
134 #define NV_CC_GT 0x4
135 #define NV_CC_NE 0x5
136 #define NV_CC_GE 0x6
137 #define NV_CC_U 0x8
138 #define NV_CC_TR 0xf
139 #define NV_CC_O 0x10
140 #define NV_CC_C 0x11
141 #define NV_CC_A 0x12
142 #define NV_CC_S 0x13
143
144 #define NV_PC_MAX_INSTRUCTIONS 2048
145 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
146
147 static INLINE boolean
148 nv_is_vector_op(uint opcode)
149 {
150 return (opcode >= NV_OP_TEX) && (opcode <= NV_OP_TXQ);
151 }
152
153 static INLINE uint
154 nv_type_order(ubyte type)
155 {
156 switch (type & 0xf) {
157 case NV_TYPE_U8:
158 case NV_TYPE_S8:
159 return 0;
160 case NV_TYPE_U16:
161 case NV_TYPE_S16:
162 return 1;
163 case NV_TYPE_U32:
164 case NV_TYPE_F32:
165 case NV_TYPE_S32:
166 case NV_TYPE_P32:
167 return 2;
168 case NV_TYPE_F64:
169 return 3;
170 }
171 assert(0);
172 }
173
174 static INLINE uint
175 nv_type_sizeof(ubyte type)
176 {
177 if (type & 0xf0)
178 return (1 << nv_type_order(type)) * (type >> 4);
179 return 1 << nv_type_order(type);
180 }
181
182 static INLINE uint
183 nv_type_sizeof_base(ubyte type)
184 {
185 return 1 << nv_type_order(type);
186 }
187
188 struct nv_reg {
189 int id;
190 ubyte file;
191 ubyte type; /* type of generating instruction's result */
192 union {
193 float f32;
194 double f64;
195 int32_t s32;
196 uint32_t u32;
197 } imm;
198 };
199
200 struct nv_range {
201 struct nv_range *next;
202 int bgn;
203 int end;
204 };
205
206 struct nv_value {
207 struct nv_reg reg;
208 struct nv_instruction *insn;
209 struct nv_value *join;
210 int n;
211 struct nv_range *livei;
212 int refc;
213
214 struct nv_value *next;
215 struct nv_value *prev;
216 };
217
218 struct nv_ref {
219 struct nv_value *value;
220 struct nv_instruction *insn;
221 ubyte mod;
222 ubyte typecast;
223 ubyte flags; /* not used yet */
224 };
225
226 struct nv_basic_block;
227
228 struct nv_instruction {
229 struct nv_instruction *next;
230 struct nv_instruction *prev;
231 uint opcode;
232 int serial;
233 struct nv_value *def[4];
234 struct nv_value *flags_def;
235 struct nv_ref *src[5];
236 struct nv_ref *flags_src;
237 struct nv_basic_block *bb;
238 struct nv_basic_block *target; /* target block of control flow insn */
239 ubyte cc;
240 ubyte set_cond : 4;
241 ubyte fixed : 1; /* don't optimize away */
242 ubyte is_terminator : 1;
243 ubyte is_join : 1;
244 ubyte is_long : 1; /* for emission */
245 /* */
246 ubyte saturate : 1;
247 ubyte centroid : 1;
248 ubyte flat : 1;
249 ubyte lanes : 4;
250 ubyte tex_live : 1;
251 /* */
252 ubyte tex_t; /* TIC binding */
253 ubyte tex_s; /* TSC binding */
254 ubyte tex_argc : 3;
255 ubyte tex_cube : 1;
256 ubyte tex_mask : 4;
257 /* */
258 ubyte quadop;
259 };
260
261 #define CFG_EDGE_FORWARD 0
262 #define CFG_EDGE_BACK 1
263 #define CFG_EDGE_LOOP_ENTER 2
264 #define CFG_EDGE_LOOP_LEAVE 4
265 #define CFG_EDGE_FAKE 8
266
267 /* 'WALL' edge means where reachability check doesn't follow */
268 /* 'LOOP' edge means just having to do with loops */
269 #define IS_LOOP_EDGE(k) ((k) & 7)
270 #define IS_WALL_EDGE(k) ((k) & 9)
271
272 struct nv_basic_block {
273 struct nv_instruction *entry; /* first non-phi instruction */
274 struct nv_instruction *exit;
275 struct nv_instruction *phi; /* very first instruction */
276 int num_instructions;
277
278 struct nv_basic_block *out[2]; /* no indirect branches -> 2 */
279 struct nv_basic_block *in[8]; /* hope that suffices */
280 uint num_in;
281 ubyte out_kind[2];
282 ubyte in_kind[8];
283
284 int id;
285 struct nv_basic_block *last_visitor;
286 uint priv;
287 uint pass_seq;
288
289 uint32_t bin_pos; /* position, size in emitted code */
290 uint32_t bin_size;
291
292 uint32_t live_set[NV_PC_MAX_VALUES / 32];
293 };
294
295 #define NV_FIXUP_CFLOW_RELOC 0
296 #define NV_FIXUP_PARAM_RELOC 1
297
298 struct nv_fixup {
299 ubyte type;
300 ubyte shift;
301 uint32_t mask;
302 uint32_t data;
303 uint32_t offset;
304 };
305
306 static INLINE void
307 nv_fixup_apply(uint32_t *bin, struct nv_fixup *fixup, uint32_t data)
308 {
309 uint32_t val;
310
311 val = bin[fixup->offset / 4] & ~fixup->mask;
312 data = (fixup->shift < 0) ? (data >> fixup->shift) : (data << fixup->shift);
313 val |= (fixup->data + data) & fixup->mask;
314 bin[fixup->offset / 4] = val;
315 }
316
317 struct nv_pc {
318 struct nv50_translation_info *ti;
319
320 struct nv_basic_block *root;
321 struct nv_basic_block *current_block;
322 struct nv_basic_block *parent_block;
323
324 int loop_nesting_bound;
325 uint pass_seq;
326
327 struct nv_value values[NV_PC_MAX_VALUES];
328 struct nv_instruction instructions[NV_PC_MAX_INSTRUCTIONS];
329 struct nv_ref **refs;
330 struct nv_basic_block **bb_list;
331 int num_values;
332 int num_instructions;
333 int num_refs;
334 int num_blocks;
335
336 int max_reg[4];
337
338 uint32_t *immd_buf; /* populated on emit */
339 unsigned immd_count;
340
341 uint32_t *emit;
342 unsigned bin_size;
343 unsigned bin_pos;
344
345 struct nv_fixup *fixups;
346 int num_fixups;
347 };
348
349 void nvbb_insert_tail(struct nv_basic_block *, struct nv_instruction *);
350 void nvi_insert_after(struct nv_instruction *, struct nv_instruction *);
351
352 static INLINE struct nv_instruction *
353 nv_alloc_instruction(struct nv_pc *pc, uint opcode)
354 {
355 struct nv_instruction *insn;
356
357 insn = &pc->instructions[pc->num_instructions++];
358 assert(pc->num_instructions < NV_PC_MAX_INSTRUCTIONS);
359
360 insn->cc = NV_CC_TR;
361 insn->opcode = opcode;
362
363 return insn;
364 }
365
366 static INLINE struct nv_instruction *
367 new_instruction(struct nv_pc *pc, uint opcode)
368 {
369 struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
370
371 nvbb_insert_tail(pc->current_block, insn);
372 return insn;
373 }
374
375 static INLINE struct nv_instruction *
376 new_instruction_at(struct nv_pc *pc, struct nv_instruction *at, uint opcode)
377 {
378 struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
379
380 nvi_insert_after(at, insn);
381 return insn;
382 }
383
384 static INLINE struct nv_value *
385 new_value(struct nv_pc *pc, ubyte file, ubyte type)
386 {
387 struct nv_value *value = &pc->values[pc->num_values];
388
389 assert(pc->num_values < NV_PC_MAX_VALUES - 1);
390
391 value->n = pc->num_values++;
392 value->join = value;
393 value->reg.id = -1;
394 value->reg.file = file;
395 value->reg.type = type;
396 return value;
397 }
398
399 static INLINE struct nv_value *
400 new_value_like(struct nv_pc *pc, struct nv_value *like)
401 {
402 return new_value(pc, like->reg.file, like->reg.type);
403 }
404
405 static INLINE struct nv_ref *
406 new_ref(struct nv_pc *pc, struct nv_value *val)
407 {
408 int i;
409 struct nv_ref *ref;
410
411 if ((pc->num_refs % 64) == 0) {
412 const unsigned old_size = pc->num_refs * sizeof(struct nv_ref *);
413 const unsigned new_size = (pc->num_refs + 64) * sizeof(struct nv_ref *);
414
415 pc->refs = REALLOC(pc->refs, old_size, new_size);
416
417 ref = CALLOC(64, sizeof(struct nv_ref));
418 for (i = 0; i < 64; ++i)
419 pc->refs[pc->num_refs + i] = &ref[i];
420 }
421
422 ref = pc->refs[pc->num_refs++];
423 ref->value = val;
424 ref->typecast = val->reg.type;
425
426 ++val->refc;
427 return ref;
428 }
429
430 static INLINE struct nv_basic_block *
431 new_basic_block(struct nv_pc *pc)
432 {
433 struct nv_basic_block *bb = CALLOC_STRUCT(nv_basic_block);
434
435 bb->id = pc->num_blocks++;
436 return bb;
437 }
438
439 static INLINE void
440 nv_reference(struct nv_pc *pc, struct nv_ref **d, struct nv_value *s)
441 {
442 if (*d)
443 --(*d)->value->refc;
444
445 if (s) {
446 if (!*d)
447 *d = new_ref(pc, s);
448 else {
449 (*d)->value = s;
450 ++(s->refc);
451 }
452 } else {
453 *d = NULL;
454 }
455 }
456
457 /* nv50_emit.c */
458 void nv50_emit_instruction(struct nv_pc *, struct nv_instruction *);
459
460 /* nv50_print.c */
461 const char *nv_opcode_name(uint opcode);
462 void nv_print_instruction(struct nv_instruction *);
463
464 /* nv50_pc.c */
465
466 void nv_print_program(struct nv_basic_block *b);
467
468 boolean nv_op_commutative(uint opcode);
469 int nv50_indirect_opnd(struct nv_instruction *);
470 boolean nv50_nvi_can_use_imm(struct nv_instruction *, int s);
471 boolean nv50_nvi_can_predicate(struct nv_instruction *);
472 boolean nv50_nvi_can_load(struct nv_instruction *, int s, struct nv_value *);
473 ubyte nv50_supported_src_mods(uint opcode, int s);
474 int nv_nvi_refcount(struct nv_instruction *);
475 void nv_nvi_delete(struct nv_instruction *);
476 void nv_nvi_permute(struct nv_instruction *, struct nv_instruction *);
477 void nvbb_attach_block(struct nv_basic_block *parent,
478 struct nv_basic_block *, ubyte edge_kind);
479 boolean nvbb_dominated_by(struct nv_basic_block *, struct nv_basic_block *);
480 boolean nvbb_reachable_by(struct nv_basic_block *, struct nv_basic_block *,
481 struct nv_basic_block *);
482 struct nv_basic_block *nvbb_dom_frontier(struct nv_basic_block *);
483 int nvcg_replace_value(struct nv_pc *pc, struct nv_value *old_val,
484 struct nv_value *new_val);
485 struct nv_value *nvcg_find_immediate(struct nv_ref *);
486 struct nv_value *nvcg_find_constant(struct nv_ref *);
487
488 typedef void (*nv_pc_pass_func)(void *priv, struct nv_basic_block *b);
489
490 void nv_pc_pass_in_order(struct nv_basic_block *, nv_pc_pass_func, void *);
491
492 int nv_pc_exec_pass0(struct nv_pc *pc);
493 int nv_pc_exec_pass1(struct nv_pc *pc);
494 int nv_pc_exec_pass2(struct nv_pc *pc);
495
496 int nv50_tgsi_to_nc(struct nv_pc *, struct nv50_translation_info *);
497
498 #endif // NV50_COMPILER_H