revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mesa / src / gallium / drivers / nvc0 / nvc0_pc.h
blob441692d766c9932df9ec5a59c474bde6c0099e6f
1 /*
2 * Copyright 2010 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #ifndef __NVC0_COMPILER_H__
24 #define __NVC0_COMPILER_H__
26 #include "nv50/nv50_debug.h"
28 #include "pipe/p_defines.h"
29 #include "util/u_inlines.h"
30 #include "util/u_memory.h"
31 #include "util/u_double_list.h"
33 /* pseudo opcodes */
34 #define NV_OP_UNDEF 0
35 #define NV_OP_BIND 1
36 #define NV_OP_MERGE 2
37 #define NV_OP_PHI 3
38 #define NV_OP_SELECT 4
39 #define NV_OP_NOP 5
41 /**
42 * BIND forces source operand i into the same register as destination operand i,
43 * and the operands will be assigned consecutive registers (needed for TEX).
44 * Beware conflicts !
45 * SELECT forces its multiple source operands and its destination operand into
46 * one and the same register.
49 /* base opcodes */
50 #define NV_OP_LD 6
51 #define NV_OP_ST 7
52 #define NV_OP_MOV 8
53 #define NV_OP_AND 9
54 #define NV_OP_OR 10
55 #define NV_OP_XOR 11
56 #define NV_OP_SHL 12
57 #define NV_OP_SHR 13
58 #define NV_OP_NOT 14
59 #define NV_OP_SET 15
60 #define NV_OP_ADD 16
61 #define NV_OP_SUB 17
62 #define NV_OP_MUL 18
63 #define NV_OP_MAD 19
64 #define NV_OP_ABS 20
65 #define NV_OP_NEG 21
66 #define NV_OP_MAX 22
67 #define NV_OP_MIN 23
68 #define NV_OP_CVT 24
69 #define NV_OP_CEIL 25
70 #define NV_OP_FLOOR 26
71 #define NV_OP_TRUNC 27
72 #define NV_OP_SAD 28
74 /* shader opcodes */
75 #define NV_OP_VFETCH 29
76 #define NV_OP_PFETCH 30
77 #define NV_OP_EXPORT 31
78 #define NV_OP_LINTERP 32
79 #define NV_OP_PINTERP 33
80 #define NV_OP_EMIT 34
81 #define NV_OP_RESTART 35
82 #define NV_OP_TEX 36
83 #define NV_OP_TXB 37
84 #define NV_OP_TXL 38
85 #define NV_OP_TXF 39
86 #define NV_OP_TXQ 40
87 #define NV_OP_QUADOP 41
88 #define NV_OP_DFDX 42
89 #define NV_OP_DFDY 43
90 #define NV_OP_KIL 44
92 /* control flow opcodes */
93 #define NV_OP_BRA 45
94 #define NV_OP_CALL 46
95 #define NV_OP_RET 47
96 #define NV_OP_EXIT 48
97 #define NV_OP_BREAK 49
98 #define NV_OP_BREAKADDR 50
99 #define NV_OP_JOINAT 51
100 #define NV_OP_JOIN 52
102 /* typed opcodes */
103 #define NV_OP_ADD_F32 NV_OP_ADD
104 #define NV_OP_ADD_B32 53
105 #define NV_OP_MUL_F32 NV_OP_MUL
106 #define NV_OP_MUL_B32 54
107 #define NV_OP_ABS_F32 NV_OP_ABS
108 #define NV_OP_ABS_S32 55
109 #define NV_OP_NEG_F32 NV_OP_NEG
110 #define NV_OP_NEG_S32 56
111 #define NV_OP_MAX_F32 NV_OP_MAX
112 #define NV_OP_MAX_S32 57
113 #define NV_OP_MAX_U32 58
114 #define NV_OP_MIN_F32 NV_OP_MIN
115 #define NV_OP_MIN_S32 59
116 #define NV_OP_MIN_U32 60
117 #define NV_OP_SET_F32 61
118 #define NV_OP_SET_S32 62
119 #define NV_OP_SET_U32 63
120 #define NV_OP_SAR 64
121 #define NV_OP_RCP 65
122 #define NV_OP_RSQ 66
123 #define NV_OP_LG2 67
124 #define NV_OP_SIN 68
125 #define NV_OP_COS 69
126 #define NV_OP_EX2 70
127 #define NV_OP_PRESIN 71
128 #define NV_OP_PREEX2 72
129 #define NV_OP_SAT 73
131 /* newly added opcodes */
132 #define NV_OP_SET_F32_AND 74
133 #define NV_OP_SET_F32_OR 75
134 #define NV_OP_SET_F32_XOR 76
135 #define NV_OP_SELP 77
136 #define NV_OP_SLCT 78
137 #define NV_OP_SLCT_F32 NV_OP_SLCT
138 #define NV_OP_SLCT_S32 79
139 #define NV_OP_SLCT_U32 80
140 #define NV_OP_SUB_F32 NV_OP_SUB
141 #define NV_OP_SUB_S32 81
142 #define NV_OP_MAD_F32 NV_OP_MAD
143 #define NV_OP_FSET_F32 82
144 #define NV_OP_TXG 83
146 #define NV_OP_COUNT 84
148 /* nv50 files omitted */
149 #define NV_FILE_GPR 0
150 #define NV_FILE_COND 1
151 #define NV_FILE_PRED 2
152 #define NV_FILE_IMM 16
153 #define NV_FILE_MEM_S 32
154 #define NV_FILE_MEM_V 34
155 #define NV_FILE_MEM_A 35
156 #define NV_FILE_MEM_L 48
157 #define NV_FILE_MEM_G 64
158 #define NV_FILE_MEM_C(i) (80 + i)
160 #define NV_IS_MEMORY_FILE(f) ((f) >= NV_FILE_MEM_S)
162 #define NV_MOD_NEG 1
163 #define NV_MOD_ABS 2
164 #define NV_MOD_NOT 4
165 #define NV_MOD_SAT 8
167 #define NV_TYPE_U8 0x00
168 #define NV_TYPE_S8 0x01
169 #define NV_TYPE_U16 0x02
170 #define NV_TYPE_S16 0x03
171 #define NV_TYPE_U32 0x04
172 #define NV_TYPE_S32 0x05
173 #define NV_TYPE_P32 0x07
174 #define NV_TYPE_F32 0x09
175 #define NV_TYPE_F64 0x0b
176 #define NV_TYPE_VEC(x, n) (NV_TYPE_##x | (n << 4))
177 #define NV_TYPE_ANY 0xff
179 #define NV_TYPE_ISINT(t) ((t) < 7)
180 #define NV_TYPE_ISSGD(t) ((t) & 1)
182 #define NV_CC_FL 0x0
183 #define NV_CC_LT 0x1
184 #define NV_CC_EQ 0x2
185 #define NV_CC_LE 0x3
186 #define NV_CC_GT 0x4
187 #define NV_CC_NE 0x5
188 #define NV_CC_GE 0x6
189 #define NV_CC_U 0x8
190 #define NV_CC_TR 0xf
191 #define NV_CC_O 0x10
192 #define NV_CC_C 0x11
193 #define NV_CC_A 0x12
194 #define NV_CC_S 0x13
195 #define NV_CC_INVERSE(cc) ((cc) ^ 0x7)
196 /* for 1 bit predicates: */
197 #define NV_CC_P 0
198 #define NV_CC_NOT_P 1
200 uint8_t nvc0_ir_reverse_cc(uint8_t cc);
202 #define NV_PC_MAX_INSTRUCTIONS 2048
203 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
205 #define NV_PC_MAX_BASIC_BLOCKS 1024
207 struct nv_op_info {
208 uint base; /* e.g. ADD_S32 -> ADD */
209 char name[12];
210 uint8_t type;
211 uint16_t mods;
212 unsigned flow : 1;
213 unsigned commutative : 1;
214 unsigned vector : 1;
215 unsigned predicate : 1;
216 unsigned pseudo : 1;
217 unsigned immediate : 3;
218 unsigned memory : 3;
221 extern struct nv_op_info nvc0_op_info_table[];
223 #define NV_BASEOP(op) (nvc0_op_info_table[op].base)
224 #define NV_OPTYPE(op) (nvc0_op_info_table[op].type)
226 static INLINE boolean
227 nv_is_texture_op(uint opcode)
229 return (opcode >= NV_OP_TEX && opcode <= NV_OP_TXQ);
232 static INLINE boolean
233 nv_is_vector_op(uint opcode)
235 return nvc0_op_info_table[opcode].vector ? TRUE : FALSE;
238 static INLINE boolean
239 nv_op_commutative(uint opcode)
241 return nvc0_op_info_table[opcode].commutative ? TRUE : FALSE;
244 static INLINE uint8_t
245 nv_op_supported_src_mods(uint opcode, int s)
247 return (nvc0_op_info_table[opcode].mods >> (s * 4)) & 0xf;
250 static INLINE uint
251 nv_type_order(ubyte type)
253 switch (type & 0xf) {
254 case NV_TYPE_U8:
255 case NV_TYPE_S8:
256 return 0;
257 case NV_TYPE_U16:
258 case NV_TYPE_S16:
259 return 1;
260 case NV_TYPE_U32:
261 case NV_TYPE_F32:
262 case NV_TYPE_S32:
263 case NV_TYPE_P32:
264 return 2;
265 case NV_TYPE_F64:
266 return 3;
268 assert(0);
269 return 0;
272 static INLINE uint
273 nv_type_sizeof(ubyte type)
275 if (type & 0xf0)
276 return (1 << nv_type_order(type)) * (type >> 4);
277 return 1 << nv_type_order(type);
280 static INLINE uint
281 nv_type_sizeof_base(ubyte type)
283 return 1 << nv_type_order(type);
286 struct nv_reg {
287 uint32_t address; /* for memory locations */
288 int id; /* for registers */
289 ubyte file;
290 ubyte size;
291 union {
292 int32_t s32;
293 int64_t s64;
294 uint64_t u64;
295 uint32_t u32; /* expected to be 0 for $r63 */
296 float f32;
297 double f64;
298 } imm;
301 struct nv_range {
302 struct nv_range *next;
303 int bgn;
304 int end;
307 struct nv_ref;
309 struct nv_value {
310 struct nv_reg reg;
311 struct nv_instruction *insn;
312 struct nv_value *join;
313 struct nv_ref *last_use;
314 int n;
315 struct nv_range *livei;
316 int refc;
317 struct nv_value *next;
318 struct nv_value *prev;
321 struct nv_ref {
322 struct nv_value *value;
323 struct nv_instruction *insn;
324 struct list_head list; /* connects uses of the same value */
325 uint8_t mod;
326 uint8_t flags;
329 #define NV_REF_FLAG_REGALLOC_PRIV (1 << 0)
331 struct nv_basic_block;
333 struct nv_instruction {
334 struct nv_instruction *next;
335 struct nv_instruction *prev;
336 uint opcode;
337 uint serial;
339 struct nv_value *def[5];
340 struct nv_ref *src[6];
342 int8_t predicate; /* index of predicate src */
343 int8_t indirect; /* index of pointer src */
345 union {
346 struct {
347 uint8_t t; /* TIC binding */
348 uint8_t s; /* TSC binding */
349 } tex;
350 struct {
351 uint8_t d; /* output type */
352 uint8_t s; /* input type */
353 } cvt;
354 } ext;
356 struct nv_basic_block *bb;
357 struct nv_basic_block *target; /* target block of control flow insn */
359 unsigned cc : 5; /* condition code */
360 unsigned fixed : 1; /* don't optimize away (prematurely) */
361 unsigned terminator : 1;
362 unsigned join : 1;
363 unsigned set_cond : 4; /* 2nd byte */
364 unsigned saturate : 1;
365 unsigned centroid : 1;
366 unsigned flat : 1;
367 unsigned patch : 1;
368 unsigned lanes : 4; /* 3rd byte */
369 unsigned tex_dim : 2;
370 unsigned tex_array : 1;
371 unsigned tex_cube : 1;
372 unsigned tex_shadow : 1; /* 4th byte */
373 unsigned tex_live : 1;
374 unsigned tex_mask : 4;
376 uint8_t quadop;
379 static INLINE int
380 nvi_vector_size(struct nv_instruction *nvi)
382 int i;
383 assert(nvi);
384 for (i = 0; i < 5 && nvi->def[i]; ++i);
385 return i;
388 #define CFG_EDGE_FORWARD 0
389 #define CFG_EDGE_BACK 1
390 #define CFG_EDGE_LOOP_ENTER 2
391 #define CFG_EDGE_LOOP_LEAVE 4
392 #define CFG_EDGE_FAKE 8
394 /* 'WALL' edge means where reachability check doesn't follow */
395 /* 'LOOP' edge means just having to do with loops */
396 #define IS_LOOP_EDGE(k) ((k) & 7)
397 #define IS_WALL_EDGE(k) ((k) & 9)
399 struct nv_basic_block {
400 struct nv_instruction *entry; /* first non-phi instruction */
401 struct nv_instruction *exit;
402 struct nv_instruction *phi; /* very first instruction */
403 int num_instructions;
405 struct nv_basic_block *out[2]; /* no indirect branches -> 2 */
406 struct nv_basic_block *in[8]; /* hope that suffices */
407 uint num_in;
408 ubyte out_kind[2];
409 ubyte in_kind[8];
411 int id;
412 int subroutine;
413 uint priv; /* reset to 0 after you're done */
414 uint pass_seq;
416 uint32_t emit_pos; /* position, size in emitted code (in bytes) */
417 uint32_t emit_size;
419 uint32_t live_set[NV_PC_MAX_VALUES / 32];
422 struct nvc0_translation_info;
424 struct nv_pc {
425 struct nv_basic_block **root;
426 struct nv_basic_block *current_block;
427 struct nv_basic_block *parent_block;
429 int loop_nesting_bound;
430 uint pass_seq;
432 struct nv_value values[NV_PC_MAX_VALUES];
433 struct nv_instruction instructions[NV_PC_MAX_INSTRUCTIONS];
434 struct nv_ref **refs;
435 struct nv_basic_block *bb_list[NV_PC_MAX_BASIC_BLOCKS];
436 int num_values;
437 int num_instructions;
438 int num_refs;
439 int num_blocks;
440 int num_subroutines;
442 int max_reg[4];
444 uint32_t *immd_buf; /* populated on emit */
445 unsigned immd_count;
447 uint32_t *emit;
448 uint32_t emit_size;
449 uint32_t emit_pos;
451 void *reloc_entries;
452 unsigned num_relocs;
454 /* optimization enables */
455 boolean opt_reload_elim;
456 boolean is_fragprog;
459 void nvc0_insn_append(struct nv_basic_block *, struct nv_instruction *);
460 void nvc0_insn_insert_before(struct nv_instruction *, struct nv_instruction *);
461 void nvc0_insn_insert_after(struct nv_instruction *, struct nv_instruction *);
463 static INLINE struct nv_instruction *
464 nv_alloc_instruction(struct nv_pc *pc, uint opcode)
466 struct nv_instruction *insn;
468 insn = &pc->instructions[pc->num_instructions++];
469 assert(pc->num_instructions < NV_PC_MAX_INSTRUCTIONS);
471 insn->opcode = opcode;
472 insn->cc = NV_CC_P;
473 insn->indirect = -1;
474 insn->predicate = -1;
476 return insn;
479 static INLINE struct nv_instruction *
480 new_instruction(struct nv_pc *pc, uint opcode)
482 struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
484 nvc0_insn_append(pc->current_block, insn);
485 return insn;
488 static INLINE struct nv_instruction *
489 new_instruction_at(struct nv_pc *pc, struct nv_instruction *at, uint opcode)
491 struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
493 nvc0_insn_insert_after(at, insn);
494 return insn;
497 static INLINE struct nv_value *
498 new_value(struct nv_pc *pc, ubyte file, ubyte size)
500 struct nv_value *value = &pc->values[pc->num_values];
502 assert(pc->num_values < NV_PC_MAX_VALUES - 1);
504 value->n = pc->num_values++;
505 value->join = value;
506 value->reg.id = -1;
507 value->reg.file = file;
508 value->reg.size = size;
509 return value;
512 static INLINE struct nv_value *
513 new_value_like(struct nv_pc *pc, struct nv_value *like)
515 return new_value(pc, like->reg.file, like->reg.size);
518 static INLINE struct nv_ref *
519 new_ref(struct nv_pc *pc, struct nv_value *val)
521 int i;
522 struct nv_ref *ref;
524 if ((pc->num_refs % 64) == 0) {
525 const unsigned old_size = pc->num_refs * sizeof(struct nv_ref *);
526 const unsigned new_size = (pc->num_refs + 64) * sizeof(struct nv_ref *);
528 pc->refs = REALLOC(pc->refs, old_size, new_size);
530 ref = CALLOC(64, sizeof(struct nv_ref));
531 for (i = 0; i < 64; ++i)
532 pc->refs[pc->num_refs + i] = &ref[i];
535 ref = pc->refs[pc->num_refs++];
536 ref->value = val;
538 LIST_INITHEAD(&ref->list);
540 ++val->refc;
541 return ref;
544 static INLINE struct nv_basic_block *
545 new_basic_block(struct nv_pc *pc)
547 struct nv_basic_block *bb;
549 if (pc->num_blocks >= NV_PC_MAX_BASIC_BLOCKS)
550 return NULL;
552 bb = CALLOC_STRUCT(nv_basic_block);
554 bb->id = pc->num_blocks;
555 pc->bb_list[pc->num_blocks++] = bb;
556 return bb;
559 static INLINE void
560 nv_reference(struct nv_pc *pc,
561 struct nv_instruction *nvi, int c, struct nv_value *s)
563 struct nv_ref **d = &nvi->src[c];
564 assert(c < 6);
566 if (*d) {
567 --(*d)->value->refc;
568 LIST_DEL(&(*d)->list);
571 if (s) {
572 if (!*d) {
573 *d = new_ref(pc, s);
574 (*d)->insn = nvi;
575 } else {
576 LIST_DEL(&(*d)->list);
577 (*d)->value = s;
578 ++(s->refc);
580 if (!s->last_use)
581 s->last_use = *d;
582 else
583 LIST_ADDTAIL(&s->last_use->list, &(*d)->list);
585 s->last_use = *d;
586 (*d)->insn = nvi;
587 } else {
588 *d = NULL;
592 /* nvc0_emit.c */
593 void nvc0_emit_instruction(struct nv_pc *, struct nv_instruction *);
595 /* nvc0_print.c */
596 const char *nvc0_opcode_name(uint opcode);
597 void nvc0_print_instruction(struct nv_instruction *);
599 /* nvc0_pc.c */
600 void nvc0_print_function(struct nv_basic_block *root);
601 void nvc0_print_program(struct nv_pc *);
603 boolean nvc0_insn_can_load(struct nv_instruction *, int s,
604 struct nv_instruction *);
605 boolean nvc0_insn_is_predicateable(struct nv_instruction *);
607 int nvc0_insn_refcount(struct nv_instruction *);
608 void nvc0_insn_delete(struct nv_instruction *);
609 void nvc0_insns_permute(struct nv_instruction *prev, struct nv_instruction *);
611 void nvc0_bblock_attach(struct nv_basic_block *parent,
612 struct nv_basic_block *child, ubyte edge_kind);
613 boolean nvc0_bblock_dominated_by(struct nv_basic_block *,
614 struct nv_basic_block *);
615 boolean nvc0_bblock_reachable_by(struct nv_basic_block *future,
616 struct nv_basic_block *past,
617 struct nv_basic_block *final);
618 struct nv_basic_block *nvc0_bblock_dom_frontier(struct nv_basic_block *);
620 int nvc0_pc_replace_value(struct nv_pc *pc,
621 struct nv_value *old_val,
622 struct nv_value *new_val);
624 struct nv_value *nvc0_pc_find_immediate(struct nv_ref *);
625 struct nv_value *nvc0_pc_find_constant(struct nv_ref *);
627 typedef void (*nv_pc_pass_func)(void *priv, struct nv_basic_block *b);
629 void nvc0_pc_pass_in_order(struct nv_basic_block *, nv_pc_pass_func, void *);
631 int nvc0_pc_exec_pass0(struct nv_pc *pc);
632 int nvc0_pc_exec_pass1(struct nv_pc *pc);
633 int nvc0_pc_exec_pass2(struct nv_pc *pc);
635 int nvc0_tgsi_to_nc(struct nv_pc *, struct nvc0_translation_info *);
637 #endif // NV50_COMPILER_H