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)
139 #define NV_PC_MAX_INSTRUCTIONS 2048
140 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
142 static INLINE boolean
143 nv_is_vector_op(uint opcode
)
145 return (opcode
>= NV_OP_TEX
) && (opcode
<= NV_OP_TXQ
);
149 nv_type_order(ubyte type
)
151 switch (type
& 0xf) {
170 nv_type_sizeof(ubyte type
)
173 return (1 << nv_type_order(type
)) * (type
>> 4);
174 return 1 << nv_type_order(type
);
178 nv_type_sizeof_base(ubyte type
)
180 return 1 << nv_type_order(type
);
186 ubyte type
; /* type of generating instruction's result */
196 struct nv_range
*next
;
203 struct nv_instruction
*insn
;
204 struct nv_value
*join
;
206 struct nv_range
*livei
;
209 struct nv_value
*next
;
210 struct nv_value
*prev
;
214 struct nv_value
*value
;
215 struct nv_instruction
*insn
;
218 ubyte flags
; /* not used yet */
221 struct nv_basic_block
;
223 struct nv_instruction
{
224 struct nv_instruction
*next
;
225 struct nv_instruction
*prev
;
228 struct nv_value
*def
[4];
229 struct nv_value
*flags_def
;
230 struct nv_ref
*src
[5];
231 struct nv_ref
*flags_src
;
232 struct nv_basic_block
*bb
;
233 struct nv_basic_block
*target
; /* target block of control flow insn */
236 ubyte fixed
: 1; /* don't optimize away */
237 ubyte is_terminator
: 1;
239 ubyte is_long
: 1; /* for emission */
247 ubyte tex_t
; /* TIC binding */
248 ubyte tex_s
; /* TSC binding */
256 #define CFG_EDGE_FORWARD 0
257 #define CFG_EDGE_BACK 1
258 #define CFG_EDGE_LOOP_ENTER 2
259 #define CFG_EDGE_LOOP_LEAVE 4
260 #define CFG_EDGE_FAKE 8
262 /* 'WALL' edge means where reachability check doesn't follow */
263 /* 'LOOP' edge means just having to do with loops */
264 #define IS_LOOP_EDGE(k) ((k) & 7)
265 #define IS_WALL_EDGE(k) ((k) & 9)
267 struct nv_basic_block
{
268 struct nv_instruction
*entry
; /* first non-phi instruction */
269 struct nv_instruction
*exit
;
270 struct nv_instruction
*phi
; /* very first instruction */
271 int num_instructions
;
273 struct nv_basic_block
*out
[2]; /* no indirect branches -> 2 */
274 struct nv_basic_block
*in
[8]; /* hope that suffices */
280 struct nv_basic_block
*last_visitor
;
284 uint32_t bin_pos
; /* position, size in emitted code */
287 uint32_t live_set
[NV_PC_MAX_VALUES
/ 32];
290 #define NV_FIXUP_CFLOW_RELOC 0
291 #define NV_FIXUP_PARAM_RELOC 1
302 nv_fixup_apply(uint32_t *bin
, struct nv_fixup
*fixup
, uint32_t data
)
306 val
= bin
[fixup
->offset
/ 4] & ~fixup
->mask
;
307 data
= (fixup
->shift
< 0) ? (data
>> fixup
->shift
) : (data
<< fixup
->shift
);
308 val
|= (fixup
->data
+ data
) & fixup
->mask
;
309 bin
[fixup
->offset
/ 4] = val
;
313 struct nv50_translation_info
*ti
;
315 struct nv_basic_block
*root
;
316 struct nv_basic_block
*current_block
;
317 struct nv_basic_block
*parent_block
;
319 int loop_nesting_bound
;
322 struct nv_value values
[NV_PC_MAX_VALUES
];
323 struct nv_instruction instructions
[NV_PC_MAX_INSTRUCTIONS
];
324 struct nv_ref
**refs
;
325 struct nv_basic_block
**bb_list
;
327 int num_instructions
;
333 uint32_t *immd_buf
; /* populated on emit */
340 struct nv_fixup
*fixups
;
344 void nvbb_insert_tail(struct nv_basic_block
*, struct nv_instruction
*);
346 static INLINE
struct nv_instruction
*
347 new_instruction(struct nv_pc
*pc
, uint opcode
)
349 struct nv_instruction
*insn
;
351 insn
= &pc
->instructions
[pc
->num_instructions
++];
352 assert(pc
->num_instructions
< NV_PC_MAX_INSTRUCTIONS
);
355 insn
->opcode
= opcode
;
357 nvbb_insert_tail(pc
->current_block
, insn
);
361 static INLINE
struct nv_value
*
362 new_value(struct nv_pc
*pc
, ubyte file
, ubyte type
)
364 struct nv_value
*value
= &pc
->values
[pc
->num_values
];
366 assert(pc
->num_values
< NV_PC_MAX_VALUES
- 1);
368 value
->n
= pc
->num_values
++;
371 value
->reg
.file
= file
;
372 value
->reg
.type
= type
;
376 static INLINE
struct nv_value
*
377 new_value_like(struct nv_pc
*pc
, struct nv_value
*like
)
379 return new_value(pc
, like
->reg
.file
, like
->reg
.type
);
382 static INLINE
struct nv_ref
*
383 new_ref(struct nv_pc
*pc
, struct nv_value
*val
)
388 if ((pc
->num_refs
% 64) == 0) {
389 const unsigned old_size
= pc
->num_refs
* sizeof(struct nv_ref
*);
390 const unsigned new_size
= (pc
->num_refs
+ 64) * sizeof(struct nv_ref
*);
392 pc
->refs
= REALLOC(pc
->refs
, old_size
, new_size
);
394 ref
= CALLOC(64, sizeof(struct nv_ref
));
395 for (i
= 0; i
< 64; ++i
)
396 pc
->refs
[pc
->num_refs
+ i
] = &ref
[i
];
399 ref
= pc
->refs
[pc
->num_refs
++];
401 ref
->typecast
= val
->reg
.type
;
407 static INLINE
struct nv_basic_block
*
408 new_basic_block(struct nv_pc
*pc
)
410 struct nv_basic_block
*bb
= CALLOC_STRUCT(nv_basic_block
);
412 bb
->id
= pc
->num_blocks
++;
417 nv_reference(struct nv_pc
*pc
, struct nv_ref
**d
, struct nv_value
*s
)
435 void nv50_emit_instruction(struct nv_pc
*, struct nv_instruction
*);
438 const char *nv_opcode_name(uint opcode
);
439 void nv_print_instruction(struct nv_instruction
*);
443 void nv_print_program(struct nv_basic_block
*b
);
445 boolean
nv_op_commutative(uint opcode
);
446 int nv50_indirect_opnd(struct nv_instruction
*);
447 boolean
nv50_nvi_can_use_imm(struct nv_instruction
*, int s
);
448 boolean
nv50_nvi_can_predicate(struct nv_instruction
*);
449 boolean
nv50_nvi_can_load(struct nv_instruction
*, int s
, struct nv_value
*);
450 ubyte
nv50_supported_src_mods(uint opcode
, int s
);
451 int nv_nvi_refcount(struct nv_instruction
*);
452 void nv_nvi_delete(struct nv_instruction
*);
453 void nv_nvi_permute(struct nv_instruction
*, struct nv_instruction
*);
454 void nvbb_attach_block(struct nv_basic_block
*parent
,
455 struct nv_basic_block
*, ubyte edge_kind
);
456 boolean
nvbb_dominated_by(struct nv_basic_block
*, struct nv_basic_block
*);
457 boolean
nvbb_reachable_by(struct nv_basic_block
*, struct nv_basic_block
*,
458 struct nv_basic_block
*);
459 struct nv_basic_block
*nvbb_dom_frontier(struct nv_basic_block
*);
460 int nvcg_replace_value(struct nv_pc
*pc
, struct nv_value
*old_val
,
461 struct nv_value
*new_val
);
463 typedef void (*nv_pc_pass_func
)(void *priv
, struct nv_basic_block
*b
);
465 void nv_pc_pass_in_order(struct nv_basic_block
*, nv_pc_pass_func
, void *);
467 int nv_pc_exec_pass0(struct nv_pc
*pc
);
468 int nv_pc_exec_pass1(struct nv_pc
*pc
);
469 int nv_pc_exec_pass2(struct nv_pc
*pc
);
471 int nv50_tgsi_to_nc(struct nv_pc
*, struct nv50_translation_info
*);
473 #endif // NV50_COMPILER_H