Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / nvc0 / nvc0_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 __NVC0_COMPILER_H__
24 #define __NVC0_COMPILER_H__
25
26 #include "nv50/nv50_debug.h"
27
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"
32
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
40
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.
47  */
48
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
73
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
91
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
101
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
130
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
145
146 #define NV_OP_COUNT     84
147
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)
159
160 #define NV_IS_MEMORY_FILE(f) ((f) >= NV_FILE_MEM_S)
161
162 #define NV_MOD_NEG 1
163 #define NV_MOD_ABS 2
164 #define NV_MOD_NOT 4
165 #define NV_MOD_SAT 8
166
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
178
179 #define NV_TYPE_ISINT(t) ((t) < 7)
180 #define NV_TYPE_ISSGD(t) ((t) & 1)
181
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
199
200 uint8_t nvc0_ir_reverse_cc(uint8_t cc);
201
202 #define NV_PC_MAX_INSTRUCTIONS 2048
203 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
204
205 #define NV_PC_MAX_BASIC_BLOCKS 1024
206
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;
219 };
220
221 extern struct nv_op_info nvc0_op_info_table[];
222
223 #define NV_BASEOP(op) (nvc0_op_info_table[op].base)
224 #define NV_OPTYPE(op) (nvc0_op_info_table[op].type)
225
226 static INLINE boolean
227 nv_is_texture_op(uint opcode)
228 {
229    return (opcode >= NV_OP_TEX && opcode <= NV_OP_TXQ);
230 }
231
232 static INLINE boolean
233 nv_is_vector_op(uint opcode)
234 {
235    return nvc0_op_info_table[opcode].vector ? TRUE : FALSE;
236 }
237
238 static INLINE boolean
239 nv_op_commutative(uint opcode)
240 {
241    return nvc0_op_info_table[opcode].commutative ? TRUE : FALSE;
242 }
243
244 static INLINE uint8_t
245 nv_op_supported_src_mods(uint opcode, int s)
246 {
247    return (nvc0_op_info_table[opcode].mods >> (s * 4)) & 0xf;
248 }
249
250 static INLINE uint
251 nv_type_order(ubyte type)
252 {
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;
267    }
268    assert(0);
269    return 0;
270 }
271
272 static INLINE uint
273 nv_type_sizeof(ubyte type)
274 {
275    if (type & 0xf0)
276       return (1 << nv_type_order(type)) * (type >> 4);
277    return 1 << nv_type_order(type);
278 }
279
280 static INLINE uint
281 nv_type_sizeof_base(ubyte type)
282 {
283    return 1 << nv_type_order(type);
284 }
285
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;
299 };
300
301 struct nv_range {
302    struct nv_range *next;
303    int bgn;
304    int end;
305 };
306
307 struct nv_ref;
308
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;
319 };
320
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;
327 };
328
329 #define NV_REF_FLAG_REGALLOC_PRIV (1 << 0)
330
331 struct nv_basic_block;
332
333 struct nv_instruction {
334    struct nv_instruction *next;
335    struct nv_instruction *prev;
336    uint opcode;
337    uint serial;
338
339    struct nv_value *def[5];
340    struct nv_ref *src[6];
341
342    int8_t predicate; /* index of predicate src */
343    int8_t indirect;  /* index of pointer src */
344
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;
355
356    struct nv_basic_block *bb;
357    struct nv_basic_block *target; /* target block of control flow insn */
358
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;
375
376    uint8_t quadop;
377 };
378
379 static INLINE int
380 nvi_vector_size(struct nv_instruction *nvi)
381 {
382    int i;
383    assert(nvi);
384    for (i = 0; i < 5 && nvi->def[i]; ++i);
385    return i;
386 }
387
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
393
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)
398
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;
404
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];
410
411    int id;
412    int subroutine;
413    uint priv; /* reset to 0 after you're done */
414    uint pass_seq;
415
416    uint32_t emit_pos; /* position, size in emitted code (in bytes) */
417    uint32_t emit_size;
418
419    uint32_t live_set[NV_PC_MAX_VALUES / 32];
420 };
421
422 struct nvc0_translation_info;
423
424 struct nv_pc {
425    struct nv_basic_block **root;
426    struct nv_basic_block *current_block;
427    struct nv_basic_block *parent_block;
428
429    int loop_nesting_bound;
430    uint pass_seq;
431
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;
441
442    int max_reg[4];
443
444    uint32_t *immd_buf; /* populated on emit */
445    unsigned immd_count;
446
447    uint32_t *emit;
448    uint32_t emit_size;
449    uint32_t emit_pos;
450
451    void *reloc_entries;
452    unsigned num_relocs;
453
454    /* optimization enables */
455    boolean opt_reload_elim;
456    boolean is_fragprog;
457 };
458
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 *);
462
463 static INLINE struct nv_instruction *
464 nv_alloc_instruction(struct nv_pc *pc, uint opcode)
465 {
466    struct nv_instruction *insn;
467
468    insn = &pc->instructions[pc->num_instructions++];
469    assert(pc->num_instructions < NV_PC_MAX_INSTRUCTIONS);
470
471    insn->opcode = opcode;
472    insn->cc = NV_CC_P;
473    insn->indirect = -1;
474    insn->predicate = -1;
475
476    return insn;
477 }
478
479 static INLINE struct nv_instruction *
480 new_instruction(struct nv_pc *pc, uint opcode)
481 {
482    struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
483
484    nvc0_insn_append(pc->current_block, insn);
485    return insn;
486 }
487
488 static INLINE struct nv_instruction *
489 new_instruction_at(struct nv_pc *pc, struct nv_instruction *at, uint opcode)
490 {
491    struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
492
493    nvc0_insn_insert_after(at, insn);
494    return insn;
495 }
496
497 static INLINE struct nv_value *
498 new_value(struct nv_pc *pc, ubyte file, ubyte size)
499 {
500    struct nv_value *value = &pc->values[pc->num_values];
501
502    assert(pc->num_values < NV_PC_MAX_VALUES - 1);
503
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;
510 }
511
512 static INLINE struct nv_value *
513 new_value_like(struct nv_pc *pc, struct nv_value *like)
514 {
515    return new_value(pc, like->reg.file, like->reg.size);
516 }
517
518 static INLINE struct nv_ref *
519 new_ref(struct nv_pc *pc, struct nv_value *val)
520 {
521    int i;
522    struct nv_ref *ref;
523
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 *);
527
528       pc->refs = REALLOC(pc->refs, old_size, new_size);
529
530       ref = CALLOC(64, sizeof(struct nv_ref));
531       for (i = 0; i < 64; ++i)
532          pc->refs[pc->num_refs + i] = &ref[i];
533    }
534
535    ref = pc->refs[pc->num_refs++];
536    ref->value = val;
537
538    LIST_INITHEAD(&ref->list);
539
540    ++val->refc;
541    return ref;
542 }
543
544 static INLINE struct nv_basic_block *
545 new_basic_block(struct nv_pc *pc)
546 {
547    struct nv_basic_block *bb;
548
549    if (pc->num_blocks >= NV_PC_MAX_BASIC_BLOCKS)
550       return NULL;
551
552    bb = CALLOC_STRUCT(nv_basic_block);
553
554    bb->id = pc->num_blocks;
555    pc->bb_list[pc->num_blocks++] = bb;
556    return bb;
557 }
558
559 static INLINE void
560 nv_reference(struct nv_pc *pc,
561              struct nv_instruction *nvi, int c, struct nv_value *s)
562 {
563    struct nv_ref **d = &nvi->src[c];
564    assert(c < 6);
565
566    if (*d) {
567       --(*d)->value->refc;
568       LIST_DEL(&(*d)->list);
569    }
570
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);
579       }
580       if (!s->last_use)
581          s->last_use = *d;
582       else
583          LIST_ADDTAIL(&s->last_use->list, &(*d)->list);
584
585       s->last_use = *d;
586       (*d)->insn = nvi;
587    } else {
588       *d = NULL;
589    }
590 }
591
592 /* nvc0_emit.c */
593 void nvc0_emit_instruction(struct nv_pc *, struct nv_instruction *);
594
595 /* nvc0_print.c */
596 const char *nvc0_opcode_name(uint opcode);
597 void nvc0_print_instruction(struct nv_instruction *);
598
599 /* nvc0_pc.c */
600 void nvc0_print_function(struct nv_basic_block *root);
601 void nvc0_print_program(struct nv_pc *);
602
603 boolean nvc0_insn_can_load(struct nv_instruction *, int s,
604                            struct nv_instruction *);
605 boolean nvc0_insn_is_predicateable(struct nv_instruction *);
606
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 *);
610
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 *);
619
620 int nvc0_pc_replace_value(struct nv_pc *pc,
621                           struct nv_value *old_val,
622                           struct nv_value *new_val);
623
624 struct nv_value *nvc0_pc_find_immediate(struct nv_ref *);
625 struct nv_value *nvc0_pc_find_constant(struct nv_ref *);
626
627 typedef void (*nv_pc_pass_func)(void *priv, struct nv_basic_block *b);
628
629 void nvc0_pc_pass_in_order(struct nv_basic_block *, nv_pc_pass_func, void *);
630
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);
634
635 int nvc0_tgsi_to_nc(struct nv_pc *, struct nvc0_translation_info *);
636
637 #endif // NV50_COMPILER_H