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
24 #include "nv50_program.h"
28 /* returns TRUE if operands 0 and 1 can be swapped */
30 nv_op_commutative(uint opcode
)
48 /* return operand to which the address register applies */
50 nv50_indirect_opnd(struct nv_instruction
*i
)
65 nv50_nvi_can_use_imm(struct nv_instruction
*nvi
, int s
)
67 if (nvi
->flags_src
|| nvi
->flags_def
)
70 switch (nvi
->opcode
) {
78 return (s
== 1) && (nvi
->def
[0]->reg
.file
== NV_FILE_GPR
);
81 return (nvi
->def
[0]->reg
.file
== NV_FILE_GPR
);
88 nv50_nvi_can_load(struct nv_instruction
*nvi
, int s
, struct nv_value
*value
)
90 switch (nvi
->opcode
) {
103 if (s
== 0 && (value
->reg
.file
== NV_FILE_MEM_S
||
104 value
->reg
.file
== NV_FILE_MEM_P
))
107 value
->reg
.file
>= NV_FILE_MEM_C(0) &&
108 value
->reg
.file
<= NV_FILE_MEM_C(15))
110 if (s
== 2 && nvi
->src
[1]->value
->reg
.file
== NV_FILE_GPR
)
122 nv50_supported_src_mods(uint opcode
, int s
)
126 return NV_MOD_NEG
| NV_MOD_ABS
; /* obviously */
145 return NV_MOD_ABS
| NV_MOD_NEG
;
152 nv_nvi_refcount(struct nv_instruction
*nvi
)
156 rc
= nvi
->flags_def
? nvi
->flags_def
->refc
: 0;
158 for (i
= 0; i
< 4; ++i
) {
161 rc
+= nvi
->def
[i
]->refc
;
167 nv_pc_free_refs(struct nv_pc
*pc
)
170 for (i
= 0; i
< pc
->num_refs
; i
+= 64)
175 nv_print_program(struct nv_basic_block
*b
)
177 struct nv_instruction
*i
= b
->phi
;
181 debug_printf("=== BB %i ", b
->id
);
183 debug_printf("(--0> %i) ", b
->out
[0]->id
);
185 debug_printf("(--1> %i) ", b
->out
[1]->id
);
186 debug_printf("===\n");
190 for (; i
; i
= i
->next
)
191 nv_print_instruction(i
);
194 debug_printf("END\n\n");
197 if (!b
->out
[1] && ++(b
->out
[0]->priv
) != b
->out
[0]->num_in
)
201 nv_print_program(b
->out
[0]);
203 if (b
->out
[1] && b
->out
[1] != b
)
204 nv_print_program(b
->out
[1]);
208 nvcg_show_bincode(struct nv_pc
*pc
)
212 for (i
= 0; i
< pc
->bin_size
/ 4; ++i
)
213 debug_printf("0x%08x ", pc
->emit
[i
]);
218 nv50_emit_program(struct nv_pc
*pc
)
220 uint32_t *code
= pc
->emit
;
223 debug_printf("emitting program: size = %u\n", pc
->bin_size
);
225 for (n
= 0; n
< pc
->num_blocks
; ++n
) {
226 struct nv_instruction
*i
;
227 struct nv_basic_block
*b
= pc
->bb_list
[n
];
229 for (i
= b
->entry
; i
; i
= i
->next
) {
230 nv50_emit_instruction(pc
, i
);
232 pc
->bin_pos
+= 1 + (pc
->emit
[0] & 1);
233 pc
->emit
+= 1 + (pc
->emit
[0] & 1);
236 assert(pc
->emit
== &code
[pc
->bin_size
/ 4]);
238 /* XXX: we can do better than this ... */
239 if ((pc
->emit
[-1] & 3) == 3) {
240 pc
->emit
[0] = 0xf0000001;
241 pc
->emit
[1] = 0xe0000000;
246 code
[pc
->bin_size
/ 4 - 1] |= 1;
248 nvcg_show_bincode(pc
);
254 nv50_generate_code(struct nv50_translation_info
*ti
)
259 pc
= CALLOC_STRUCT(nv_pc
);
263 ret
= nv50_tgsi_to_nc(pc
, ti
);
268 ret
= nv_pc_exec_pass0(pc
);
272 /* register allocation */
273 ret
= nv_pc_exec_pass1(pc
);
277 /* prepare for emission */
278 ret
= nv_pc_exec_pass2(pc
);
282 pc
->emit
= CALLOC(pc
->bin_size
/ 4 + 2, 4);
287 ret
= nv50_emit_program(pc
);
291 ti
->p
->code_size
= pc
->bin_size
;
292 ti
->p
->code
= pc
->emit
;
294 ti
->p
->immd_size
= pc
->immd_count
* 4;
295 ti
->p
->immd
= pc
->immd_buf
;
297 ti
->p
->max_gpr
= (pc
->max_reg
[NV_FILE_GPR
] + 1) >> 1;
300 ti
->p
->fixups
= pc
->fixups
;
301 ti
->p
->num_fixups
= pc
->num_fixups
;
303 debug_printf("SHADER TRANSLATION - %s\n", ret
? "failure" : "success");
321 nvbb_insert_phi(struct nv_basic_block
*b
, struct nv_instruction
*i
)
328 assert(!b
->entry
->prev
&& b
->exit
);
336 if (b
->entry
->opcode
== NV_OP_PHI
) { /* insert after entry */
337 assert(b
->entry
== b
->exit
);
342 } else { /* insert before entry */
343 assert(b
->entry
->prev
&& b
->exit
);
345 i
->prev
= b
->entry
->prev
;
353 nvbb_insert_tail(struct nv_basic_block
*b
, struct nv_instruction
*i
)
355 if (i
->opcode
== NV_OP_PHI
) {
356 nvbb_insert_phi(b
, i
);
365 if (i
->prev
&& i
->prev
->opcode
== NV_OP_PHI
)
370 b
->num_instructions
++;
374 nv_nvi_delete(struct nv_instruction
*nvi
)
376 struct nv_basic_block
*b
= nvi
->bb
;
379 debug_printf("REM: "); nv_print_instruction(nvi
);
381 for (j
= 0; j
< 4; ++j
) {
384 --(nvi
->src
[j
]->value
->refc
);
389 nvi
->next
->prev
= nvi
->prev
;
391 assert(nvi
== b
->exit
);
396 nvi
->prev
->next
= nvi
->next
;
398 if (nvi
== b
->entry
) {
399 assert(nvi
->opcode
!= NV_OP_PHI
|| !nvi
->next
);
401 if (!nvi
->next
|| (nvi
->opcode
== NV_OP_PHI
))
402 b
->entry
= nvi
->prev
;
404 b
->entry
= nvi
->next
;
409 if (nvi
->opcode
!= NV_OP_PHI
)
410 debug_printf("WARN: b->phi points to non-PHI instruction\n");
412 if (!nvi
->next
|| nvi
->next
->opcode
!= NV_OP_PHI
)
420 nv_nvi_permute(struct nv_instruction
*i1
, struct nv_instruction
*i2
)
422 struct nv_basic_block
*b
= i1
->bb
;
424 assert(i1
->opcode
!= NV_OP_PHI
&&
425 i2
->opcode
!= NV_OP_PHI
);
426 assert(i1
->next
== i2
);
445 void nvbb_attach_block(struct nv_basic_block
*parent
, struct nv_basic_block
*b
)
447 if (parent
->out
[0]) {
448 assert(!parent
->out
[1]);
453 b
->in
[b
->num_in
++] = parent
;