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
23 #ifndef __NV50_COMPILER_H__
24 #define __NV50_COMPILER_H__
26 #include "nv50_debug.h"
28 #include "pipe/p_defines.h"
29 #include "util/u_inlines.h"
30 #include "util/u_memory.h"
33 #define NV_OP_EXTRACT 1
34 #define NV_OP_COMBINE 2
52 #define NV_OP_UNDEF 20
58 #define NV_OP_PRESIN 26
59 #define NV_OP_PREEX2 27
68 #define NV_OP_BREAK 36
69 #define NV_OP_BREAKADDR 37
70 #define NV_OP_JOINAT 38
78 #define NV_OP_QUADOP 46
79 #define NV_OP_LINTERP 47
80 #define NV_OP_PINTERP 48
83 #define NV_OP_FLOOR 51
84 #define NV_OP_TRUNC 52
86 #define NV_OP_SELECT 54
87 #define NV_OP_EXPORT 55
89 #define NV_OP_ROUND 57
90 #define NV_OP_COUNT 58
94 #define NV_FILE_ADDR 2
95 #define NV_FILE_FLAGS 3
96 #define NV_FILE_IMM 16
97 #define NV_FILE_MEM_S 32
98 #define NV_FILE_MEM_P 33
99 #define NV_FILE_MEM_V 34
100 #define NV_FILE_MEM_L 48
101 #define NV_FILE_MEM_G(i) (64 + i)
102 #define NV_FILE_MEM_C(i) (80 + i)
109 #define NV_TYPE_U8 0x00
110 #define NV_TYPE_S8 0x01
111 #define NV_TYPE_U16 0x02
112 #define NV_TYPE_S16 0x03
113 #define NV_TYPE_U32 0x04
114 #define NV_TYPE_S32 0x05
115 #define NV_TYPE_P32 0x07
116 #define NV_TYPE_F32 0x09
117 #define NV_TYPE_F64 0x0b
118 #define NV_TYPE_VEC(x, n) (NV_TYPE_##x | (n << 4))
119 #define NV_TYPE_LO 0x00
120 #define NV_TYPE_HI 0x80
121 #define NV_TYPE_ANY 0xff
123 #define NV_TYPE_ISINT(t) ((t) <= 5)
124 #define NV_TYPE_ISFLT(t) ((t) & 0x08)
126 /* $cX registers contain 4 bits: OCSZ (Z is bit 0) */
141 #define NV_PC_MAX_INSTRUCTIONS 2048
142 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
144 #define NV_PC_MAX_BASIC_BLOCKS 1024
146 static INLINE boolean
147 nv_is_vector_op(uint opcode)
149 return (opcode >= NV_OP_TEX) && (opcode <= NV_OP_TXQ);
153 nv_type_order(ubyte type)
155 switch (type & 0xf) {
175 nv_type_sizeof(ubyte type)
178 return (1 << nv_type_order(type)) * (type >> 4);
179 return 1 << nv_type_order(type);
183 nv_type_sizeof_base(ubyte type)
185 return 1 << nv_type_order(type);
191 ubyte type; /* type of generating instruction's result */
192 ubyte as_type; /* default type for new references to this value */
202 struct nv_range *next;
209 struct nv_instruction *insn;
210 struct nv_value *join;
212 struct nv_range *livei;
215 struct nv_value *next;
216 struct nv_value *prev;
220 struct nv_value *value;
223 ubyte flags; /* not used yet */
226 #define NV_REF_FLAG_REGALLOC_PRIV (1 << 0)
228 struct nv_basic_block;
230 struct nv_instruction {
231 struct nv_instruction *next;
232 struct nv_instruction *prev;
235 struct nv_value *def[4];
236 struct nv_value *flags_def;
237 struct nv_ref *src[5];
238 struct nv_ref *flags_src;
239 struct nv_basic_block *bb;
240 struct nv_basic_block *target; /* target block of control flow insn */
242 unsigned set_cond : 4;
243 unsigned fixed : 1; /* don't optimize away */
244 unsigned is_terminator : 1;
245 unsigned is_join : 1;
246 unsigned is_long : 1; /* for emission */
248 unsigned saturate : 1;
249 unsigned centroid : 1;
252 unsigned tex_live : 1;
254 ubyte tex_t; /* TIC binding */
255 ubyte tex_s; /* TSC binding */
256 unsigned tex_argc : 3;
257 unsigned tex_cube : 1;
258 unsigned tex_mask : 4;
264 nvi_vector_size(struct nv_instruction *nvi)
268 for (i = 0; i < 4 && nvi->def[i]; ++i);
272 #define CFG_EDGE_FORWARD 0
273 #define CFG_EDGE_BACK 1
274 #define CFG_EDGE_LOOP_ENTER 2
275 #define CFG_EDGE_LOOP_LEAVE 4
276 #define CFG_EDGE_FAKE 8
278 /* 'WALL' edge means where reachability check doesn't follow */
279 /* 'LOOP' edge means just having to do with loops */
280 #define IS_LOOP_EDGE(k) ((k) & 7)
281 #define IS_WALL_EDGE(k) ((k) & 9)
283 struct nv_basic_block {
284 struct nv_instruction *entry; /* first non-phi instruction */
285 struct nv_instruction *exit;
286 struct nv_instruction *phi; /* very first instruction */
287 int num_instructions;
289 struct nv_basic_block *out[2]; /* no indirect branches -> 2 */
290 struct nv_basic_block *in[8]; /* hope that suffices */
297 uint priv; /* reset to 0 after you're done */
300 uint32_t bin_pos; /* position, size in emitted code */
303 uint32_t live_set[NV_PC_MAX_VALUES / 32];
306 struct nv50_translation_info;
309 struct nv_basic_block **root;
310 struct nv_basic_block *current_block;
311 struct nv_basic_block *parent_block;
313 int loop_nesting_bound;
316 struct nv_value values[NV_PC_MAX_VALUES];
317 struct nv_instruction instructions[NV_PC_MAX_INSTRUCTIONS];
318 struct nv_ref **refs;
319 struct nv_basic_block *bb_list[NV_PC_MAX_BASIC_BLOCKS];
321 int num_instructions;
328 uint32_t *immd_buf; /* populated on emit */
338 /* optimization enables */
339 boolean opt_reload_elim;
342 void nvbb_insert_tail(struct nv_basic_block *, struct nv_instruction *);
343 void nvi_insert_after(struct nv_instruction *, struct nv_instruction *);
345 static INLINE struct nv_instruction *
346 nv_alloc_instruction(struct nv_pc *pc, uint opcode)
348 struct nv_instruction *insn;
350 insn = &pc->instructions[pc->num_instructions++];
351 assert(pc->num_instructions < NV_PC_MAX_INSTRUCTIONS);
354 insn->opcode = opcode;
359 static INLINE struct nv_instruction *
360 new_instruction(struct nv_pc *pc, uint opcode)
362 struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
364 nvbb_insert_tail(pc->current_block, insn);
368 static INLINE struct nv_instruction *
369 new_instruction_at(struct nv_pc *pc, struct nv_instruction *at, uint opcode)
371 struct nv_instruction *insn = nv_alloc_instruction(pc, opcode);
373 nvi_insert_after(at, insn);
377 static INLINE struct nv_value *
378 new_value(struct nv_pc *pc, ubyte file, ubyte type)
380 struct nv_value *value = &pc->values[pc->num_values];
382 assert(pc->num_values < NV_PC_MAX_VALUES - 1);
384 value->n = pc->num_values++;
387 value->reg.file = file;
388 value->reg.type = value->reg.as_type = type;
392 static INLINE struct nv_value *
393 new_value_like(struct nv_pc *pc, struct nv_value *like)
395 struct nv_value *val = new_value(pc, like->reg.file, like->reg.type);
396 val->reg.as_type = like->reg.as_type;
400 static INLINE struct nv_ref *
401 new_ref(struct nv_pc *pc, struct nv_value *val)
406 if ((pc->num_refs % 64) == 0) {
407 const unsigned old_size = pc->num_refs * sizeof(struct nv_ref *);
408 const unsigned new_size = (pc->num_refs + 64) * sizeof(struct nv_ref *);
410 pc->refs = REALLOC(pc->refs, old_size, new_size);
412 ref = CALLOC(64, sizeof(struct nv_ref));
413 for (i = 0; i < 64; ++i)
414 pc->refs[pc->num_refs + i] = &ref[i];
417 ref = pc->refs[pc->num_refs++];
419 ref->typecast = val->reg.as_type;
425 static INLINE struct nv_basic_block *
426 new_basic_block(struct nv_pc *pc)
428 struct nv_basic_block *bb;
430 if (pc->num_blocks >= NV_PC_MAX_BASIC_BLOCKS)
433 bb = CALLOC_STRUCT(nv_basic_block);
435 bb->id = pc->num_blocks;
436 pc->bb_list[pc->num_blocks++] = bb;
441 nv_reference(struct nv_pc *pc, struct nv_ref **d, struct nv_value *s)
459 void nv50_emit_instruction(struct nv_pc *, struct nv_instruction *);
460 unsigned nv50_inst_min_size(struct nv_instruction *);
463 const char *nv_opcode_name(uint opcode);
464 void nv_print_instruction(struct nv_instruction *);
468 void nv_print_function(struct nv_basic_block *root);
469 void nv_print_program(struct nv_pc *);
471 boolean nv_op_commutative(uint opcode);
472 int nv50_indirect_opnd(struct nv_instruction *);
473 boolean nv50_nvi_can_use_imm(struct nv_instruction *, int s);
474 boolean nv50_nvi_can_predicate(struct nv_instruction *);
475 boolean nv50_nvi_can_load(struct nv_instruction *, int s, struct nv_value *);
476 boolean nv50_op_can_write_flags(uint opcode);
477 ubyte nv50_supported_src_mods(uint opcode, int s);
478 int nv_nvi_refcount(struct nv_instruction *);
479 void nv_nvi_delete(struct nv_instruction *);
480 void nv_nvi_permute(struct nv_instruction *, struct nv_instruction *);
481 void nvbb_attach_block(struct nv_basic_block *parent,
482 struct nv_basic_block *, ubyte edge_kind);
483 boolean nvbb_dominated_by(struct nv_basic_block *, struct nv_basic_block *);
484 boolean nvbb_reachable_by(struct nv_basic_block *, struct nv_basic_block *,
485 struct nv_basic_block *);
486 struct nv_basic_block *nvbb_dom_frontier(struct nv_basic_block *);
487 int nvcg_replace_value(struct nv_pc *pc, struct nv_value *old_val,
488 struct nv_value *new_val);
489 struct nv_value *nvcg_find_immediate(struct nv_ref *);
490 struct nv_value *nvcg_find_constant(struct nv_ref *);
492 typedef void (*nv_pc_pass_func)(void *priv, struct nv_basic_block *b);
494 void nv_pc_pass_in_order(struct nv_basic_block *, nv_pc_pass_func, void *);
496 int nv_pc_exec_pass0(struct nv_pc *pc);
497 int nv_pc_exec_pass1(struct nv_pc *pc);
498 int nv_pc_exec_pass2(struct nv_pc *pc);
500 int nv50_tgsi_to_nc(struct nv_pc *, struct nv50_translation_info *);
502 #endif // NV50_COMPILER_H