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__
27 # define NV50_DBGMSG(args...) debug_printf(args)
29 # define NV50_DBGMSG(args...)
32 #include "pipe/p_defines.h"
33 #include "util/u_inlines.h"
34 #include "util/u_memory.h"
37 #define NV_OP_EXTRACT 1
38 #define NV_OP_COMBINE 2
56 #define NV_OP_UNDEF 20
62 #define NV_OP_PRESIN 26
63 #define NV_OP_PREEX2 27
72 #define NV_OP_BREAK 36
73 #define NV_OP_BREAKADDR 37
74 #define NV_OP_JOINAT 38
82 #define NV_OP_QUADOP 46
83 #define NV_OP_LINTERP 47
84 #define NV_OP_PINTERP 48
87 #define NV_OP_FLOOR 51
88 #define NV_OP_TRUNC 52
90 #define NV_OP_SELECT 54
91 #define NV_OP_EXPORT 55
93 #define NV_OP_COUNT 57
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)
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
126 #define NV_TYPE_ISINT(t) ((t) <= 5)
127 #define NV_TYPE_ISFLT(t) ((t) & 0x08)
129 /* $cX registers contain 4 bits: OCSZ (Z is bit 0) */
144 #define NV_PC_MAX_INSTRUCTIONS 2048
145 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
147 static INLINE boolean
148 nv_is_vector_op(uint opcode
)
150 return (opcode
>= NV_OP_TEX
) && (opcode
<= NV_OP_TXQ
);
154 nv_type_order(ubyte type
)
156 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 */
201 struct nv_range
*next
;
208 struct nv_instruction
*insn
;
209 struct nv_value
*join
;
211 struct nv_range
*livei
;
214 struct nv_value
*next
;
215 struct nv_value
*prev
;
219 struct nv_value
*value
;
220 struct nv_instruction
*insn
;
223 ubyte flags
; /* not used yet */
226 struct nv_basic_block
;
228 struct nv_instruction
{
229 struct nv_instruction
*next
;
230 struct nv_instruction
*prev
;
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 */
241 ubyte fixed
: 1; /* don't optimize away */
242 ubyte is_terminator
: 1;
244 ubyte is_long
: 1; /* for emission */
252 ubyte tex_t
; /* TIC binding */
253 ubyte tex_s
; /* TSC binding */
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
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)
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
;
278 struct nv_basic_block
*out
[2]; /* no indirect branches -> 2 */
279 struct nv_basic_block
*in
[8]; /* hope that suffices */
285 struct nv_basic_block
*last_visitor
;
289 uint32_t bin_pos
; /* position, size in emitted code */
292 uint32_t live_set
[NV_PC_MAX_VALUES
/ 32];
295 #define NV_FIXUP_CFLOW_RELOC 0
296 #define NV_FIXUP_PARAM_RELOC 1
307 nv_fixup_apply(uint32_t *bin
, struct nv_fixup
*fixup
, uint32_t data
)
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
;
318 struct nv50_translation_info
*ti
;
320 struct nv_basic_block
*root
;
321 struct nv_basic_block
*current_block
;
322 struct nv_basic_block
*parent_block
;
324 int loop_nesting_bound
;
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
;
332 int num_instructions
;
338 uint32_t *immd_buf
; /* populated on emit */
345 struct nv_fixup
*fixups
;
349 void nvbb_insert_tail(struct nv_basic_block
*, struct nv_instruction
*);
350 void nvi_insert_after(struct nv_instruction
*, struct nv_instruction
*);
352 static INLINE
struct nv_instruction
*
353 nv_alloc_instruction(struct nv_pc
*pc
, uint opcode
)
355 struct nv_instruction
*insn
;
357 insn
= &pc
->instructions
[pc
->num_instructions
++];
358 assert(pc
->num_instructions
< NV_PC_MAX_INSTRUCTIONS
);
361 insn
->opcode
= opcode
;
366 static INLINE
struct nv_instruction
*
367 new_instruction(struct nv_pc
*pc
, uint opcode
)
369 struct nv_instruction
*insn
= nv_alloc_instruction(pc
, opcode
);
371 nvbb_insert_tail(pc
->current_block
, insn
);
375 static INLINE
struct nv_instruction
*
376 new_instruction_at(struct nv_pc
*pc
, struct nv_instruction
*at
, uint opcode
)
378 struct nv_instruction
*insn
= nv_alloc_instruction(pc
, opcode
);
380 nvi_insert_after(at
, insn
);
384 static INLINE
struct nv_value
*
385 new_value(struct nv_pc
*pc
, ubyte file
, ubyte type
)
387 struct nv_value
*value
= &pc
->values
[pc
->num_values
];
389 assert(pc
->num_values
< NV_PC_MAX_VALUES
- 1);
391 value
->n
= pc
->num_values
++;
394 value
->reg
.file
= file
;
395 value
->reg
.type
= type
;
399 static INLINE
struct nv_value
*
400 new_value_like(struct nv_pc
*pc
, struct nv_value
*like
)
402 return new_value(pc
, like
->reg
.file
, like
->reg
.type
);
405 static INLINE
struct nv_ref
*
406 new_ref(struct nv_pc
*pc
, struct nv_value
*val
)
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
*);
415 pc
->refs
= REALLOC(pc
->refs
, old_size
, new_size
);
417 ref
= CALLOC(64, sizeof(struct nv_ref
));
418 for (i
= 0; i
< 64; ++i
)
419 pc
->refs
[pc
->num_refs
+ i
] = &ref
[i
];
422 ref
= pc
->refs
[pc
->num_refs
++];
424 ref
->typecast
= val
->reg
.type
;
430 static INLINE
struct nv_basic_block
*
431 new_basic_block(struct nv_pc
*pc
)
433 struct nv_basic_block
*bb
= CALLOC_STRUCT(nv_basic_block
);
435 bb
->id
= pc
->num_blocks
++;
440 nv_reference(struct nv_pc
*pc
, struct nv_ref
**d
, struct nv_value
*s
)
458 void nv50_emit_instruction(struct nv_pc
*, struct nv_instruction
*);
461 const char *nv_opcode_name(uint opcode
);
462 void nv_print_instruction(struct nv_instruction
*);
466 void nv_print_program(struct nv_basic_block
*b
);
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
*);
488 typedef void (*nv_pc_pass_func
)(void *priv
, struct nv_basic_block
*b
);
490 void nv_pc_pass_in_order(struct nv_basic_block
*, nv_pc_pass_func
, void *);
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
);
496 int nv50_tgsi_to_nc(struct nv_pc
*, struct nv50_translation_info
*);
498 #endif // NV50_COMPILER_H