nv50: initialize edgeflag input index
[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 #include "pipe/p_defines.h"
27 #include "util/u_inlines.h"
28 #include "util/u_memory.h"
29
30 #define NV_OP_PHI 0
31 #define NV_OP_EXTRACT 1
32 #define NV_OP_COMBINE 2
33 #define NV_OP_LDA 3
34 #define NV_OP_STA 4
35 #define NV_OP_MOV 5
36 #define NV_OP_ADD 6
37 #define NV_OP_SUB 7
38 #define NV_OP_NEG 8
39 #define NV_OP_MUL 9
40 #define NV_OP_MAD 10
41 #define NV_OP_CVT 11
42 #define NV_OP_SAT 12
43 #define NV_OP_NOT 13
44 #define NV_OP_AND 14
45 #define NV_OP_OR 15
46 #define NV_OP_XOR 16
47 #define NV_OP_SHL 17
48 #define NV_OP_SHR 18
49 #define NV_OP_RCP 19
50 #define NV_OP_UNDEF 20
51 #define NV_OP_RSQ 21
52 #define NV_OP_LG2 22
53 #define NV_OP_SIN 23
54 #define NV_OP_COS 24
55 #define NV_OP_EX2 25
56 #define NV_OP_PRESIN 26
57 #define NV_OP_PREEX2 27
58 #define NV_OP_MIN 28
59 #define NV_OP_MAX 29
60 #define NV_OP_SET 30
61 #define NV_OP_SAD 31
62 #define NV_OP_KIL 32
63 #define NV_OP_BRA 33
64 #define NV_OP_CALL 34
65 #define NV_OP_RET 35
66 #define NV_OP_BREAK 36
67 #define NV_OP_BREAKADDR 37
68 #define NV_OP_JOINAT 38
69 #define NV_OP_TEX 39
70 #define NV_OP_TXB 40
71 #define NV_OP_TXL 41
72 #define NV_OP_TXF 42
73 #define NV_OP_TXQ 43
74 #define NV_OP_DFDX 44
75 #define NV_OP_DFDY 45
76 #define NV_OP_QUADOP 46
77 #define NV_OP_LINTERP 47
78 #define NV_OP_PINTERP 48
79 #define NV_OP_ABS 49
80 #define NV_OP_CEIL 50
81 #define NV_OP_FLOOR 51
82 #define NV_OP_TRUNC 52
83 #define NV_OP_NOP 53
84 #define NV_OP_SELECT 54
85 #define NV_OP_EXPORT 55
86 #define NV_OP_JOIN 56
87 #define NV_OP_COUNT 57
88
89 #define NV_FILE_GPR 0
90 #define NV_FILE_OUT 1
91 #define NV_FILE_ADDR 2
92 #define NV_FILE_FLAGS 3
93 #define NV_FILE_IMM 16
94 #define NV_FILE_MEM_S 32
95 #define NV_FILE_MEM_P 33
96 #define NV_FILE_MEM_V 34
97 #define NV_FILE_MEM_L 48
98 #define NV_FILE_MEM_G(i) (64 + i)
99 #define NV_FILE_MEM_C(i) (80 + i)
100
101 #define NV_MOD_NEG 1
102 #define NV_MOD_ABS 2
103 #define NV_MOD_NOT 4
104 #define NV_MOD_SAT 8
105
106 #define NV_TYPE_U8 0x00
107 #define NV_TYPE_S8 0x01
108 #define NV_TYPE_U16 0x02
109 #define NV_TYPE_S16 0x03
110 #define NV_TYPE_U32 0x04
111 #define NV_TYPE_S32 0x05
112 #define NV_TYPE_P32 0x07
113 #define NV_TYPE_F32 0x09
114 #define NV_TYPE_F64 0x0b
115 #define NV_TYPE_VEC(x, n) (NV_TYPE_##x | (n << 4))
116 #define NV_TYPE_LO 0x00
117 #define NV_TYPE_HI 0x80
118 #define NV_TYPE_ANY 0xff
119
120 #define NV_TYPE_ISINT(t) ((t) <= 5)
121 #define NV_TYPE_ISFLT(t) ((t) & 0x08)
122
123 #define NV_CC_FL 0x0
124 #define NV_CC_LT 0x1
125 #define NV_CC_EQ 0x2
126 #define NV_CC_LE 0x3
127 #define NV_CC_GT 0x4
128 #define NV_CC_NE 0x5
129 #define NV_CC_GE 0x6
130 #define NV_CC_U 0x8
131 #define NV_CC_TR 0xf
132
133 #define NV_PC_MAX_INSTRUCTIONS 2048
134 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
135
136 static INLINE boolean
137 nv_is_vector_op(uint opcode)
138 {
139 return (opcode >= NV_OP_TEX) && (opcode <= NV_OP_TXQ);
140 }
141
142 static INLINE uint
143 nv_type_order(ubyte type)
144 {
145 switch (type & 0xf) {
146 case NV_TYPE_U8:
147 case NV_TYPE_S8:
148 return 0;
149 case NV_TYPE_U16:
150 case NV_TYPE_S16:
151 return 1;
152 case NV_TYPE_U32:
153 case NV_TYPE_F32:
154 case NV_TYPE_S32:
155 case NV_TYPE_P32:
156 return 2;
157 case NV_TYPE_F64:
158 return 3;
159 }
160 assert(0);
161 }
162
163 static INLINE uint
164 nv_type_sizeof(ubyte type)
165 {
166 if (type & 0xf0)
167 return (1 << nv_type_order(type)) * (type >> 4);
168 return 1 << nv_type_order(type);
169 }
170
171 static INLINE uint
172 nv_type_sizeof_base(ubyte type)
173 {
174 return 1 << nv_type_order(type);
175 }
176
177 struct nv_reg {
178 int id;
179 ubyte file;
180 ubyte type; /* type of generating instruction's result */
181 union {
182 float f32;
183 double f64;
184 int32_t s32;
185 uint32_t u32;
186 } imm;
187 };
188
189 struct nv_range {
190 struct nv_range *next;
191 int bgn;
192 int end;
193 };
194
195 struct nv_value {
196 struct nv_reg reg;
197 struct nv_instruction *insn;
198 struct nv_value *join;
199 int n;
200 struct nv_range *livei;
201 int refc;
202
203 struct nv_value *next;
204 struct nv_value *prev;
205 };
206
207 struct nv_ref {
208 struct nv_value *value;
209 struct nv_instruction *insn;
210 ubyte mod;
211 ubyte typecast;
212 ubyte flags; /* not used yet */
213 };
214
215 struct nv_basic_block;
216
217 struct nv_instruction {
218 struct nv_instruction *next;
219 struct nv_instruction *prev;
220 uint opcode;
221 int serial;
222 struct nv_value *def[4];
223 struct nv_value *flags_def;
224 struct nv_ref *src[5];
225 struct nv_ref *flags_src;
226 struct nv_basic_block *bb;
227 struct nv_basic_block *target; /* target block of control flow insn */
228 ubyte cc;
229 ubyte set_cond : 4;
230 ubyte fixed : 1; /* don't optimize away */
231 ubyte is_terminator : 1;
232 ubyte is_join : 1;
233 ubyte is_long : 1; /* for emission */
234 /* */
235 ubyte saturate : 1;
236 ubyte centroid : 1;
237 ubyte flat : 1;
238 ubyte padding : 4;
239 ubyte tex_live : 1;
240 /* */
241 ubyte tex_t; /* TIC binding */
242 ubyte tex_s; /* TSC binding */
243 ubyte tex_argc : 3;
244 ubyte tex_cube : 1;
245 ubyte tex_mask : 4;
246 /* */
247 ubyte quadop;
248 };
249
250 #define CFG_EDGE_FORWARD 0
251 #define CFG_EDGE_BACK 1
252 #define CFG_EDGE_LOOP_ENTER 2
253 #define CFG_EDGE_LOOP_LEAVE 4
254
255 struct nv_basic_block {
256 struct nv_instruction *entry; /* first non-phi instruction */
257 struct nv_instruction *exit;
258 struct nv_instruction *phi; /* very first instruction */
259 int num_instructions;
260
261 struct nv_basic_block *out[2]; /* no indirect branches -> 2 */
262 struct nv_basic_block *in[8]; /* hope that suffices */
263 uint num_in;
264 ubyte out_kind[2];
265 ubyte in_kind[8];
266
267 int id;
268 struct nv_basic_block *last_visitor;
269 uint priv;
270 uint pass_seq;
271
272 uint32_t bin_pos; /* position, size in emitted code */
273 uint32_t bin_size;
274
275 uint32_t live_set[NV_PC_MAX_VALUES / 32];
276 };
277
278 #define NV_FIXUP_CFLOW_RELOC 0
279 #define NV_FIXUP_PARAM_RELOC 1
280
281 struct nv_fixup {
282 ubyte type;
283 ubyte shift;
284 uint32_t mask;
285 uint32_t data;
286 uint32_t offset;
287 };
288
289 static INLINE void
290 nv_fixup_apply(uint32_t *bin, struct nv_fixup *fixup, uint32_t data)
291 {
292 uint32_t val;
293
294 val = bin[fixup->offset / 4] & ~fixup->mask;
295 data = (fixup->shift < 0) ? (data >> fixup->shift) : (data << fixup->shift);
296 val |= (fixup->data + data) & fixup->mask;
297 bin[fixup->offset / 4] = val;
298 }
299
300 struct nv_pc {
301 struct nv50_translation_info *ti;
302
303 struct nv_basic_block *root;
304 struct nv_basic_block *current_block;
305 struct nv_basic_block *parent_block;
306
307 int loop_nesting_bound;
308 uint pass_seq;
309
310 struct nv_value values[NV_PC_MAX_VALUES];
311 struct nv_instruction instructions[NV_PC_MAX_INSTRUCTIONS];
312 struct nv_ref **refs;
313 struct nv_basic_block **bb_list;
314 int num_values;
315 int num_instructions;
316 int num_refs;
317 int num_blocks;
318
319 int max_reg[4];
320
321 uint32_t *immd_buf; /* populated on emit */
322 unsigned immd_count;
323
324 uint32_t *emit;
325 unsigned bin_size;
326 unsigned bin_pos;
327
328 struct nv_fixup *fixups;
329 int num_fixups;
330 };
331
332 void nvbb_insert_tail(struct nv_basic_block *, struct nv_instruction *);
333
334 static INLINE struct nv_instruction *
335 new_instruction(struct nv_pc *pc, uint opcode)
336 {
337 struct nv_instruction *insn;
338
339 insn = &pc->instructions[pc->num_instructions++];
340 assert(pc->num_instructions < NV_PC_MAX_INSTRUCTIONS);
341
342 insn->cc = NV_CC_TR;
343 insn->opcode = opcode;
344
345 nvbb_insert_tail(pc->current_block, insn);
346 return insn;
347 }
348
349 static INLINE struct nv_value *
350 new_value(struct nv_pc *pc, ubyte file, ubyte type)
351 {
352 struct nv_value *value = &pc->values[pc->num_values];
353
354 assert(pc->num_values < NV_PC_MAX_VALUES - 1);
355
356 value->n = pc->num_values++;
357 value->join = value;
358 value->reg.id = -1;
359 value->reg.file = file;
360 value->reg.type = type;
361 return value;
362 }
363
364 static INLINE struct nv_value *
365 new_value_like(struct nv_pc *pc, struct nv_value *like)
366 {
367 return new_value(pc, like->reg.file, like->reg.type);
368 }
369
370 static INLINE struct nv_ref *
371 new_ref(struct nv_pc *pc, struct nv_value *val)
372 {
373 int i;
374 struct nv_ref *ref;
375
376 if ((pc->num_refs % 64) == 0) {
377 const unsigned old_size = pc->num_refs * sizeof(struct nv_ref *);
378 const unsigned new_size = (pc->num_refs + 64) * sizeof(struct nv_ref *);
379
380 pc->refs = REALLOC(pc->refs, old_size, new_size);
381
382 ref = CALLOC(64, sizeof(struct nv_ref));
383 for (i = 0; i < 64; ++i)
384 pc->refs[pc->num_refs + i] = &ref[i];
385 }
386
387 ref = pc->refs[pc->num_refs++];
388 ref->value = val;
389 ref->typecast = val->reg.type;
390
391 ++val->refc;
392 return ref;
393 }
394
395 static INLINE struct nv_basic_block *
396 new_basic_block(struct nv_pc *pc)
397 {
398 struct nv_basic_block *bb = CALLOC_STRUCT(nv_basic_block);
399
400 bb->id = pc->num_blocks++;
401 return bb;
402 }
403
404 static INLINE void
405 nv_reference(struct nv_pc *pc, struct nv_ref **d, struct nv_value *s)
406 {
407 if (*d)
408 --(*d)->value->refc;
409
410 if (s) {
411 if (!*d)
412 *d = new_ref(pc, s);
413 else {
414 (*d)->value = s;
415 ++(s->refc);
416 }
417 } else {
418 *d = NULL;
419 }
420 }
421
422 /* nv50_emit.c */
423 void nv50_emit_instruction(struct nv_pc *, struct nv_instruction *);
424
425 /* nv50_print.c */
426 const char *nv_opcode_name(uint opcode);
427 void nv_print_instruction(struct nv_instruction *);
428
429 /* nv50_pc.c */
430
431 void nv_print_program(struct nv_basic_block *b);
432
433 boolean nv_op_commutative(uint opcode);
434 int nv50_indirect_opnd(struct nv_instruction *);
435 boolean nv50_nvi_can_use_imm(struct nv_instruction *, int s);
436 boolean nv50_nvi_can_predicate(struct nv_instruction *);
437 boolean nv50_nvi_can_load(struct nv_instruction *, int s, struct nv_value *);
438 ubyte nv50_supported_src_mods(uint opcode, int s);
439 int nv_nvi_refcount(struct nv_instruction *);
440 void nv_nvi_delete(struct nv_instruction *);
441 void nv_nvi_permute(struct nv_instruction *, struct nv_instruction *);
442 void nvbb_attach_block(struct nv_basic_block *parent,
443 struct nv_basic_block *, ubyte edge_kind);
444 boolean nvbb_dominated_by(struct nv_basic_block *, struct nv_basic_block *);
445 boolean nvbb_reachable_by(struct nv_basic_block *, struct nv_basic_block *,
446 struct nv_basic_block *);
447 struct nv_basic_block *nvbb_dom_frontier(struct nv_basic_block *);
448 int nvcg_replace_value(struct nv_pc *pc, struct nv_value *old_val,
449 struct nv_value *new_val);
450
451 typedef void (*nv_pc_pass_func)(void *priv, struct nv_basic_block *b);
452
453 void nv_pc_pass_in_order(struct nv_basic_block *, nv_pc_pass_func, void *);
454
455 int nv_pc_exec_pass0(struct nv_pc *pc);
456 int nv_pc_exec_pass1(struct nv_pc *pc);
457 int nv_pc_exec_pass2(struct nv_pc *pc);
458
459 int nv50_tgsi_to_nc(struct nv_pc *, struct nv50_translation_info *);
460
461 #endif // NV50_COMPILER_H