1 /*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #ifndef ROGUE_H
25 #define ROGUE_H
26
27 /**
28 * \file rogue.h
29 *
30 * \brief Main header.
31 */
32
33 #define __pvr_address_type pvr_dev_addr_t
34 #define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
35 /* clang-format off */
36 #define __pvr_make_address(addr_u64) PVR_DEV_ADDR(addr_u64)
37 /* clang-format on */
38
39 #include "pvr_types.h"
40 #include "csbgen/rogue_hwdefs.h"
41 #include "vulkan/pvr_limits.h"
42 #include "vulkan/pvr_common.h"
43
44 #include "compiler/nir/nir.h"
45 #include "compiler/shader_enums.h"
46 #include "compiler/spirv/nir_spirv.h"
47 #include "rogue_isa.h"
48 #include "util/bitscan.h"
49 #include "util/bitset.h"
50 #include "util/compiler.h"
51 #include "util/list.h"
52 #include "util/sparse_array.h"
53 #include "util/ralloc.h"
54 #include "util/u_dynarray.h"
55 #include "util/u_math.h"
56
57 #include <limits.h>
58 #include <stdarg.h>
59 #include <stdbool.h>
60 #include <stdint.h>
61
62 /* Coefficient registers are typically used in groups of 4. */
63 #define ROGUE_COEFF_ALIGN 4
64
65 #define ROGUE_REG_UNUSED ~0
66
67 /* All registers are 32-bit in size. */
68 #define ROGUE_REG_SIZE_BYTES 4
69
70 /** Rogue register classes. */
71 enum rogue_reg_class {
72 ROGUE_REG_CLASS_INVALID = 0,
73
74 ROGUE_REG_CLASS_SSA, /** SSA register. */
75
76 ROGUE_REG_CLASS_TEMP, /** Temp register. */
77 ROGUE_REG_CLASS_COEFF, /** Coefficient register. */
78 ROGUE_REG_CLASS_SHARED, /** Shared register. */
79
80 ROGUE_REG_CLASS_SPECIAL, /** Special register. */
81 ROGUE_REG_CLASS_INTERNAL, /** Internal register. */
82 ROGUE_REG_CLASS_CONST, /** Constant register. */
83 ROGUE_REG_CLASS_PIXOUT, /** Pixel output register. */
84
85 ROGUE_REG_CLASS_VTXIN, /** Vertex input register. */
86 ROGUE_REG_CLASS_VTXOUT, /** Vertex output register. */
87
88 ROGUE_REG_CLASS_COUNT,
89 } PACKED;
90
91 typedef struct rogue_reg_info {
92 const char *name; /** Human-readable name. */
93 const char *str; /** Register prefix. */
94 unsigned num; /** Number of hardware registers available. */
95 uint64_t supported_io_srcs;
96 } rogue_reg_info;
97
98 extern const rogue_reg_info rogue_reg_infos[ROGUE_REG_CLASS_COUNT];
99
rogue_reg_bank_encoding(enum rogue_reg_class class)100 static inline enum reg_bank rogue_reg_bank_encoding(enum rogue_reg_class class)
101 {
102 switch (class) {
103 case ROGUE_REG_CLASS_TEMP:
104 return BANK_TEMP;
105 case ROGUE_REG_CLASS_COEFF:
106 return BANK_COEFF;
107 case ROGUE_REG_CLASS_SHARED:
108 return BANK_SHARED;
109 case ROGUE_REG_CLASS_SPECIAL:
110 return BANK_SPECIAL;
111 case ROGUE_REG_CLASS_VTXIN:
112 return BANK_VTXIN;
113
114 default:
115 unreachable("Unsupported register class.");
116 }
117 }
118
119 /* TODO: Do this dynamically by iterating
120 * through regarrays and matching sizes.
121 */
122 enum rogue_regalloc_class {
123 ROGUE_REGALLOC_CLASS_TEMP_1,
124 ROGUE_REGALLOC_CLASS_TEMP_2,
125 ROGUE_REGALLOC_CLASS_TEMP_4,
126
127 ROGUE_REGALLOC_CLASS_COUNT,
128 };
129
130 typedef struct rogue_regalloc_info {
131 enum rogue_reg_class class;
132 unsigned stride;
133 } rogue_regalloc_info;
134
135 extern const rogue_regalloc_info regalloc_info[ROGUE_REGALLOC_CLASS_COUNT];
136
137 #define ROGUE_ISA_DSTS 2
138 #define ROGUE_ISA_SRCS 6
139 #define ROGUE_ISA_ISSS 6
140
141 #define ROGUE_ISA_ICACHE_ALIGN 8
142
143 typedef struct rogue_reg_dst_info {
144 unsigned num_dsts;
145 unsigned bank_bits[ROGUE_ISA_DSTS];
146 unsigned index_bits[ROGUE_ISA_DSTS];
147 unsigned bytes;
148 } rogue_reg_dst_info;
149
150 #define ROGUE_REG_DST_VARIANTS 5
151 extern const rogue_reg_dst_info rogue_reg_dst_infos[ROGUE_REG_DST_VARIANTS];
152
153 typedef struct rogue_reg_src_info {
154 unsigned num_srcs;
155 unsigned mux_bits;
156 unsigned bank_bits[ROGUE_ISA_SRCS / 2];
157 unsigned index_bits[ROGUE_ISA_SRCS / 2];
158 unsigned bytes;
159 } rogue_reg_src_info;
160
161 #define ROGUE_REG_SRC_VARIANTS 8
162 extern const rogue_reg_src_info
163 rogue_reg_lower_src_infos[ROGUE_REG_SRC_VARIANTS];
164 extern const rogue_reg_src_info
165 rogue_reg_upper_src_infos[ROGUE_REG_SRC_VARIANTS];
166
167 typedef struct rogue_shader rogue_shader;
168 typedef struct rogue_reg rogue_reg;
169 typedef struct rogue_regarray rogue_regarray;
170
171 /** Rogue register. */
172 typedef struct rogue_reg {
173 rogue_shader *shader; /** Pointer back to shader. */
174 enum rogue_reg_class class; /** Register class. */
175
176 struct list_head link; /** Link in rogue_shader::regs. */
177 struct list_head writes; /** List of all writes to this register. */
178 struct list_head uses; /** List of all register uses. */
179
180 rogue_regarray *regarray;
181
182 bool dirty;
183 uint32_t index; /** Register index. */
184
185 rogue_reg **cached;
186 } rogue_reg;
187
188 #define rogue_foreach_reg(reg, shader, class) \
189 list_for_each_entry (rogue_reg, reg, &(shader)->regs[class], link)
190
191 #define rogue_foreach_reg_safe(reg, shader, class) \
192 list_for_each_entry_safe (rogue_reg, reg, &(shader)->regs[class], link)
193
194 #define REG_CACHE_KEY_COMPONENT_BITS 3
195 #define REG_CACHE_KEY_INDEX_BITS 28
196 #define REG_CACHE_KEY_VEC_BITS 1
197
198 struct rogue_reg_cache_key {
199 union {
200 struct {
201 uint32_t component : REG_CACHE_KEY_COMPONENT_BITS;
202 uint32_t index : REG_CACHE_KEY_INDEX_BITS;
203 uint32_t vec : REG_CACHE_KEY_VEC_BITS;
204 } PACKED;
205
206 uint32_t val;
207 } PACKED;
208 } PACKED;
209 static_assert(sizeof(struct rogue_reg_cache_key) == sizeof(uint32_t),
210 "sizeof(struct rogue_reg_cache_key) != sizeof(uint32_t)");
211
212 static inline uint32_t
rogue_reg_cache_key(unsigned index,bool vec,unsigned component)213 rogue_reg_cache_key(unsigned index, bool vec, unsigned component)
214 {
215 assert(util_last_bit(component) <= REG_CACHE_KEY_COMPONENT_BITS);
216 assert(!vec || util_last_bit(index) <= REG_CACHE_KEY_INDEX_BITS);
217 assert(vec || util_last_bit(index) <= 32);
218 assert(util_last_bit(vec) <= REG_CACHE_KEY_VEC_BITS);
219
220 if (!vec)
221 return index;
222
223 return (struct rogue_reg_cache_key){ .component = component,
224 .index = index,
225 .vec = vec }
226 .val;
227 }
228
rogue_reg_is_unused(rogue_reg * reg)229 static inline bool rogue_reg_is_unused(rogue_reg *reg)
230 {
231 return list_is_empty(®->uses) && list_is_empty(®->writes);
232 }
233
234 struct rogue_regarray_cache_key {
235 union {
236 struct {
237 uint32_t start_index;
238 enum rogue_reg_class class;
239 uint16_t size;
240 uint8_t __pad;
241 } PACKED;
242
243 uint64_t val;
244 } PACKED;
245 } PACKED;
246 static_assert(sizeof(struct rogue_regarray_cache_key) == sizeof(uint64_t),
247 "sizeof(struct rogue_regarray_cache_key) != sizeof(uint64_t)");
248
rogue_regarray_cache_key(unsigned size,enum rogue_reg_class class,uint32_t start_index,bool vec,uint8_t component)249 static inline uint64_t rogue_regarray_cache_key(unsigned size,
250 enum rogue_reg_class class,
251 uint32_t start_index,
252 bool vec,
253 uint8_t component)
254 {
255 uint32_t reg_cache_key = rogue_reg_cache_key(start_index, vec, component);
256 return (struct rogue_regarray_cache_key){ .start_index = reg_cache_key,
257 .class = class,
258 .size = size }
259 .val;
260 }
261
262 typedef struct rogue_regarray {
263 struct list_head link; /** Link in rogue_shader::regarrays. */
264 unsigned size; /** Number of registers in the array. */
265 rogue_regarray *parent;
266 struct list_head children; /** List of subarrays with this regarray as their
267 parent. */
268 struct list_head child_link; /** Link in rogue_regarray::children. */
269 rogue_reg **regs; /** Registers (allocated array if this is a parent, else
270 pointer to inside parent regarray->regs). */
271 rogue_regarray **cached;
272
273 struct list_head writes; /** List of all writes to this register array. */
274 struct list_head uses; /** List of all register array uses. */
275 } rogue_regarray;
276
277 #define rogue_foreach_regarray(regarray, shader) \
278 list_for_each_entry (rogue_regarray, regarray, &(shader)->regarrays, link)
279
280 #define rogue_foreach_regarray_safe(regarray, shader) \
281 list_for_each_entry_safe (rogue_regarray, \
282 regarray, \
283 &(shader)->regarrays, \
284 link)
285
286 #define rogue_foreach_subarray(subarray, regarray) \
287 assert(!regarray->parent); \
288 list_for_each_entry (rogue_regarray, \
289 subarray, \
290 &(regarray)->children, \
291 child_link)
292
293 #define rogue_foreach_subarray_safe(subarray, regarray) \
294 assert(!regarray->parent); \
295 list_for_each_entry_safe (rogue_regarray, \
296 subarray, \
297 &(regarray)->children, \
298 child_link)
299
300 typedef struct rogue_instr rogue_instr;
301
302 typedef struct rogue_regarray_write {
303 rogue_instr *instr;
304 unsigned dst_index;
305 struct list_head link; /** Link in rogue_regarray::writes. */
306 } rogue_regarray_write;
307
308 #define rogue_foreach_regarray_write(write, regarray) \
309 list_for_each_entry (rogue_regarray_write, write, &(regarray)->writes, link)
310
311 #define rogue_foreach_regarray_write_safe(write, regarray) \
312 list_for_each_entry_safe (rogue_regarray_write, \
313 write, \
314 &(regarray)->writes, \
315 link)
316
317 typedef struct rogue_regarray_use {
318 rogue_instr *instr;
319 unsigned src_index;
320 struct list_head link; /** Link in rogue_regarray::uses. */
321 } rogue_regarray_use;
322
323 #define rogue_foreach_regarray_use(use, regarray) \
324 list_for_each_entry (rogue_regarray_use, use, &(regarray)->uses, link)
325
326 #define rogue_foreach_regarray_use_safe(use, regarray) \
327 list_for_each_entry_safe (rogue_regarray_use, use, &(regarray)->uses, link)
328
329 /** Instruction phases, used in bitset. */
330 enum rogue_instr_phase {
331 /** Main/ALU (and backend) instructions. */
332 ROGUE_INSTR_PHASE_0,
333 ROGUE_INSTR_PHASE_1,
334 ROGUE_INSTR_PHASE_2_PCK,
335 ROGUE_INSTR_PHASE_2_TST,
336 ROGUE_INSTR_PHASE_2_MOV,
337 ROGUE_INSTR_PHASE_BACKEND,
338
339 ROGUE_INSTR_PHASE_COUNT,
340
341 /** Control instructions (no co-issuing). */
342 ROGUE_INSTR_PHASE_CTRL = ROGUE_INSTR_PHASE_0,
343
344 /** Bitwise instructions. */
345 ROGUE_INSTR_PHASE_0_BITMASK = ROGUE_INSTR_PHASE_0,
346 ROGUE_INSTR_PHASE_0_SHIFT1 = ROGUE_INSTR_PHASE_1,
347 ROGUE_INSTR_PHASE_0_COUNT = ROGUE_INSTR_PHASE_2_PCK,
348 ROGUE_INSTR_PHASE_1_LOGICAL = ROGUE_INSTR_PHASE_2_TST,
349 ROGUE_INSTR_PHASE_2_SHIFT2 = ROGUE_INSTR_PHASE_2_MOV,
350 ROGUE_INSTR_PHASE_2_TEST = ROGUE_INSTR_PHASE_BACKEND,
351
352 ROGUE_INSTR_PHASE_INVALID = ~0,
353 };
354
355 /* TODO: put into bitscan.h */
356 #define u_foreach_bit64_rev(b, dword) \
357 for (uint64_t __dword = (dword), b; \
358 ((b) = util_last_bit64(__dword) - 1, __dword); \
359 __dword &= ~(1ull << (b)))
360
361 #define rogue_foreach_phase_in_set(p, phases) u_foreach_bit64(p, phases)
362 #define rogue_foreach_phase_in_set_rev(p, phases) u_foreach_bit64_rev(p, phases)
363
364 #define rogue_foreach_mod_in_set(m, mods) u_foreach_bit64(m, mods)
365
366 /** Rogue basic block. */
367 typedef struct rogue_block {
368 rogue_shader *shader; /** Shader containing this block. */
369 struct list_head instrs; /** Basic block instruction list. */
370 struct list_head link; /** Link in rogue_shader::blocks. */
371
372 struct list_head uses; /** List of all block uses. */
373
374 unsigned index; /** Block index. */
375 const char *label; /** Block label. */
376 } rogue_block;
377
378 #define rogue_foreach_block(block, shader) \
379 list_for_each_entry (rogue_block, block, &(shader)->blocks, link)
380
381 #define rogue_foreach_block_safe(block, shader) \
382 list_for_each_entry_safe (rogue_block, block, &(shader)->blocks, link)
383
384 #define rogue_foreach_block_rev(block, shader) \
385 list_for_each_entry_rev (rogue_block, block, &(shader)->blocks, link)
386
387 #define rogue_foreach_block_safe_rev(block, shader) \
388 list_for_each_entry_safe_rev (rogue_block, block, &(shader)->blocks, link)
389
390 /** Rogue execution conditions. */
391 enum rogue_exec_cond {
392 ROGUE_EXEC_COND_INVALID = 0,
393
394 ROGUE_EXEC_COND_PE_TRUE,
395 ROGUE_EXEC_COND_P0_TRUE,
396 ROGUE_EXEC_COND_PE_ANY,
397 ROGUE_EXEC_COND_P0_FALSE,
398
399 ROGUE_EXEC_COND_COUNT,
400 };
401
402 extern const char *rogue_exec_cond_str[ROGUE_EXEC_COND_COUNT];
403
404 /** Rogue instruction type. */
405 enum rogue_instr_type {
406 ROGUE_INSTR_TYPE_INVALID = 0,
407
408 ROGUE_INSTR_TYPE_ALU, /** ALU instruction. */
409 /* ROGUE_INSTR_TYPE_CMPLX, */ /** TODO: Complex/trig instruction (these take
410 up the whole pipeline). */
411 ROGUE_INSTR_TYPE_BACKEND, /** Backend instruction. */
412 ROGUE_INSTR_TYPE_CTRL, /** Control instruction. */
413 ROGUE_INSTR_TYPE_BITWISE, /** Bitwise instruction. */
414 /* ROGUE_INSTR_TYPE_F16SOP, */ /** TODO: F16 sum-of-products instruction. */
415
416 ROGUE_INSTR_TYPE_COUNT,
417 };
418
419 extern const char *rogue_instr_type_str[ROGUE_INSTR_TYPE_COUNT];
420
421 enum rogue_alu {
422 ROGUE_ALU_INVALID = 0,
423
424 ROGUE_ALU_MAIN,
425 ROGUE_ALU_BITWISE,
426 ROGUE_ALU_CONTROL,
427
428 ROGUE_ALU_COUNT,
429 };
430
431 extern const char *const rogue_alu_str[ROGUE_ALU_COUNT];
432
433 extern const char
434 *const rogue_instr_phase_str[ROGUE_ALU_COUNT][ROGUE_INSTR_PHASE_COUNT];
435
436 typedef struct rogue_instr_group rogue_instr_group;
437
438 /** Rogue instruction. */
439 typedef struct rogue_instr {
440 enum rogue_instr_type type; /** Instruction type. */
441
442 enum rogue_exec_cond exec_cond;
443 unsigned repeat;
444 bool end;
445
446 union {
447 struct list_head link; /** Link in rogue_block::instrs. */
448 rogue_instr_group *group; /** Instruction group containing this
449 instruction. */
450 };
451
452 rogue_block *block; /** Basic block containing this instruction. */
453
454 bool group_next; /** Group next instruction with this one. */
455 unsigned index; /** Instruction index. */
456 char *comment; /** Comment string. */
457 } rogue_instr;
458
rogue_set_instr_group_next(rogue_instr * instr,bool group_next)459 static inline void rogue_set_instr_group_next(rogue_instr *instr,
460 bool group_next)
461 {
462 instr->group_next = group_next;
463 }
464
465 #define rogue_foreach_instr_in_block(instr, block) \
466 list_for_each_entry (rogue_instr, instr, &(block)->instrs, link)
467
468 #define rogue_foreach_instr_in_block_safe(instr, block) \
469 list_for_each_entry_safe (rogue_instr, instr, &(block)->instrs, link)
470
471 #define rogue_foreach_instr_in_block_rev(instr, block) \
472 list_for_each_entry_rev (rogue_instr, instr, &(block)->instrs, link)
473
474 #define rogue_foreach_instr_in_block_safe_rev(instr, block) \
475 list_for_each_entry_safe_rev (rogue_instr, instr, &(block)->instrs, link)
476
477 #define rogue_foreach_instr_in_shader(instr, shader) \
478 rogue_foreach_block (_block, (shader)) \
479 rogue_foreach_instr_in_block ((instr), _block)
480
481 #define rogue_foreach_instr_in_shader_safe(instr, shader) \
482 rogue_foreach_block_safe (_block, (shader)) \
483 rogue_foreach_instr_in_block_safe ((instr), _block)
484
485 #define rogue_foreach_instr_in_shader_rev(instr, shader) \
486 rogue_foreach_block_rev (_block, (shader)) \
487 rogue_foreach_instr_in_block_rev ((instr), _block)
488
489 #define rogue_foreach_instr_in_shader_safe_rev(instr, shader) \
490 rogue_foreach_block_safe_rev (_block, (shader)) \
491 rogue_foreach_instr_in_block_safe_rev ((instr), _block)
492
rogue_set_instr_exec_cond(rogue_instr * instr,enum rogue_exec_cond exec_cond)493 static inline void rogue_set_instr_exec_cond(rogue_instr *instr,
494 enum rogue_exec_cond exec_cond)
495 {
496 instr->exec_cond = exec_cond;
497 }
498
rogue_set_instr_repeat(rogue_instr * instr,unsigned repeat)499 static inline void rogue_set_instr_repeat(rogue_instr *instr, unsigned repeat)
500 {
501 instr->repeat = repeat;
502 }
503
rogue_add_instr_comment(rogue_instr * instr,const char * comment)504 static inline void rogue_add_instr_comment(rogue_instr *instr,
505 const char *comment)
506 {
507 if (!instr->comment)
508 instr->comment = ralloc_strdup(instr, comment);
509 else
510 ralloc_asprintf_append(&instr->comment, ", %s", comment);
511 }
512
rogue_copy_instr_comment(rogue_instr * to,const rogue_instr * from)513 static inline void rogue_copy_instr_comment(rogue_instr *to,
514 const rogue_instr *from)
515 {
516 if (!from->comment)
517 return;
518
519 rogue_add_instr_comment(to, from->comment);
520 }
521
rogue_merge_instr_comment(rogue_instr * to,const rogue_instr * from,const char * comment)522 static inline void rogue_merge_instr_comment(rogue_instr *to,
523 const rogue_instr *from,
524 const char *comment)
525 {
526 rogue_copy_instr_comment(to, from);
527 rogue_add_instr_comment(to, comment);
528 }
529
530 typedef union rogue_imm_t {
531 float f32;
532 int32_t s32;
533 uint32_t u32;
534 } rogue_imm_t;
535
536 enum rogue_io {
537 ROGUE_IO_INVALID = 0,
538
539 /* Lower sources. */
540 ROGUE_IO_S0,
541 ROGUE_IO_S1,
542 ROGUE_IO_S2,
543
544 /* Upper sources. */
545 ROGUE_IO_S3,
546 ROGUE_IO_S4,
547 ROGUE_IO_S5,
548
549 /* Destinations. */
550 ROGUE_IO_W0,
551 ROGUE_IO_W1,
552
553 /* Internal selectors. */
554 ROGUE_IO_IS0,
555 ROGUE_IO_IS1,
556 ROGUE_IO_IS2,
557 ROGUE_IO_IS3,
558 ROGUE_IO_IS4,
559 ROGUE_IO_IS5,
560
561 /* Feedthroughs. */
562 ROGUE_IO_FT0,
563 ROGUE_IO_FT1,
564 ROGUE_IO_FT2,
565 ROGUE_IO_FTE,
566
567 /* Only used for bitwise instructions. */
568 ROGUE_IO_FT3,
569 ROGUE_IO_FT4,
570 ROGUE_IO_FT5,
571
572 /* Test output feedthrough. */
573 ROGUE_IO_FTT,
574
575 /* Predicate register. */
576 ROGUE_IO_P0,
577
578 /* For optional instruction arguments. */
579 ROGUE_IO_NONE,
580
581 ROGUE_IO_COUNT,
582 };
583
rogue_io_is_src(enum rogue_io io)584 static inline bool rogue_io_is_src(enum rogue_io io)
585 {
586 return (io >= ROGUE_IO_S0 && io <= ROGUE_IO_S5);
587 }
588
rogue_io_is_dst(enum rogue_io io)589 static inline bool rogue_io_is_dst(enum rogue_io io)
590 {
591 return (io >= ROGUE_IO_W0 && io <= ROGUE_IO_W1);
592 }
593
rogue_io_is_iss(enum rogue_io io)594 static inline bool rogue_io_is_iss(enum rogue_io io)
595 {
596 return (io >= ROGUE_IO_IS0 && io <= ROGUE_IO_IS5);
597 }
598
rogue_io_is_ft(enum rogue_io io)599 static inline bool rogue_io_is_ft(enum rogue_io io)
600 {
601 return (io >= ROGUE_IO_FT0 && io <= ROGUE_IO_FTE);
602 }
603
rogue_io_is_none(enum rogue_io io)604 static inline bool rogue_io_is_none(enum rogue_io io)
605 {
606 return io == ROGUE_IO_NONE;
607 }
608
609 typedef struct rogue_io_info {
610 const char *str;
611 } rogue_io_info;
612
613 extern const rogue_io_info rogue_io_infos[ROGUE_IO_COUNT];
614
rogue_io_supported(enum rogue_io io,uint64_t supported_ios)615 static inline bool rogue_io_supported(enum rogue_io io, uint64_t supported_ios)
616 {
617 return !!(BITFIELD64_BIT(io - 1) & supported_ios);
618 }
619
620 #define ROGUE_DRCS 2
621
622 typedef struct rogue_drc_trxn {
623 rogue_instr *acquire;
624 rogue_instr *release;
625 struct list_head link; /** Link in rogue_shader::drc_trxns[0/1]. */
626 } rogue_drc_trxn;
627
628 #define rogue_foreach_drc_trxn(drc_trxn, shader, index) \
629 list_for_each_entry (rogue_drc_trxn, \
630 drc_trxn, \
631 &(shader)->drc_trxns[index], \
632 link)
633
634 #define rogue_foreach_drc_trxn_safe(drc_trxn, shader, index) \
635 list_for_each_entry_safe (rogue_drc_trxn, \
636 drc_trxn, \
637 &(shader)->drc_trxns[index], \
638 link)
639
640 enum rogue_ref_type {
641 ROGUE_REF_TYPE_INVALID = 0,
642
643 ROGUE_REF_TYPE_VAL, /* Immediate that is not going to be replaced with a
644 register reference. */
645
646 ROGUE_REF_TYPE_REG,
647 ROGUE_REF_TYPE_REGARRAY,
648
649 ROGUE_REF_TYPE_IMM, /* Immediate that is going to be replaced with a register
650 reference. */
651
652 ROGUE_REF_TYPE_IO,
653
654 ROGUE_REF_TYPE_DRC,
655
656 ROGUE_REF_TYPE_COUNT,
657 };
658
659 typedef struct rogue_drc {
660 unsigned index;
661 union {
662 rogue_drc_trxn trxn;
663 rogue_drc_trxn *trxn_ptr;
664 };
665 } rogue_drc;
666
667 typedef struct rogue_imm_use {
668 rogue_instr *instr;
669 unsigned src_index;
670 rogue_imm_t *imm;
671 struct list_head link; /** Link in rogue_shader::imm_uses. */
672 } rogue_imm_use;
673
674 #define rogue_foreach_imm_use(imm_use, shader) \
675 list_for_each_entry (rogue_imm_use, imm_use, &(shader)->imm_uses, link)
676
677 #define rogue_foreach_imm_use_safe(imm_use, shader) \
678 list_for_each_entry_safe (rogue_imm_use, imm_use, &(shader)->imm_uses, link)
679
680 typedef struct rogue_imm {
681 rogue_imm_t imm;
682 rogue_imm_use use;
683 } rogue_imm;
684
685 typedef struct rogue_ref {
686 enum rogue_ref_type type;
687
688 union {
689 unsigned val;
690 rogue_imm imm;
691 rogue_reg *reg;
692 rogue_regarray *regarray;
693 enum rogue_io io;
694 rogue_drc drc;
695 };
696 } rogue_ref;
697
rogue_ref_type_supported(enum rogue_ref_type type,uint64_t supported_types)698 static inline bool rogue_ref_type_supported(enum rogue_ref_type type,
699 uint64_t supported_types)
700 {
701 return !!(BITFIELD64_BIT(type - 1) & supported_types);
702 }
703
704 /**
705 * \brief Returns a reference to a value.
706 *
707 * \param[in] val The value.
708 * \return The reference.
709 */
rogue_ref_val(unsigned val)710 static inline rogue_ref rogue_ref_val(unsigned val)
711 {
712 return (rogue_ref){
713 .type = ROGUE_REF_TYPE_VAL,
714 .val = val,
715 };
716 }
717
718 /**
719 * \brief Returns a reference to a register.
720 *
721 * \param[in] reg The register.
722 * \return The reference.
723 */
rogue_ref_reg(rogue_reg * reg)724 static inline rogue_ref rogue_ref_reg(rogue_reg *reg)
725 {
726 return (rogue_ref){
727 .type = ROGUE_REF_TYPE_REG,
728 .reg = reg,
729 };
730 }
731
732 /**
733 * \brief Returns a reference to a register array.
734 *
735 * \param[in] regarray The register array.
736 * \return The reference.
737 */
rogue_ref_regarray(rogue_regarray * regarray)738 static inline rogue_ref rogue_ref_regarray(rogue_regarray *regarray)
739 {
740 return (rogue_ref){
741 .type = ROGUE_REF_TYPE_REGARRAY,
742 .regarray = regarray,
743 };
744 }
745
rogue_ref_imm(uint32_t imm)746 static inline rogue_ref rogue_ref_imm(uint32_t imm)
747 {
748 return (rogue_ref){
749 .type = ROGUE_REF_TYPE_IMM,
750 .imm.imm.u32 = imm,
751 };
752 }
753
rogue_ref_io(enum rogue_io io)754 static inline rogue_ref rogue_ref_io(enum rogue_io io)
755 {
756 return (rogue_ref){
757 .type = ROGUE_REF_TYPE_IO,
758 .io = io,
759 };
760 }
761
rogue_ref_drc(unsigned index)762 static inline rogue_ref rogue_ref_drc(unsigned index)
763 {
764 return (rogue_ref){
765 .type = ROGUE_REF_TYPE_DRC,
766 .drc.index = index,
767 };
768 }
769
rogue_ref_drc_trxn(unsigned index,rogue_drc_trxn * drc_trxn)770 static inline rogue_ref rogue_ref_drc_trxn(unsigned index,
771 rogue_drc_trxn *drc_trxn)
772 {
773 return (rogue_ref){
774 .type = ROGUE_REF_TYPE_DRC,
775 .drc.index = index,
776 .drc.trxn_ptr = drc_trxn,
777 };
778 }
779
rogue_ref_null(void)780 static inline rogue_ref rogue_ref_null(void)
781 {
782 return (rogue_ref){};
783 }
784
rogue_ref_is_imm(const rogue_ref * ref)785 static inline bool rogue_ref_is_imm(const rogue_ref *ref)
786 {
787 return ref->type == ROGUE_REF_TYPE_IMM;
788 }
789
rogue_ref_is_val(const rogue_ref * ref)790 static inline bool rogue_ref_is_val(const rogue_ref *ref)
791 {
792 return ref->type == ROGUE_REF_TYPE_VAL;
793 }
794
rogue_ref_is_reg(const rogue_ref * ref)795 static inline bool rogue_ref_is_reg(const rogue_ref *ref)
796 {
797 return ref->type == ROGUE_REF_TYPE_REG;
798 }
799
rogue_ref_is_special_reg(const rogue_ref * ref)800 static inline bool rogue_ref_is_special_reg(const rogue_ref *ref)
801 {
802 return rogue_ref_is_reg(ref) && ref->reg->class == ROGUE_REG_CLASS_SPECIAL;
803 }
804
rogue_ref_is_regarray(const rogue_ref * ref)805 static inline bool rogue_ref_is_regarray(const rogue_ref *ref)
806 {
807 return ref->type == ROGUE_REF_TYPE_REGARRAY;
808 }
809
rogue_ref_is_reg_or_regarray(const rogue_ref * ref)810 static inline bool rogue_ref_is_reg_or_regarray(const rogue_ref *ref)
811 {
812 return rogue_ref_is_reg(ref) || rogue_ref_is_regarray(ref);
813 }
814
rogue_ref_is_io(const rogue_ref * ref)815 static inline bool rogue_ref_is_io(const rogue_ref *ref)
816 {
817 return ref->type == ROGUE_REF_TYPE_IO;
818 }
819
rogue_ref_is_drc(const rogue_ref * ref)820 static inline bool rogue_ref_is_drc(const rogue_ref *ref)
821 {
822 return ref->type == ROGUE_REF_TYPE_DRC;
823 }
824
rogue_ref_is_null(const rogue_ref * ref)825 static inline bool rogue_ref_is_null(const rogue_ref *ref)
826 {
827 return ref->type == ROGUE_REF_TYPE_INVALID;
828 }
829
rogue_ref_get_reg_class(const rogue_ref * ref)830 static inline enum rogue_reg_class rogue_ref_get_reg_class(const rogue_ref *ref)
831 {
832 if (rogue_ref_is_regarray(ref))
833 return ref->regarray->regs[0]->class;
834 else if (rogue_ref_is_reg(ref))
835 return ref->reg->class;
836 unreachable("Ref is not a reg/regarray.");
837 }
838
rogue_ref_get_reg_index(const rogue_ref * ref)839 static inline unsigned rogue_ref_get_reg_index(const rogue_ref *ref)
840 {
841 if (rogue_ref_is_regarray(ref))
842 return ref->regarray->regs[0]->index;
843 else if (rogue_ref_is_reg(ref))
844 return ref->reg->index;
845 unreachable("Ref is not a reg/regarray.");
846 }
847
rogue_ref_get_regarray_size(const rogue_ref * ref)848 static inline unsigned rogue_ref_get_regarray_size(const rogue_ref *ref)
849 {
850 if (rogue_ref_is_regarray(ref))
851 return ref->regarray->size;
852 unreachable("Ref is not a regarray.");
853 }
854
855 #define ROGUE_INTERNAL0_OFFSET 36
856 #define ROGUE_INTERNAL_GROUP 8
857
858 #define ROGUE_PIXOUT0_OFFSET 32
859 #define ROGUE_PIXOUT4_OFFSET 164
860 #define ROGUE_PIXOUT_GROUP 4
861
rogue_ref_is_pixout(rogue_ref * ref)862 static inline bool rogue_ref_is_pixout(rogue_ref *ref)
863 {
864 enum rogue_reg_class class;
865 unsigned index;
866
867 if (!rogue_ref_is_reg(ref) && !rogue_ref_is_regarray(ref))
868 return false;
869
870 class = rogue_ref_get_reg_class(ref);
871
872 if (class == ROGUE_REG_CLASS_PIXOUT)
873 return true;
874 else if (class != ROGUE_REG_CLASS_SPECIAL)
875 return false;
876
877 index = rogue_ref_get_reg_index(ref);
878
879 return (index >= ROGUE_PIXOUT0_OFFSET &&
880 index < (ROGUE_PIXOUT0_OFFSET + ROGUE_PIXOUT_GROUP)) ||
881 (index >= ROGUE_PIXOUT4_OFFSET &&
882 index < (ROGUE_PIXOUT4_OFFSET + ROGUE_PIXOUT_GROUP));
883 }
884
rogue_ref_get_io(const rogue_ref * ref)885 static inline enum rogue_io rogue_ref_get_io(const rogue_ref *ref)
886 {
887 assert(rogue_ref_is_io(ref));
888 return ref->io;
889 }
890
rogue_ref_is_io_p0(const rogue_ref * ref)891 static inline bool rogue_ref_is_io_p0(const rogue_ref *ref)
892 {
893 return rogue_ref_get_io(ref) == ROGUE_IO_P0;
894 }
895
rogue_ref_is_io_ftt(const rogue_ref * ref)896 static inline bool rogue_ref_is_io_ftt(const rogue_ref *ref)
897 {
898 return rogue_ref_get_io(ref) == ROGUE_IO_FTT;
899 }
900
rogue_ref_is_io_none(const rogue_ref * ref)901 static inline bool rogue_ref_is_io_none(const rogue_ref *ref)
902 {
903 /* Special case - never assert. */
904 if (!rogue_ref_is_io(ref))
905 return false;
906
907 return rogue_ref_get_io(ref) == ROGUE_IO_NONE;
908 }
909
rogue_ref_get_io_src_index(const rogue_ref * ref)910 static inline unsigned rogue_ref_get_io_src_index(const rogue_ref *ref)
911 {
912 return rogue_ref_get_io(ref) - ROGUE_IO_S0;
913 }
914
rogue_ref_get_drc_index(const rogue_ref * ref)915 static inline unsigned rogue_ref_get_drc_index(const rogue_ref *ref)
916 {
917 assert(rogue_ref_is_drc(ref));
918 return ref->drc.index;
919 }
920
rogue_ref_get_drc(rogue_ref * ref)921 static inline rogue_drc *rogue_ref_get_drc(rogue_ref *ref)
922 {
923 assert(rogue_ref_is_drc(ref));
924 return &ref->drc;
925 }
926
rogue_ref_get_val(const rogue_ref * ref)927 static inline unsigned rogue_ref_get_val(const rogue_ref *ref)
928 {
929 assert(rogue_ref_is_val(ref));
930 return ref->val;
931 }
932
rogue_ref_get_imm(rogue_ref * ref)933 static inline rogue_imm *rogue_ref_get_imm(rogue_ref *ref)
934 {
935 assert(rogue_ref_is_imm(ref));
936 return &ref->imm;
937 }
938
rogue_refs_equal(rogue_ref * a,rogue_ref * b)939 static inline bool rogue_refs_equal(rogue_ref *a, rogue_ref *b)
940 {
941 if (a->type != b->type)
942 return false;
943
944 switch (a->type) {
945 case ROGUE_REF_TYPE_VAL:
946 return a->val == b->val;
947
948 case ROGUE_REF_TYPE_REG:
949 return a->reg == b->reg;
950
951 case ROGUE_REF_TYPE_REGARRAY:
952 return a->regarray == b->regarray;
953
954 case ROGUE_REF_TYPE_IMM:
955 return a->imm.imm.u32 == b->imm.imm.u32;
956
957 case ROGUE_REF_TYPE_IO:
958 return a->io == b->io;
959
960 case ROGUE_REF_TYPE_DRC:
961 return a->drc.index == b->drc.index;
962
963 default:
964 break;
965 }
966
967 return false;
968 }
969
970 typedef struct rogue_instr_dst {
971 rogue_ref ref;
972 uint64_t mod;
973 unsigned index;
974 } rogue_instr_dst;
975
976 typedef struct rogue_instr_src {
977 rogue_ref ref;
978 uint64_t mod;
979 unsigned index;
980 } rogue_instr_src;
981
rogue_instr_dst_src_equal(rogue_instr_dst * dst,rogue_instr_src * src)982 static inline bool rogue_instr_dst_src_equal(rogue_instr_dst *dst,
983 rogue_instr_src *src)
984 {
985 /* TODO: Take modifiers into account. */
986 if (dst->mod || src->mod)
987 return false;
988
989 return rogue_refs_equal(&dst->ref, &src->ref);
990 }
991
992 typedef struct rogue_reg_write {
993 rogue_instr *instr;
994 unsigned dst_index;
995 struct list_head link; /** Link in rogue_reg::writes. */
996 } rogue_reg_write;
997
998 #define rogue_foreach_reg_write(write, reg) \
999 list_for_each_entry (rogue_reg_write, write, &(reg)->writes, link)
1000
1001 #define rogue_foreach_reg_write_safe(write, reg) \
1002 list_for_each_entry_safe (rogue_reg_write, write, &(reg)->writes, link)
1003
1004 typedef struct rogue_reg_use {
1005 rogue_instr *instr;
1006 unsigned src_index;
1007 struct list_head link; /** Link in rogue_reg::uses. */
1008 } rogue_reg_use;
1009
1010 #define rogue_foreach_reg_use(use, reg) \
1011 list_for_each_entry (rogue_reg_use, use, &(reg)->uses, link)
1012
1013 #define rogue_foreach_reg_use_safe(use, reg) \
1014 list_for_each_entry_safe (rogue_reg_use, use, &(reg)->uses, link)
1015
1016 typedef union rogue_dst_write {
1017 rogue_reg_write reg;
1018 rogue_regarray_write regarray;
1019 } rogue_dst_write;
1020
1021 typedef union rogue_src_use {
1022 rogue_reg_use reg;
1023 rogue_regarray_use regarray;
1024 } rogue_src_use;
1025
1026 typedef struct rogue_block_use {
1027 rogue_instr *instr;
1028 struct list_head link; /** Link in rogue_block::uses. */
1029 } rogue_block_use;
1030
1031 #define rogue_foreach_block_use(use, block) \
1032 list_for_each_entry (rogue_block_use, use, &(block)->uses, link)
1033
1034 #define rogue_foreach_block_use_safe(use, block) \
1035 list_for_each_entry_safe (rogue_block_use, use, &(block)->uses, link)
1036
1037 /** Rogue ALU instruction operations. */
1038 enum rogue_alu_op {
1039 ROGUE_ALU_OP_INVALID = 0,
1040
1041 /* Real instructions. */
1042
1043 ROGUE_ALU_OP_MBYP,
1044
1045 ROGUE_ALU_OP_FADD,
1046 ROGUE_ALU_OP_FMUL,
1047 ROGUE_ALU_OP_FMAD,
1048
1049 ROGUE_ALU_OP_ADD64,
1050
1051 ROGUE_ALU_OP_TST,
1052 ROGUE_ALU_OP_MOVC,
1053
1054 ROGUE_ALU_OP_PCK_U8888,
1055
1056 /* Pseudo-instructions. */
1057 ROGUE_ALU_OP_PSEUDO,
1058 ROGUE_ALU_OP_MOV = ROGUE_ALU_OP_PSEUDO,
1059 ROGUE_ALU_OP_CMOV, /** Conditional move. */
1060
1061 ROGUE_ALU_OP_FABS,
1062 ROGUE_ALU_OP_FNEG,
1063 ROGUE_ALU_OP_FNABS,
1064
1065 ROGUE_ALU_OP_FMAX,
1066 ROGUE_ALU_OP_FMIN,
1067
1068 ROGUE_ALU_OP_COUNT,
1069 };
1070
1071 enum rogue_alu_op_mod {
1072 /* In order of priority */
1073 ROGUE_ALU_OP_MOD_LP, /* Low-precision modifier (force 13 lsbs of all sources
1074 to zero before op, and of result after op). */
1075 ROGUE_ALU_OP_MOD_SAT, /* Saturate output. */
1076
1077 ROGUE_ALU_OP_MOD_SCALE, /* Scale to [0, 1]. */
1078 ROGUE_ALU_OP_MOD_ROUNDZERO, /* Round to zero. */
1079
1080 ROGUE_ALU_OP_MOD_Z, /** Test == 0. */
1081 ROGUE_ALU_OP_MOD_GZ, /** Test > 0. */
1082 ROGUE_ALU_OP_MOD_GEZ, /** Test >= 0. */
1083 ROGUE_ALU_OP_MOD_C, /** Test integer carry-out. */
1084 ROGUE_ALU_OP_MOD_E, /** Test a == b. */
1085 ROGUE_ALU_OP_MOD_G, /** Test a > b. */
1086 ROGUE_ALU_OP_MOD_GE, /** Test a >= b. */
1087 ROGUE_ALU_OP_MOD_NE, /** Test a != b. */
1088 ROGUE_ALU_OP_MOD_L, /** Test a < b. */
1089 ROGUE_ALU_OP_MOD_LE, /** Test a <= b. */
1090
1091 ROGUE_ALU_OP_MOD_F32,
1092 ROGUE_ALU_OP_MOD_U16,
1093 ROGUE_ALU_OP_MOD_S16,
1094 ROGUE_ALU_OP_MOD_U8,
1095 ROGUE_ALU_OP_MOD_S8,
1096 ROGUE_ALU_OP_MOD_U32,
1097 ROGUE_ALU_OP_MOD_S32,
1098
1099 ROGUE_ALU_OP_MOD_COUNT,
1100 };
1101
1102 typedef struct rogue_alu_op_mod_info {
1103 const char *str;
1104 uint64_t exclude; /* Can't use this op mod with any of these. */
1105 uint64_t require; /* Required op mods for this to be used (OR). */
1106 } rogue_alu_op_mod_info;
1107
1108 extern const rogue_alu_op_mod_info
1109 rogue_alu_op_mod_infos[ROGUE_ALU_OP_MOD_COUNT];
1110
rogue_mods_supported(uint64_t mods,uint64_t supported_mods)1111 static inline bool rogue_mods_supported(uint64_t mods, uint64_t supported_mods)
1112 {
1113 return !(mods & ~supported_mods);
1114 }
1115
1116 enum rogue_alu_dst_mod {
1117 ROGUE_ALU_DST_MOD_E0,
1118 ROGUE_ALU_DST_MOD_E1,
1119 ROGUE_ALU_DST_MOD_E2,
1120 ROGUE_ALU_DST_MOD_E3,
1121
1122 ROGUE_ALU_DST_MOD_COUNT,
1123 };
1124
1125 typedef struct rogue_alu_dst_mod_info {
1126 const char *str;
1127 } rogue_alu_dst_mod_info;
1128
1129 extern const rogue_alu_dst_mod_info
1130 rogue_alu_dst_mod_infos[ROGUE_ALU_DST_MOD_COUNT];
1131
1132 enum rogue_alu_src_mod {
1133 /* In order of priority, i.e. if all NEG, ABS, and FLR are all set, FLR will
1134 happen first, then ABS, then NEG. */
1135 ROGUE_ALU_SRC_MOD_FLR,
1136 ROGUE_ALU_SRC_MOD_ABS,
1137 ROGUE_ALU_SRC_MOD_NEG,
1138
1139 ROGUE_ALU_SRC_MOD_E0,
1140 ROGUE_ALU_SRC_MOD_E1,
1141 ROGUE_ALU_SRC_MOD_E2,
1142 ROGUE_ALU_SRC_MOD_E3,
1143
1144 ROGUE_ALU_SRC_MOD_COUNT,
1145 };
1146
1147 typedef struct rogue_alu_src_mod_info {
1148 const char *str;
1149 } rogue_alu_src_mod_info;
1150
1151 extern const rogue_alu_src_mod_info
1152 rogue_alu_src_mod_infos[ROGUE_ALU_SRC_MOD_COUNT];
1153
1154 enum rogue_ctrl_op {
1155 ROGUE_CTRL_OP_INVALID = 0,
1156
1157 /* Real instructions. */
1158 ROGUE_CTRL_OP_NOP,
1159 ROGUE_CTRL_OP_WOP,
1160 ROGUE_CTRL_OP_BR, /* Branch: relative (to block). */
1161 ROGUE_CTRL_OP_BA, /* Branch: absolute (to address). */
1162 ROGUE_CTRL_OP_WDF,
1163
1164 /* Pseudo-instructions. */
1165 ROGUE_CTRL_OP_PSEUDO,
1166 ROGUE_CTRL_OP_END = ROGUE_CTRL_OP_PSEUDO,
1167
1168 ROGUE_CTRL_OP_COUNT,
1169 };
1170
1171 enum rogue_ctrl_op_mod {
1172 /* In order of priority */
1173 ROGUE_CTRL_OP_MOD_LINK,
1174
1175 ROGUE_CTRL_OP_MOD_ALLINST,
1176 ROGUE_CTRL_OP_MOD_ANYINST,
1177
1178 ROGUE_CTRL_OP_MOD_END,
1179
1180 ROGUE_CTRL_OP_MOD_COUNT,
1181 };
1182
1183 typedef struct rogue_ctrl_op_mod_info {
1184 const char *str;
1185 uint64_t exclude; /* Can't use this op mod with any of these. */
1186 uint64_t require; /* Required op mods for this to be used (OR). */
1187 } rogue_ctrl_op_mod_info;
1188
1189 extern const rogue_ctrl_op_mod_info
1190 rogue_ctrl_op_mod_infos[ROGUE_CTRL_OP_MOD_COUNT];
1191
1192 #define ROGUE_CTRL_OP_MAX_SRCS 7
1193 #define ROGUE_CTRL_OP_MAX_DSTS 2
1194
1195 typedef struct rogue_ctrl_op_info {
1196 const char *str;
1197
1198 bool has_target; /* Has a block as a target. */
1199 bool ends_block; /* Can be the instruction at the end of a block. */
1200 bool has_srcs; /* Has encodable sources. */
1201 bool has_dsts; /* Has encodable destinations. */
1202
1203 unsigned num_dsts;
1204 unsigned num_srcs;
1205
1206 uint64_t supported_op_mods;
1207 uint64_t supported_dst_mods[ROGUE_CTRL_OP_MAX_DSTS];
1208 uint64_t supported_src_mods[ROGUE_CTRL_OP_MAX_SRCS];
1209
1210 uint64_t supported_dst_types[ROGUE_CTRL_OP_MAX_DSTS];
1211 uint64_t supported_src_types[ROGUE_CTRL_OP_MAX_SRCS];
1212
1213 unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1214 unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1215
1216 uint64_t dst_repeat_mask;
1217 uint64_t src_repeat_mask;
1218 } rogue_ctrl_op_info;
1219
1220 extern const rogue_ctrl_op_info rogue_ctrl_op_infos[ROGUE_CTRL_OP_COUNT];
1221
rogue_ctrl_op_has_srcs(enum rogue_ctrl_op op)1222 static inline bool rogue_ctrl_op_has_srcs(enum rogue_ctrl_op op)
1223 {
1224 const rogue_ctrl_op_info *info = &rogue_ctrl_op_infos[op];
1225 return info->has_srcs;
1226 }
1227
rogue_ctrl_op_has_dsts(enum rogue_ctrl_op op)1228 static inline bool rogue_ctrl_op_has_dsts(enum rogue_ctrl_op op)
1229 {
1230 const rogue_ctrl_op_info *info = &rogue_ctrl_op_infos[op];
1231 return info->has_dsts;
1232 }
1233
1234 /* ALU instructions have at most 5 sources. */
1235 #define ROGUE_ALU_OP_MAX_SRCS 5
1236 #define ROGUE_ALU_OP_MAX_DSTS 3
1237
1238 typedef struct rogue_alu_io_info {
1239 enum rogue_io dst[ROGUE_ALU_OP_MAX_DSTS];
1240 enum rogue_io src[ROGUE_ALU_OP_MAX_SRCS];
1241 } rogue_alu_io_info;
1242
1243 /** Rogue ALU instruction operation info. */
1244 typedef struct rogue_alu_op_info {
1245 const char *str;
1246
1247 unsigned num_dsts;
1248 unsigned num_srcs;
1249
1250 uint64_t supported_phases;
1251 rogue_alu_io_info phase_io[ROGUE_INSTR_PHASE_COUNT];
1252
1253 uint64_t supported_op_mods;
1254 uint64_t supported_dst_mods[ROGUE_ALU_OP_MAX_DSTS];
1255 uint64_t supported_src_mods[ROGUE_ALU_OP_MAX_SRCS];
1256
1257 uint64_t supported_dst_types[ROGUE_ALU_OP_MAX_DSTS];
1258 uint64_t supported_src_types[ROGUE_ALU_OP_MAX_SRCS];
1259
1260 unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1261 unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1262
1263 uint64_t dst_repeat_mask;
1264 uint64_t src_repeat_mask;
1265 } rogue_alu_op_info;
1266
1267 extern const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT];
1268
1269 /** Rogue ALU instruction. */
1270 typedef struct rogue_alu_instr {
1271 rogue_instr instr;
1272
1273 enum rogue_alu_op op;
1274
1275 uint64_t mod;
1276
1277 rogue_instr_dst dst[ROGUE_ALU_OP_MAX_DSTS];
1278 rogue_dst_write dst_write[ROGUE_ALU_OP_MAX_DSTS];
1279
1280 rogue_instr_src src[ROGUE_ALU_OP_MAX_SRCS];
1281 rogue_src_use src_use[ROGUE_ALU_OP_MAX_SRCS];
1282 } rogue_alu_instr;
1283
rogue_set_alu_op_mod(rogue_alu_instr * alu,enum rogue_alu_op_mod mod)1284 static inline void rogue_set_alu_op_mod(rogue_alu_instr *alu,
1285 enum rogue_alu_op_mod mod)
1286 {
1287 alu->mod |= BITFIELD64_BIT(mod);
1288 }
1289
rogue_alu_op_mod_is_set(const rogue_alu_instr * alu,enum rogue_alu_op_mod mod)1290 static inline bool rogue_alu_op_mod_is_set(const rogue_alu_instr *alu,
1291 enum rogue_alu_op_mod mod)
1292 {
1293 return !!(alu->mod & BITFIELD64_BIT(mod));
1294 }
1295
rogue_set_alu_dst_mod(rogue_alu_instr * alu,unsigned dst_index,enum rogue_alu_dst_mod mod)1296 static inline void rogue_set_alu_dst_mod(rogue_alu_instr *alu,
1297 unsigned dst_index,
1298 enum rogue_alu_dst_mod mod)
1299 {
1300 alu->dst[dst_index].mod |= BITFIELD64_BIT(mod);
1301 }
1302
rogue_alu_dst_mod_is_set(const rogue_alu_instr * alu,unsigned dst_index,enum rogue_alu_dst_mod mod)1303 static inline bool rogue_alu_dst_mod_is_set(const rogue_alu_instr *alu,
1304 unsigned dst_index,
1305 enum rogue_alu_dst_mod mod)
1306 {
1307 return !!(alu->dst[dst_index].mod & BITFIELD64_BIT(mod));
1308 }
1309
rogue_set_alu_src_mod(rogue_alu_instr * alu,unsigned src_index,enum rogue_alu_src_mod mod)1310 static inline void rogue_set_alu_src_mod(rogue_alu_instr *alu,
1311 unsigned src_index,
1312 enum rogue_alu_src_mod mod)
1313 {
1314 alu->src[src_index].mod |= BITFIELD64_BIT(mod);
1315 }
1316
rogue_alu_src_mod_is_set(const rogue_alu_instr * alu,unsigned src_index,enum rogue_alu_src_mod mod)1317 static inline bool rogue_alu_src_mod_is_set(const rogue_alu_instr *alu,
1318 unsigned src_index,
1319 enum rogue_alu_src_mod mod)
1320 {
1321 return !!(alu->src[src_index].mod & BITFIELD64_BIT(mod));
1322 }
1323
1324 /**
1325 * \brief Allocates and initializes a new ALU instruction.
1326 *
1327 * \param[in] block The block which will contain the instruction.
1328 * \param[in] op The ALU instruction operation.
1329 * \return The new instruction.
1330 */
1331 rogue_alu_instr *rogue_alu_instr_create(rogue_block *block,
1332 enum rogue_alu_op op);
1333
1334 #define ROGUE_BACKEND_OP_MAX_SRCS 6
1335 #define ROGUE_BACKEND_OP_MAX_DSTS 2
1336
1337 enum rogue_backend_op {
1338 ROGUE_BACKEND_OP_INVALID = 0,
1339
1340 ROGUE_BACKEND_OP_UVSW_WRITE,
1341 ROGUE_BACKEND_OP_UVSW_EMIT,
1342 /* ROGUE_BACKEND_OP_UVSW_CUT, */
1343 /* ROGUE_BACKEND_OP_UVSW_EMITTHENCUT, */
1344 ROGUE_BACKEND_OP_UVSW_ENDTASK,
1345 ROGUE_BACKEND_OP_UVSW_EMITTHENENDTASK,
1346 ROGUE_BACKEND_OP_UVSW_WRITETHENEMITTHENENDTASK,
1347
1348 ROGUE_BACKEND_OP_IDF,
1349
1350 ROGUE_BACKEND_OP_EMITPIX,
1351
1352 ROGUE_BACKEND_OP_LD,
1353 ROGUE_BACKEND_OP_ST,
1354
1355 ROGUE_BACKEND_OP_FITR_PIXEL,
1356 /* ROGUE_BACKEND_OP_SAMPLE, */
1357 /* ROGUE_BACKEND_OP_CENTROID, */
1358 ROGUE_BACKEND_OP_FITRP_PIXEL,
1359 /* ROGUE_BACKEND_OP_FITRP_SAMPLE, */
1360 /* ROGUE_BACKEND_OP_FITRP_CENTROID, */
1361
1362 ROGUE_BACKEND_OP_SMP1D,
1363 ROGUE_BACKEND_OP_SMP2D,
1364 ROGUE_BACKEND_OP_SMP3D,
1365
1366 ROGUE_BACKEND_OP_PSEUDO,
1367 ROGUE_BACKEND_OP_COUNT = ROGUE_BACKEND_OP_PSEUDO,
1368 };
1369
1370 typedef struct rogue_backend_io_info {
1371 enum rogue_io dst[ROGUE_BACKEND_OP_MAX_DSTS];
1372 enum rogue_io src[ROGUE_BACKEND_OP_MAX_SRCS];
1373 } rogue_backend_io_info;
1374
1375 typedef struct rogue_backend_op_info {
1376 const char *str;
1377
1378 unsigned num_dsts;
1379 unsigned num_srcs;
1380
1381 /* supported_phases not needed as it's always going to be in the backend
1382 * phase. */
1383 rogue_backend_io_info phase_io;
1384
1385 uint64_t supported_op_mods;
1386 uint64_t supported_dst_mods[ROGUE_BACKEND_OP_MAX_DSTS];
1387 uint64_t supported_src_mods[ROGUE_BACKEND_OP_MAX_SRCS];
1388
1389 uint64_t supported_dst_types[ROGUE_BACKEND_OP_MAX_DSTS];
1390 uint64_t supported_src_types[ROGUE_BACKEND_OP_MAX_SRCS];
1391
1392 unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1393 unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1394
1395 uint64_t dst_repeat_mask;
1396 uint64_t src_repeat_mask;
1397 } rogue_backend_op_info;
1398
1399 extern const rogue_backend_op_info
1400 rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT];
1401
1402 enum rogue_backend_op_mod {
1403 /* In order of priority */
1404 ROGUE_BACKEND_OP_MOD_PROJ, /* Projection (send T co-ordinate). */
1405 ROGUE_BACKEND_OP_MOD_FCNORM, /* Fixed-point texture data (convert to float).
1406 */
1407 ROGUE_BACKEND_OP_MOD_NNCOORDS, /* Non-normalised co-ordinates. */
1408
1409 ROGUE_BACKEND_OP_MOD_BIAS, /* LOD mode: bias. */
1410 ROGUE_BACKEND_OP_MOD_REPLACE, /* LOD mode: replace. */
1411 ROGUE_BACKEND_OP_MOD_GRADIENT, /* LOD mode: gradient. */
1412
1413 ROGUE_BACKEND_OP_MOD_PPLOD, /* Per-pixel LOD. */
1414 ROGUE_BACKEND_OP_MOD_TAO, /* Texture address override. */
1415 ROGUE_BACKEND_OP_MOD_SOO, /* Sample offset supplied. */
1416 ROGUE_BACKEND_OP_MOD_SNO, /* Sample number supplied. */
1417 ROGUE_BACKEND_OP_MOD_WRT, /* SMP write. */
1418
1419 ROGUE_BACKEND_OP_MOD_DATA, /* Sample bypass mode: data. */
1420 ROGUE_BACKEND_OP_MOD_INFO, /* Sample bypass mode: info. */
1421 ROGUE_BACKEND_OP_MOD_BOTH, /* Sample bypass mode: both. */
1422
1423 ROGUE_BACKEND_OP_MOD_TILED, /* Tiled LD/ST. */
1424
1425 ROGUE_BACKEND_OP_MOD_BYPASS, /* MCU cache mode (read): bypass. */
1426 ROGUE_BACKEND_OP_MOD_FORCELINEFILL, /* MCU cache mode (read): force line
1427 * fill.
1428 */
1429
1430 ROGUE_BACKEND_OP_MOD_WRITETHROUGH, /* MCU cache mode (write): write through
1431 * L1 & SLC.
1432 */
1433 ROGUE_BACKEND_OP_MOD_WRITEBACK, /* MCU cache mode (write): write back. */
1434 ROGUE_BACKEND_OP_MOD_LAZYWRITEBACK, /* MCU cache mode (write): lazy write
1435 * back.
1436 */
1437
1438 ROGUE_BACKEND_OP_MOD_SLCBYPASS, /* SLC cache mode: bypass.*/
1439 ROGUE_BACKEND_OP_MOD_SLCWRITEBACK, /* SLC cache mode: write back */
1440 ROGUE_BACKEND_OP_MOD_SLCWRITETHROUGH, /* SLC cache mode: write through. */
1441 ROGUE_BACKEND_OP_MOD_SLCNOALLOC, /* SLC cache mode: cached reads/no
1442 * allocation on miss.
1443 */
1444
1445 ROGUE_BACKEND_OP_MOD_ARRAY, /* Sample data contains array index/texture
1446 * arrays enabled.
1447 */
1448 ROGUE_BACKEND_OP_MOD_INTEGER, /* Integer co-ordinates and sample data. */
1449 ROGUE_BACKEND_OP_MOD_SCHEDSWAP, /* Deschedule slot after instruction. */
1450
1451 ROGUE_BACKEND_OP_MOD_F16, /* Return packed F16 data. */
1452
1453 ROGUE_BACKEND_OP_MOD_SAT, /* Saturate output. */
1454
1455 ROGUE_BACKEND_OP_MOD_FREEP, /* Free partition. */
1456
1457 ROGUE_BACKEND_OP_MOD_COUNT,
1458 };
1459
1460 typedef struct rogue_backend_op_mod_info {
1461 const char *str;
1462 uint64_t exclude; /* Can't use this op mod with any of these. */
1463 uint64_t require; /* Required op mods for this to be used (OR). */
1464 } rogue_backend_op_mod_info;
1465
1466 extern const rogue_backend_op_mod_info
1467 rogue_backend_op_mod_infos[ROGUE_BACKEND_OP_MOD_COUNT];
1468
1469 typedef struct rogue_backend_instr {
1470 rogue_instr instr;
1471
1472 enum rogue_backend_op op;
1473
1474 uint64_t mod;
1475
1476 /* Backend instructions don't have source/dest modifiers. */
1477
1478 rogue_instr_dst dst[ROGUE_BACKEND_OP_MAX_DSTS];
1479 rogue_dst_write dst_write[ROGUE_BACKEND_OP_MAX_DSTS];
1480
1481 rogue_instr_src src[ROGUE_BACKEND_OP_MAX_SRCS];
1482 rogue_src_use src_use[ROGUE_BACKEND_OP_MAX_SRCS];
1483 } rogue_backend_instr;
1484
rogue_set_backend_op_mod(rogue_backend_instr * backend,enum rogue_backend_op_mod mod)1485 static inline void rogue_set_backend_op_mod(rogue_backend_instr *backend,
1486 enum rogue_backend_op_mod mod)
1487 {
1488 backend->mod |= BITFIELD64_BIT(mod);
1489 }
1490
1491 static inline bool
rogue_backend_op_mod_is_set(const rogue_backend_instr * backend,enum rogue_backend_op_mod mod)1492 rogue_backend_op_mod_is_set(const rogue_backend_instr *backend,
1493 enum rogue_backend_op_mod mod)
1494 {
1495 return !!(backend->mod & BITFIELD64_BIT(mod));
1496 }
1497
1498 rogue_backend_instr *rogue_backend_instr_create(rogue_block *block,
1499 enum rogue_backend_op op);
1500
1501 typedef struct rogue_ctrl_instr {
1502 rogue_instr instr;
1503
1504 enum rogue_ctrl_op op;
1505
1506 uint64_t mod;
1507
1508 /* Control instructions don't have source/dest modifiers. */
1509
1510 rogue_instr_dst dst[ROGUE_CTRL_OP_MAX_DSTS];
1511 rogue_dst_write dst_write[ROGUE_CTRL_OP_MAX_DSTS];
1512
1513 rogue_instr_src src[ROGUE_CTRL_OP_MAX_SRCS];
1514 rogue_src_use src_use[ROGUE_CTRL_OP_MAX_SRCS];
1515
1516 rogue_block *target_block;
1517 rogue_block_use block_use;
1518 } rogue_ctrl_instr;
1519
rogue_set_ctrl_op_mod(rogue_ctrl_instr * ctrl,enum rogue_ctrl_op_mod mod)1520 static inline void rogue_set_ctrl_op_mod(rogue_ctrl_instr *ctrl,
1521 enum rogue_ctrl_op_mod mod)
1522 {
1523 ctrl->mod |= BITFIELD64_BIT(mod);
1524 }
1525
rogue_ctrl_op_mod_is_set(const rogue_ctrl_instr * ctrl,enum rogue_ctrl_op_mod mod)1526 static inline bool rogue_ctrl_op_mod_is_set(const rogue_ctrl_instr *ctrl,
1527 enum rogue_ctrl_op_mod mod)
1528 {
1529 return !!(ctrl->mod & BITFIELD64_BIT(mod));
1530 }
1531
1532 /**
1533 * \brief Allocates and initializes a new control instruction.
1534 *
1535 * \param[in] block The block which will contain the instruction.
1536 * \param[in] op The ALU instruction operation.
1537 * \return The new instruction.
1538 */
1539 rogue_ctrl_instr *rogue_ctrl_instr_create(rogue_block *block,
1540 enum rogue_ctrl_op op);
1541
1542 enum rogue_bitwise_op {
1543 ROGUE_BITWISE_OP_INVALID = 0,
1544
1545 /* Real instructions. */
1546 ROGUE_BITWISE_OP_BYP0,
1547
1548 /* Pseudo-instructions. */
1549 ROGUE_BITWISE_OP_PSEUDO,
1550 ROGUE_BITWISE_OP_ = ROGUE_BITWISE_OP_PSEUDO,
1551
1552 ROGUE_BITWISE_OP_COUNT,
1553 };
1554
1555 enum rogue_bitwise_op_mod {
1556 /* In order of priority */
1557 ROGUE_BITWISE_OP_MOD_TWB, /* Top word break. */
1558 ROGUE_BITWISE_OP_MOD_PWB, /* Partial word break. */
1559 ROGUE_BITWISE_OP_MOD_MTB, /* Mask top break. */
1560 ROGUE_BITWISE_OP_MOD_FTB, /* Find top break. */
1561
1562 ROGUE_BITWISE_OP_MOD_COUNT,
1563 };
1564
1565 typedef struct rogue_bitwise_op_mod_info {
1566 const char *str;
1567 uint64_t exclude; /* Can't use this op mod with any of these. */
1568 uint64_t require; /* Required op mods for this to be used (OR). */
1569 } rogue_bitwise_op_mod_info;
1570
1571 extern const rogue_bitwise_op_mod_info
1572 rogue_bitwise_op_mod_infos[ROGUE_BITWISE_OP_MOD_COUNT];
1573
1574 #define ROGUE_BITWISE_OP_MAX_SRCS 7
1575 #define ROGUE_BITWISE_OP_MAX_DSTS 2
1576
1577 typedef struct rogue_bitwise_op_info {
1578 const char *str;
1579
1580 unsigned num_dsts;
1581 unsigned num_srcs;
1582
1583 uint64_t supported_phases;
1584 rogue_alu_io_info phase_io[ROGUE_INSTR_PHASE_COUNT];
1585
1586 uint64_t supported_op_mods;
1587 uint64_t supported_dst_mods[ROGUE_BITWISE_OP_MAX_DSTS];
1588 uint64_t supported_src_mods[ROGUE_BITWISE_OP_MAX_SRCS];
1589
1590 uint64_t supported_dst_types[ROGUE_BITWISE_OP_MAX_DSTS];
1591 uint64_t supported_src_types[ROGUE_BITWISE_OP_MAX_SRCS];
1592
1593 unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1594 unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1595
1596 uint64_t dst_repeat_mask;
1597 uint64_t src_repeat_mask;
1598 } rogue_bitwise_op_info;
1599
1600 extern const rogue_bitwise_op_info
1601 rogue_bitwise_op_infos[ROGUE_BITWISE_OP_COUNT];
1602
1603 typedef struct rogue_bitwise_dst {
1604 rogue_ref ref;
1605 unsigned index;
1606 } rogue_bitwise_dst;
1607
1608 typedef struct rogue_bitwise_src {
1609 rogue_ref ref;
1610 unsigned index;
1611 } rogue_bitwise_src;
1612
1613 typedef struct rogue_bitwise_instr {
1614 rogue_instr instr;
1615
1616 enum rogue_bitwise_op op;
1617
1618 uint64_t mod;
1619
1620 /* TODO NEXT: source/dest modifiers */
1621
1622 rogue_instr_dst dst[ROGUE_BITWISE_OP_MAX_DSTS];
1623 rogue_dst_write dst_write[ROGUE_BITWISE_OP_MAX_DSTS];
1624
1625 rogue_instr_src src[ROGUE_BITWISE_OP_MAX_SRCS];
1626 rogue_src_use src_use[ROGUE_BITWISE_OP_MAX_SRCS];
1627 } rogue_bitwise_instr;
1628
rogue_set_bitwise_op_mod(rogue_bitwise_instr * bitwise,enum rogue_bitwise_op_mod mod)1629 static inline void rogue_set_bitwise_op_mod(rogue_bitwise_instr *bitwise,
1630 enum rogue_bitwise_op_mod mod)
1631 {
1632 bitwise->mod |= BITFIELD64_BIT(mod);
1633 }
1634
1635 static inline bool
rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr * bitwise,enum rogue_bitwise_op_mod mod)1636 rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr *bitwise,
1637 enum rogue_bitwise_op_mod mod)
1638 {
1639 return !!(bitwise->mod & BITFIELD64_BIT(mod));
1640 }
1641
1642 /**
1643 * \brief Allocates and initializes a new bitwise instruction.
1644 *
1645 * \param[in] op The ALU instruction operation.
1646 * \return The new instruction.
1647 */
1648 rogue_bitwise_instr *rogue_bitwise_instr_create(rogue_block *block,
1649 enum rogue_bitwise_op op);
1650
1651 /** Defines a cast function
1652 *
1653 * This macro defines a cast function from in_type to out_type where
1654 * out_type is some structure type that contains a field of type out_type.
1655 *
1656 * Note that you have to be a bit careful as the generated cast function
1657 * destroys constness.
1658 */
1659 #define ROGUE_DEFINE_CAST(name, \
1660 in_type, \
1661 out_type, \
1662 field, \
1663 type_field, \
1664 type_value) \
1665 static inline out_type *name(const in_type *parent) \
1666 { \
1667 assert(parent && parent->type_field == type_value); \
1668 return list_entry(parent, out_type, field); \
1669 }
1670
ROGUE_DEFINE_CAST(rogue_instr_as_alu,rogue_instr,rogue_alu_instr,instr,type,ROGUE_INSTR_TYPE_ALU)1671 ROGUE_DEFINE_CAST(rogue_instr_as_alu,
1672 rogue_instr,
1673 rogue_alu_instr,
1674 instr,
1675 type,
1676 ROGUE_INSTR_TYPE_ALU)
1677 ROGUE_DEFINE_CAST(rogue_instr_as_backend,
1678 rogue_instr,
1679 rogue_backend_instr,
1680 instr,
1681 type,
1682 ROGUE_INSTR_TYPE_BACKEND)
1683 ROGUE_DEFINE_CAST(rogue_instr_as_ctrl,
1684 rogue_instr,
1685 rogue_ctrl_instr,
1686 instr,
1687 type,
1688 ROGUE_INSTR_TYPE_CTRL)
1689 ROGUE_DEFINE_CAST(rogue_instr_as_bitwise,
1690 rogue_instr,
1691 rogue_bitwise_instr,
1692 instr,
1693 type,
1694 ROGUE_INSTR_TYPE_BITWISE)
1695
1696 static inline enum rogue_io rogue_instr_src_io_src(const rogue_instr *instr,
1697 enum rogue_instr_phase phase,
1698 unsigned src_index)
1699 {
1700 switch (instr->type) {
1701 case ROGUE_INSTR_TYPE_ALU: {
1702 const rogue_alu_instr *alu = rogue_instr_as_alu(instr);
1703 const rogue_alu_op_info *info = &rogue_alu_op_infos[alu->op];
1704 return info->phase_io[phase].src[src_index];
1705 }
1706
1707 case ROGUE_INSTR_TYPE_BACKEND: {
1708 const rogue_backend_instr *backend = rogue_instr_as_backend(instr);
1709 const rogue_backend_op_info *info = &rogue_backend_op_infos[backend->op];
1710 return info->phase_io.src[src_index];
1711 }
1712
1713 case ROGUE_INSTR_TYPE_CTRL: {
1714 /* TODO after phase_io is added to relevant control instructions as well.
1715 */
1716 break;
1717 }
1718
1719 default:
1720 unreachable("Unsupported instruction type.");
1721 break;
1722 }
1723
1724 return ROGUE_IO_INVALID;
1725 }
1726
1727 /* Maps sources and destinations ("inputs"/"outputs") to registers. */
1728 typedef struct rogue_instr_group_io_sel {
1729 rogue_ref srcs[ROGUE_ISA_SRCS]; /** Upper + lower sources. */
1730 rogue_ref dsts[ROGUE_ISA_DSTS]; /** Destinations. */
1731 rogue_ref iss[ROGUE_ISA_ISSS]; /** Internal source selector (includes
1732 IS0/MUX). */
1733 } rogue_instr_group_io_sel;
1734
1735 static inline rogue_ref *
rogue_instr_group_io_sel_ref(rogue_instr_group_io_sel * map,enum rogue_io io)1736 rogue_instr_group_io_sel_ref(rogue_instr_group_io_sel *map, enum rogue_io io)
1737 {
1738 if (rogue_io_is_src(io))
1739 return &map->srcs[io - ROGUE_IO_S0];
1740 else if (rogue_io_is_dst(io))
1741 return &map->dsts[io - ROGUE_IO_W0];
1742 else if (rogue_io_is_iss(io))
1743 return &map->iss[io - ROGUE_IO_IS0];
1744 unreachable("Unsupported io.");
1745 }
1746
1747 /** Rogue instruction group. */
1748 typedef struct rogue_instr_group {
1749 rogue_block *block;
1750 struct list_head link; /** Link in rogue_block::instrs. */
1751
1752 rogue_instr *instrs[ROGUE_INSTR_PHASE_COUNT]; /** Instructions in group. */
1753 rogue_instr_group_io_sel io_sel; /** Source, destination, internal source
1754 selector maps. */
1755
1756 struct {
1757 uint64_t phases; /** Instructions phases present. */
1758
1759 enum rogue_exec_cond exec_cond;
1760 enum rogue_alu alu;
1761
1762 bool end; /** Shader end flag. */
1763 unsigned repeat;
1764 } header;
1765
1766 struct {
1767 unsigned header;
1768 unsigned instrs[ROGUE_INSTR_PHASE_COUNT];
1769 unsigned lower_srcs;
1770 unsigned upper_srcs;
1771 unsigned iss;
1772 unsigned dsts;
1773 unsigned word_padding; /* Padding to make total size a word (% 2 == 0) */
1774 unsigned align_padding; /* Padding to align instruction position in memory
1775 */
1776 unsigned total;
1777
1778 unsigned offset;
1779 } size;
1780
1781 struct {
1782 unsigned lower_src_index;
1783 unsigned upper_src_index;
1784 unsigned dst_index;
1785 } encode_info;
1786
1787 unsigned index; /** For debug purposes. */
1788 } rogue_instr_group;
1789
1790 #define rogue_foreach_instr_group_in_block(group, block) \
1791 list_for_each_entry (rogue_instr_group, group, &(block)->instrs, link)
1792
1793 #define rogue_foreach_instr_group_in_block_safe(group, block) \
1794 list_for_each_entry_safe (rogue_instr_group, group, &(block)->instrs, link)
1795
1796 #define rogue_foreach_instr_group_in_shader(group, shader) \
1797 rogue_foreach_block (_block, (shader)) \
1798 rogue_foreach_instr_group_in_block ((group), _block)
1799
1800 #define rogue_foreach_instr_group_in_shader_safe(group, shader) \
1801 rogue_foreach_block_safe (_block, (shader)) \
1802 rogue_foreach_instr_group_in_block_safe ((group), _block)
1803
rogue_instr_group_create(rogue_block * block,enum rogue_alu alu)1804 static inline rogue_instr_group *rogue_instr_group_create(rogue_block *block,
1805 enum rogue_alu alu)
1806 {
1807 rogue_instr_group *group = rzalloc_size(block, sizeof(*group));
1808 group->header.alu = alu;
1809 group->block = block;
1810 return group;
1811 }
1812
1813 typedef struct rogue_build_ctx rogue_build_ctx;
1814
1815 /** Rogue shader object. */
1816 typedef struct rogue_shader {
1817 gl_shader_stage stage; /** Shader stage. */
1818
1819 rogue_build_ctx *ctx; /** Build context. */
1820
1821 unsigned next_instr; /** Next instruction index. */
1822 unsigned next_block; /** Next block index. */
1823
1824 struct list_head blocks; /** List of basic blocks. */
1825 struct list_head regs[ROGUE_REG_CLASS_COUNT]; /** List of registers used by
1826 the shader. */
1827 BITSET_WORD *regs_used[ROGUE_REG_CLASS_COUNT]; /** Bitset of register numbers
1828 used. */
1829 struct util_sparse_array reg_cache[ROGUE_REG_CLASS_COUNT];
1830
1831 struct list_head regarrays; /** List of register arrays used by the shader.
1832 */
1833 struct util_sparse_array regarray_cache;
1834
1835 struct list_head drc_trxns[ROGUE_DRCS]; /** List of drc transactions. */
1836
1837 struct list_head imm_uses; /** List of immediate value uses. */
1838
1839 bool is_grouped; /** Whether the instructions are grouped. */
1840
1841 const char *name; /** Shader name. */
1842 } rogue_shader;
1843
rogue_set_shader_name(rogue_shader * shader,const char * name)1844 static inline void rogue_set_shader_name(rogue_shader *shader, const char *name)
1845 {
1846 shader->name = ralloc_strdup(shader, name);
1847 }
1848
rogue_reg_is_used(const rogue_shader * shader,enum rogue_reg_class class,unsigned index)1849 static inline bool rogue_reg_is_used(const rogue_shader *shader,
1850 enum rogue_reg_class class,
1851 unsigned index)
1852 {
1853 return BITSET_TEST(shader->regs_used[class], index);
1854 }
1855
rogue_set_reg_use(rogue_shader * shader,enum rogue_reg_class class,unsigned index)1856 static inline void rogue_set_reg_use(rogue_shader *shader,
1857 enum rogue_reg_class class,
1858 unsigned index)
1859 {
1860 BITSET_SET(shader->regs_used[class], index);
1861 }
1862
rogue_clear_reg_use(rogue_shader * shader,enum rogue_reg_class class,unsigned index)1863 static inline void rogue_clear_reg_use(rogue_shader *shader,
1864 enum rogue_reg_class class,
1865 unsigned index)
1866 {
1867 BITSET_CLEAR(shader->regs_used[class], index);
1868 }
1869
1870 /**
1871 * \brief Allocates and initializes a new rogue_shader object.
1872 *
1873 * \param[in] mem_ctx The parent memory context.
1874 * \param[in] stage The shader stage.
1875 * \return The new shader.
1876 */
1877 rogue_shader *rogue_shader_create(void *mem_ctx, gl_shader_stage stage);
1878
1879 rogue_reg *rogue_ssa_reg(rogue_shader *shader, unsigned index);
1880
1881 rogue_reg *rogue_temp_reg(rogue_shader *shader, unsigned index);
1882
1883 rogue_reg *rogue_coeff_reg(rogue_shader *shader, unsigned index);
1884
1885 rogue_reg *rogue_shared_reg(rogue_shader *shader, unsigned index);
1886
1887 rogue_reg *rogue_const_reg(rogue_shader *shader, unsigned index);
1888
1889 rogue_reg *rogue_pixout_reg(rogue_shader *shader, unsigned index);
1890
1891 rogue_reg *rogue_special_reg(rogue_shader *shader, unsigned index);
1892
1893 rogue_reg *rogue_vtxin_reg(rogue_shader *shader, unsigned index);
1894
1895 rogue_reg *rogue_vtxout_reg(rogue_shader *shader, unsigned index);
1896
1897 rogue_reg *
1898 rogue_ssa_vec_reg(rogue_shader *shader, unsigned index, unsigned component);
1899
1900 void rogue_reg_delete(rogue_reg *reg);
1901
1902 rogue_regarray *
1903 rogue_ssa_regarray(rogue_shader *shader, unsigned size, unsigned start_index);
1904
1905 rogue_regarray *
1906 rogue_temp_regarray(rogue_shader *shader, unsigned size, unsigned start_index);
1907
1908 rogue_regarray *
1909 rogue_coeff_regarray(rogue_shader *shader, unsigned size, unsigned start_index);
1910
1911 rogue_regarray *rogue_shared_regarray(rogue_shader *shader,
1912 unsigned size,
1913 unsigned start_index);
1914
1915 rogue_regarray *rogue_ssa_vec_regarray(rogue_shader *shader,
1916 unsigned size,
1917 unsigned start_index,
1918 unsigned component);
1919
1920 rogue_regarray *rogue_regarray_cached(rogue_shader *shader,
1921 unsigned size,
1922 enum rogue_reg_class class,
1923 uint32_t start_index);
1924
1925 rogue_regarray *rogue_vec_regarray_cached(rogue_shader *shader,
1926 unsigned size,
1927 enum rogue_reg_class class,
1928 uint32_t start_index,
1929 uint8_t component);
1930
rogue_regarray_is_unused(rogue_regarray * regarray)1931 static inline bool rogue_regarray_is_unused(rogue_regarray *regarray)
1932 {
1933 return list_is_empty(®array->uses) && list_is_empty(®array->writes);
1934 }
1935
rogue_regarray_delete(rogue_regarray * regarray)1936 static void rogue_regarray_delete(rogue_regarray *regarray)
1937 {
1938 assert(rogue_regarray_is_unused(regarray));
1939
1940 if (!regarray->parent) {
1941 for (unsigned u = 0; u < regarray->size; ++u)
1942 rogue_reg_delete(regarray->regs[u]);
1943 }
1944
1945 if (regarray->cached && *regarray->cached == regarray)
1946 *regarray->cached = NULL;
1947
1948 list_del(®array->link);
1949 if (regarray->parent)
1950 list_del(®array->child_link);
1951 ralloc_free(regarray);
1952 }
1953
rogue_reset_reg_usage(rogue_shader * shader,enum rogue_reg_class class)1954 static inline void rogue_reset_reg_usage(rogue_shader *shader,
1955 enum rogue_reg_class class)
1956 {
1957 const rogue_reg_info *info = &rogue_reg_infos[class];
1958
1959 if (info->num) {
1960 memset(shader->regs_used[class],
1961 0,
1962 sizeof(*shader->regs_used[class]) * BITSET_WORDS(info->num));
1963 }
1964
1965 rogue_foreach_reg (reg, shader, class) {
1966 reg->dirty = false;
1967 }
1968 }
1969
1970 bool rogue_reg_set(rogue_shader *shader,
1971 rogue_reg *reg,
1972 enum rogue_reg_class class,
1973 unsigned index);
1974
1975 bool rogue_reg_rewrite(rogue_shader *shader,
1976 rogue_reg *reg,
1977 enum rogue_reg_class class,
1978 unsigned index);
1979
1980 bool rogue_regarray_set(rogue_shader *shader,
1981 rogue_regarray *regarray,
1982 enum rogue_reg_class class,
1983 unsigned base_index,
1984 bool set_regs);
1985
1986 bool rogue_regarray_rewrite(rogue_shader *shader,
1987 rogue_regarray *regarray,
1988 enum rogue_reg_class class,
1989 unsigned base_index);
1990
1991 /** Cursor for Rogue instructions/groups and basic blocks. */
1992 typedef struct rogue_cursor {
1993 bool block;
1994 struct list_head *prev; /** Linked-list pointer to before the object. */
1995 bool first; /** Whether the cursor is pointing to the first element. */
1996 } rogue_cursor;
1997
1998 /**
1999 * \brief Returns a cursor set to the beginning of the shader.
2000 *
2001 * \param[in] shader The shader.
2002 * \return The cursor.
2003 */
rogue_cursor_before_shader(rogue_shader * shader)2004 static inline rogue_cursor rogue_cursor_before_shader(rogue_shader *shader)
2005 {
2006 return (rogue_cursor){
2007 .block = true,
2008 .prev = &shader->blocks,
2009 .first = true,
2010 };
2011 }
2012
2013 /**
2014 * \brief Returns a cursor set to before a block.
2015 *
2016 * \param[in] block The block.
2017 * \return The cursor.
2018 */
rogue_cursor_before_block(rogue_block * block)2019 static inline rogue_cursor rogue_cursor_before_block(rogue_block *block)
2020 {
2021 return (rogue_cursor){
2022 .block = true,
2023 .prev = block->link.prev,
2024 .first = (block->link.prev == &block->shader->blocks),
2025 };
2026 }
2027
2028 /**
2029 * \brief Returns a cursor set to after a block.
2030 *
2031 * \param[in] block The block.
2032 * \return The cursor.
2033 */
rogue_cursor_after_block(rogue_block * block)2034 static inline rogue_cursor rogue_cursor_after_block(rogue_block *block)
2035 {
2036 return (rogue_cursor){
2037 .block = true,
2038 .prev = &block->link,
2039 };
2040 }
2041
2042 /**
2043 * \brief Returns a cursor set to before an instruction.
2044 *
2045 * \param[in] instr The instruction.
2046 * \return The cursor.
2047 */
rogue_cursor_before_instr(rogue_instr * instr)2048 static inline rogue_cursor rogue_cursor_before_instr(rogue_instr *instr)
2049 {
2050 return (rogue_cursor){
2051 .block = false,
2052 .prev = instr->link.prev,
2053 .first = (instr->link.prev == &instr->block->instrs),
2054 };
2055 }
2056
2057 /**
2058 * \brief Returns a cursor set to after an instruction.
2059 *
2060 * \param[in] instr The instruction.
2061 * \return The cursor.
2062 */
rogue_cursor_after_instr(rogue_instr * instr)2063 static inline rogue_cursor rogue_cursor_after_instr(rogue_instr *instr)
2064 {
2065 return (rogue_cursor){
2066 .block = false,
2067 .prev = &instr->link,
2068 };
2069 }
2070
2071 /**
2072 * \brief Allocates and initializes a new rogue_block object.
2073 *
2074 * \param[in] shader The shader which will contain the block.
2075 * \param[in] label The (optional) block label.
2076 * \return The new block.
2077 */
2078 rogue_block *rogue_block_create(rogue_shader *shader, const char *label);
2079
2080 /**
2081 * \brief Returns the block currently being pointed to by the cursor.
2082 *
2083 * If the cursor is currently pointing to a block, this function will
2084 * directly return said block. If it is pointing to an instruction, it
2085 * will return the block that said instruction is a part of.
2086 *
2087 * \param[in] cursor A cursor.
2088 * \return The the block being pointed to.
2089 */
rogue_cursor_block(rogue_cursor cursor)2090 static inline rogue_block *rogue_cursor_block(rogue_cursor cursor)
2091 {
2092 rogue_block *block = NULL;
2093
2094 if (cursor.block) {
2095 assert(!cursor.first && "Cursor is not pointing at a block.");
2096 block = list_entry(cursor.prev, rogue_block, link);
2097 } else {
2098 block = cursor.first ? list_entry(cursor.prev, rogue_block, instrs)
2099 : list_entry(cursor.prev, rogue_instr, link)->block;
2100 }
2101
2102 return block;
2103 }
2104
2105 /**
2106 * \brief Inserts a basic block at the specified cursor position.
2107 *
2108 * \param[in] block The basic block to insert.
2109 * \param[in] cursor The cursor.
2110 */
rogue_block_insert(rogue_block * block,rogue_cursor cursor)2111 static inline void rogue_block_insert(rogue_block *block, rogue_cursor cursor)
2112 {
2113 struct list_head *list = cursor.prev;
2114
2115 /* If the cursor is pointing at an instruction, the block
2116 * is always going to be inserted *after* the block
2117 * that the instruction is in.
2118 */
2119 if (!cursor.block)
2120 list = &rogue_cursor_block(cursor)->link;
2121
2122 list_add(&block->link, list);
2123 }
2124
2125 void rogue_link_instr_write(rogue_instr *instr);
2126
2127 void rogue_link_instr_use(rogue_instr *instr);
2128
2129 void rogue_unlink_instr_write(rogue_instr *instr);
2130
2131 void rogue_unlink_instr_use(rogue_instr *instr);
2132
2133 /**
2134 * \brief Inserts an instruction at the specified cursor position.
2135 *
2136 * \param[in] instr The instruction to insert.
2137 * \param[in] cursor The cursor.
2138 */
rogue_instr_insert(rogue_instr * instr,rogue_cursor cursor)2139 static inline void rogue_instr_insert(rogue_instr *instr, rogue_cursor cursor)
2140 {
2141 struct list_head *list = cursor.prev;
2142
2143 /* If the cursor is pointing at block, the instruction
2144 * is always going to be inserted at the end of any other
2145 * instructions in the block.
2146 */
2147 if (cursor.block)
2148 list = rogue_cursor_block(cursor)->instrs.prev;
2149
2150 list_add(&instr->link, list);
2151
2152 rogue_link_instr_write(instr);
2153 rogue_link_instr_use(instr);
2154 }
2155
rogue_instr_delete(rogue_instr * instr)2156 static inline void rogue_instr_delete(rogue_instr *instr)
2157 {
2158 rogue_unlink_instr_use(instr);
2159 rogue_unlink_instr_write(instr);
2160
2161 list_del(&instr->link);
2162
2163 ralloc_free(instr);
2164 }
2165
2166 static inline void
rogue_link_drc_trxn(rogue_shader * shader,rogue_instr * instr,rogue_drc * drc)2167 rogue_link_drc_trxn(rogue_shader *shader, rogue_instr *instr, rogue_drc *drc)
2168 {
2169 unsigned index = drc->index;
2170 assert(index < ROGUE_DRCS);
2171
2172 drc->trxn.acquire = instr;
2173 list_addtail(&drc->trxn.link, &shader->drc_trxns[index]);
2174 }
2175
2176 static inline void
rogue_unlink_drc_trxn(rogue_shader * shader,rogue_instr * instr,rogue_drc * drc)2177 rogue_unlink_drc_trxn(rogue_shader *shader, rogue_instr *instr, rogue_drc *drc)
2178 {
2179 ASSERTED unsigned index = drc->index;
2180 assert(index < ROGUE_DRCS);
2181 assert(drc->trxn.acquire == instr);
2182
2183 if (drc->trxn.release)
2184 rogue_instr_delete(drc->trxn.release);
2185
2186 list_del(&drc->trxn.link);
2187 }
2188
rogue_link_imm_use(rogue_shader * shader,rogue_instr * instr,unsigned src_index,rogue_imm * imm)2189 static inline void rogue_link_imm_use(rogue_shader *shader,
2190 rogue_instr *instr,
2191 unsigned src_index,
2192 rogue_imm *imm)
2193 {
2194 rogue_imm_use *imm_use = &imm->use;
2195
2196 imm_use->instr = instr;
2197 imm_use->src_index = src_index;
2198 imm_use->imm = &imm->imm;
2199
2200 list_addtail(&imm_use->link, &shader->imm_uses);
2201 }
2202
rogue_unlink_imm_use(rogue_instr * instr,rogue_imm_use * imm_use)2203 static inline void rogue_unlink_imm_use(rogue_instr *instr,
2204 rogue_imm_use *imm_use)
2205 {
2206 assert(imm_use->instr == instr);
2207 list_del(&imm_use->link);
2208 }
2209
rogue_link_instr_write_reg(rogue_instr * instr,rogue_reg_write * write,rogue_reg * reg,unsigned dst_index)2210 static inline void rogue_link_instr_write_reg(rogue_instr *instr,
2211 rogue_reg_write *write,
2212 rogue_reg *reg,
2213 unsigned dst_index)
2214 {
2215 write->instr = instr;
2216 write->dst_index = dst_index;
2217 list_addtail(&write->link, ®->writes);
2218 }
2219
rogue_unlink_instr_write_reg(rogue_instr * instr,rogue_reg_write * write)2220 static inline void rogue_unlink_instr_write_reg(rogue_instr *instr,
2221 rogue_reg_write *write)
2222 {
2223 assert(write->instr == instr);
2224 write->instr = NULL;
2225 list_del(&write->link);
2226 }
2227
rogue_link_instr_write_regarray(rogue_instr * instr,rogue_regarray_write * write,rogue_regarray * regarray,unsigned dst_index)2228 static inline void rogue_link_instr_write_regarray(rogue_instr *instr,
2229 rogue_regarray_write *write,
2230 rogue_regarray *regarray,
2231 unsigned dst_index)
2232 {
2233 write->instr = instr;
2234 write->dst_index = dst_index;
2235 list_addtail(&write->link, ®array->writes);
2236 }
2237
2238 static inline void
rogue_unlink_instr_write_regarray(rogue_instr * instr,rogue_regarray_write * write)2239 rogue_unlink_instr_write_regarray(rogue_instr *instr,
2240 rogue_regarray_write *write)
2241 {
2242 assert(write->instr == instr);
2243 write->instr = NULL;
2244 list_del(&write->link);
2245 }
2246
rogue_link_instr_use_reg(rogue_instr * instr,rogue_reg_use * use,rogue_reg * reg,unsigned src_index)2247 static inline void rogue_link_instr_use_reg(rogue_instr *instr,
2248 rogue_reg_use *use,
2249 rogue_reg *reg,
2250 unsigned src_index)
2251 {
2252 use->instr = instr;
2253 use->src_index = src_index;
2254 list_addtail(&use->link, ®->uses);
2255 }
2256
rogue_unlink_instr_use_reg(rogue_instr * instr,rogue_reg_use * use)2257 static inline void rogue_unlink_instr_use_reg(rogue_instr *instr,
2258 rogue_reg_use *use)
2259 {
2260 assert(use->instr == instr);
2261 use->instr = NULL;
2262 list_del(&use->link);
2263 }
2264
rogue_link_instr_use_regarray(rogue_instr * instr,rogue_regarray_use * use,rogue_regarray * regarray,unsigned src_index)2265 static inline void rogue_link_instr_use_regarray(rogue_instr *instr,
2266 rogue_regarray_use *use,
2267 rogue_regarray *regarray,
2268 unsigned src_index)
2269 {
2270 use->instr = instr;
2271 use->src_index = src_index;
2272 list_addtail(&use->link, ®array->uses);
2273 }
2274
rogue_unlink_instr_use_regarray(rogue_instr * instr,rogue_regarray_use * use)2275 static inline void rogue_unlink_instr_use_regarray(rogue_instr *instr,
2276 rogue_regarray_use *use)
2277 {
2278 assert(use->instr == instr);
2279 use->instr = NULL;
2280 list_del(&use->link);
2281 }
2282
rogue_link_instr_use_block(rogue_instr * instr,rogue_block_use * block_use,rogue_block * target_block)2283 static inline void rogue_link_instr_use_block(rogue_instr *instr,
2284 rogue_block_use *block_use,
2285 rogue_block *target_block)
2286 {
2287 assert(!block_use->instr);
2288 block_use->instr = instr;
2289 list_addtail(&block_use->link, &target_block->uses);
2290 }
2291
rogue_unlink_instr_use_block(rogue_instr * instr,rogue_block_use * block_use)2292 static inline void rogue_unlink_instr_use_block(rogue_instr *instr,
2293 rogue_block_use *block_use)
2294 {
2295 assert(block_use->instr == instr);
2296 list_del(&block_use->link);
2297 }
2298
rogue_dst_reg_replace(rogue_reg_write * write,rogue_reg * new_reg)2299 static inline bool rogue_dst_reg_replace(rogue_reg_write *write,
2300 rogue_reg *new_reg)
2301 {
2302 unsigned dst_index = write->dst_index;
2303 rogue_instr *instr = write->instr;
2304 rogue_ref *ref;
2305
2306 switch (instr->type) {
2307 case ROGUE_INSTR_TYPE_ALU:
2308 ref = &rogue_instr_as_alu(instr)->dst[dst_index].ref;
2309 break;
2310
2311 case ROGUE_INSTR_TYPE_BACKEND:
2312 ref = &rogue_instr_as_backend(instr)->dst[dst_index].ref;
2313 break;
2314
2315 case ROGUE_INSTR_TYPE_CTRL:
2316 ref = &rogue_instr_as_ctrl(instr)->dst[dst_index].ref;
2317 break;
2318
2319 case ROGUE_INSTR_TYPE_BITWISE:
2320 ref = &rogue_instr_as_bitwise(instr)->dst[dst_index].ref;
2321 break;
2322
2323 default:
2324 unreachable("Unsupported instruction type.");
2325 return false;
2326 }
2327
2328 /* We don't want to be modifying regarrays. */
2329 assert(rogue_ref_is_reg(ref));
2330
2331 if (ref->reg == new_reg)
2332 return false;
2333
2334 rogue_unlink_instr_write_reg(instr, write);
2335 *ref = rogue_ref_reg(new_reg);
2336 rogue_link_instr_write_reg(instr, write, new_reg, dst_index);
2337
2338 return true;
2339 }
2340
rogue_src_reg_replace(rogue_reg_use * use,rogue_reg * new_reg)2341 static inline bool rogue_src_reg_replace(rogue_reg_use *use, rogue_reg *new_reg)
2342 {
2343 unsigned src_index = use->src_index;
2344 rogue_instr *instr = use->instr;
2345 rogue_ref *ref;
2346
2347 switch (instr->type) {
2348 case ROGUE_INSTR_TYPE_ALU:
2349 ref = &rogue_instr_as_alu(instr)->src[src_index].ref;
2350 break;
2351
2352 case ROGUE_INSTR_TYPE_BACKEND:
2353 ref = &rogue_instr_as_backend(instr)->src[src_index].ref;
2354 break;
2355
2356 case ROGUE_INSTR_TYPE_CTRL:
2357 ref = &rogue_instr_as_ctrl(instr)->src[src_index].ref;
2358 break;
2359
2360 default:
2361 unreachable("Unsupported instruction type.");
2362 return false;
2363 }
2364
2365 /* We don't want to be modifying regarrays. */
2366 assert(rogue_ref_is_reg(ref));
2367
2368 if (ref->reg == new_reg)
2369 return false;
2370
2371 rogue_unlink_instr_use_reg(instr, use);
2372 *ref = rogue_ref_reg(new_reg);
2373 rogue_link_instr_use_reg(instr, use, new_reg, src_index);
2374
2375 return true;
2376 }
2377
rogue_reg_replace(rogue_reg * old_reg,rogue_reg * new_reg)2378 static inline bool rogue_reg_replace(rogue_reg *old_reg, rogue_reg *new_reg)
2379 {
2380 bool replaced = true;
2381
2382 rogue_foreach_reg_write_safe (write, old_reg) {
2383 replaced &= rogue_dst_reg_replace(write, new_reg);
2384 }
2385
2386 rogue_foreach_reg_use_safe (use, old_reg) {
2387 replaced &= rogue_src_reg_replace(use, new_reg);
2388 }
2389
2390 if (replaced)
2391 rogue_reg_delete(old_reg);
2392
2393 return replaced;
2394 }
2395
2396 /* TODO: try and commonise this with the reg one! */
rogue_dst_regarray_replace(rogue_regarray_write * write,rogue_regarray * new_regarray)2397 static inline bool rogue_dst_regarray_replace(rogue_regarray_write *write,
2398 rogue_regarray *new_regarray)
2399 {
2400 unsigned dst_index = write->dst_index;
2401 rogue_instr *instr = write->instr;
2402 rogue_ref *ref;
2403
2404 switch (instr->type) {
2405 case ROGUE_INSTR_TYPE_ALU:
2406 ref = &rogue_instr_as_alu(instr)->dst[dst_index].ref;
2407 break;
2408
2409 case ROGUE_INSTR_TYPE_BACKEND:
2410 ref = &rogue_instr_as_backend(instr)->dst[dst_index].ref;
2411 break;
2412
2413 case ROGUE_INSTR_TYPE_CTRL:
2414 ref = &rogue_instr_as_ctrl(instr)->dst[dst_index].ref;
2415 break;
2416
2417 case ROGUE_INSTR_TYPE_BITWISE:
2418 ref = &rogue_instr_as_bitwise(instr)->dst[dst_index].ref;
2419 break;
2420
2421 default:
2422 unreachable("Unsupported instruction type.");
2423 return false;
2424 }
2425
2426 /* We don't want to be modifying regs. */
2427 assert(rogue_ref_is_regarray(ref));
2428
2429 if (ref->regarray == new_regarray)
2430 return false;
2431
2432 rogue_unlink_instr_write_regarray(instr, write);
2433 *ref = rogue_ref_regarray(new_regarray);
2434 rogue_link_instr_write_regarray(instr, write, new_regarray, dst_index);
2435
2436 return true;
2437 }
2438
rogue_src_regarray_replace(rogue_regarray_use * use,rogue_regarray * new_regarray)2439 static inline bool rogue_src_regarray_replace(rogue_regarray_use *use,
2440 rogue_regarray *new_regarray)
2441 {
2442 unsigned src_index = use->src_index;
2443 rogue_instr *instr = use->instr;
2444 rogue_ref *ref;
2445
2446 switch (instr->type) {
2447 case ROGUE_INSTR_TYPE_ALU:
2448 ref = &rogue_instr_as_alu(instr)->src[src_index].ref;
2449 break;
2450
2451 case ROGUE_INSTR_TYPE_BACKEND:
2452 ref = &rogue_instr_as_backend(instr)->src[src_index].ref;
2453 break;
2454
2455 case ROGUE_INSTR_TYPE_CTRL:
2456 ref = &rogue_instr_as_ctrl(instr)->src[src_index].ref;
2457 break;
2458
2459 default:
2460 unreachable("Unsupported instruction type.");
2461 return false;
2462 }
2463
2464 /* We don't want to be modifying reg. */
2465 assert(rogue_ref_is_regarray(ref));
2466
2467 if (ref->regarray == new_regarray)
2468 return false;
2469
2470 rogue_unlink_instr_use_regarray(instr, use);
2471 *ref = rogue_ref_regarray(new_regarray);
2472 rogue_link_instr_use_regarray(instr, use, new_regarray, src_index);
2473
2474 return true;
2475 }
2476
rogue_regarray_replace(rogue_shader * shader,rogue_regarray * old_regarray,rogue_regarray * new_regarray)2477 static inline bool rogue_regarray_replace(rogue_shader *shader,
2478 rogue_regarray *old_regarray,
2479 rogue_regarray *new_regarray)
2480 {
2481 bool replaced = true;
2482
2483 assert(!old_regarray->parent);
2484 assert(!new_regarray->parent);
2485
2486 rogue_foreach_regarray_write_safe (write, old_regarray) {
2487 replaced &= rogue_dst_regarray_replace(write, new_regarray);
2488 }
2489
2490 rogue_foreach_regarray_use_safe (use, old_regarray) {
2491 replaced &= rogue_src_regarray_replace(use, new_regarray);
2492 }
2493
2494 enum rogue_reg_class new_class = new_regarray->regs[0]->class;
2495 unsigned new_base_index = new_regarray->regs[0]->index;
2496
2497 /* Replace subarrays. */
2498 rogue_foreach_subarray_safe (old_subarray, old_regarray) {
2499 unsigned idx_offset =
2500 old_subarray->regs[0]->index - old_regarray->regs[0]->index;
2501 rogue_regarray *new_subarray =
2502 rogue_regarray_cached(shader,
2503 old_subarray->size,
2504 new_class,
2505 new_base_index + idx_offset);
2506
2507 rogue_foreach_regarray_write_safe (write, old_subarray) {
2508 replaced &= rogue_dst_regarray_replace(write, new_subarray);
2509 }
2510
2511 rogue_foreach_regarray_use_safe (use, old_subarray) {
2512 replaced &= rogue_src_regarray_replace(use, new_subarray);
2513 }
2514
2515 rogue_regarray_delete(old_subarray);
2516 }
2517
2518 rogue_regarray_delete(old_regarray);
2519
2520 return replaced;
2521 }
2522
rogue_src_imm_replace(rogue_imm_use * imm_use,rogue_reg * new_reg)2523 static inline bool rogue_src_imm_replace(rogue_imm_use *imm_use,
2524 rogue_reg *new_reg)
2525 {
2526 unsigned src_index = imm_use->src_index;
2527 rogue_instr *instr = imm_use->instr;
2528 rogue_ref *ref;
2529 rogue_reg_use *reg_use;
2530
2531 switch (instr->type) {
2532 case ROGUE_INSTR_TYPE_ALU:
2533 ref = &rogue_instr_as_alu(instr)->src[src_index].ref;
2534 reg_use = &rogue_instr_as_alu(instr)->src_use[src_index].reg;
2535 break;
2536
2537 case ROGUE_INSTR_TYPE_BACKEND:
2538 ref = &rogue_instr_as_backend(instr)->src[src_index].ref;
2539 reg_use = &rogue_instr_as_backend(instr)->src_use[src_index].reg;
2540 break;
2541
2542 case ROGUE_INSTR_TYPE_CTRL:
2543 ref = &rogue_instr_as_ctrl(instr)->src[src_index].ref;
2544 reg_use = &rogue_instr_as_ctrl(instr)->src_use[src_index].reg;
2545 break;
2546
2547 default:
2548 unreachable("Unsupported instruction type.");
2549 return false;
2550 }
2551
2552 assert(rogue_ref_is_imm(ref));
2553
2554 rogue_unlink_imm_use(instr, imm_use);
2555 *ref = rogue_ref_reg(new_reg);
2556 rogue_link_instr_use_reg(instr, reg_use, new_reg, src_index);
2557
2558 return true;
2559 }
2560
rogue_instr_is_nop_end(const rogue_instr * instr)2561 static inline bool rogue_instr_is_nop_end(const rogue_instr *instr)
2562 {
2563 if (instr->type != ROGUE_INSTR_TYPE_CTRL)
2564 return false;
2565
2566 const rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
2567
2568 if (ctrl->op != ROGUE_CTRL_OP_NOP)
2569 return false;
2570
2571 return rogue_ctrl_op_mod_is_set(ctrl, ROGUE_CTRL_OP_MOD_END);
2572 }
2573
rogue_instr_supported_phases(const rogue_instr * instr)2574 static inline unsigned rogue_instr_supported_phases(const rogue_instr *instr)
2575 {
2576 uint64_t supported_phases = 0;
2577
2578 switch (instr->type) {
2579 case ROGUE_INSTR_TYPE_ALU: {
2580 rogue_alu_instr *alu = rogue_instr_as_alu(instr);
2581 if (alu->op >= ROGUE_ALU_OP_PSEUDO)
2582 return 0;
2583
2584 const rogue_alu_op_info *info = &rogue_alu_op_infos[alu->op];
2585 supported_phases = info->supported_phases;
2586 break;
2587 }
2588
2589 case ROGUE_INSTR_TYPE_BACKEND: {
2590 rogue_backend_instr *backend = rogue_instr_as_backend(instr);
2591 if (backend->op >= ROGUE_BACKEND_OP_PSEUDO)
2592 return 0;
2593
2594 supported_phases = BITFIELD_BIT(ROGUE_INSTR_PHASE_BACKEND);
2595 break;
2596 }
2597
2598 case ROGUE_INSTR_TYPE_CTRL: {
2599 /* Control instructions can't be co-issued; just make sure this isn't a
2600 * pseudo-instruction. */
2601 rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
2602 if (ctrl->op >= ROGUE_CTRL_OP_PSEUDO)
2603 return 0;
2604
2605 supported_phases = BITFIELD_BIT(ROGUE_INSTR_PHASE_CTRL);
2606 break;
2607 }
2608
2609 case ROGUE_INSTR_TYPE_BITWISE: {
2610 rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr);
2611 if (bitwise->op >= ROGUE_BITWISE_OP_PSEUDO)
2612 return 0;
2613
2614 const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op];
2615 supported_phases = info->supported_phases;
2616 break;
2617 }
2618
2619 default:
2620 unreachable("Unsupported instruction type.");
2621 }
2622
2623 return supported_phases;
2624 }
2625
2626 /* Loop through and find first unused phase that's supported, then return its
2627 * enum. */
2628 static inline enum rogue_instr_phase
rogue_get_supported_phase(uint64_t supported_phases,uint64_t occupied_phases)2629 rogue_get_supported_phase(uint64_t supported_phases, uint64_t occupied_phases)
2630 {
2631 rogue_foreach_phase_in_set (p, supported_phases) {
2632 if (!(BITFIELD_BIT(p) & occupied_phases))
2633 return p;
2634 }
2635
2636 return ROGUE_INSTR_PHASE_INVALID;
2637 }
2638
rogue_phase_occupied(enum rogue_instr_phase phase,uint64_t occupied_phases)2639 static inline bool rogue_phase_occupied(enum rogue_instr_phase phase,
2640 uint64_t occupied_phases)
2641 {
2642 return !!(BITFIELD_BIT(phase) & occupied_phases);
2643 }
2644
rogue_can_replace_reg_use(rogue_reg_use * use,const rogue_reg * new_reg)2645 static inline bool rogue_can_replace_reg_use(rogue_reg_use *use,
2646 const rogue_reg *new_reg)
2647 {
2648 bool can_replace = false;
2649 const rogue_reg_info *reg_info = &rogue_reg_infos[new_reg->class];
2650 const rogue_instr *instr = use->instr;
2651
2652 rogue_foreach_phase_in_set (p, rogue_instr_supported_phases(instr)) {
2653 enum rogue_io io_src = rogue_instr_src_io_src(instr, p, use->src_index);
2654 can_replace &= rogue_io_supported(io_src, reg_info->supported_io_srcs);
2655 }
2656
2657 return can_replace;
2658 }
2659
2660 #define ROGUE_NO_CONST_REG ~0
2661
2662 unsigned rogue_constreg_lookup(rogue_imm_t imm);
2663
2664 /* Printing */
2665
2666 void rogue_print_color(bool print_color);
2667
2668 /**
2669 * \brief Prints a shader's Rogue IR/assembly.
2670 *
2671 * \param[in] fp The file pointer to use for printing.
2672 * \param[in] shader The shader to print.
2673 */
2674 void rogue_print_shader(FILE *fp, const rogue_shader *shader);
2675
2676 /**
2677 * \brief Prints an instruction.
2678 *
2679 * \param[in] fp The file pointer to use for printing.
2680 * \param[in] instr The instruction to print.
2681 */
2682 void rogue_print_instr(FILE *fp, const rogue_instr *instr);
2683
2684 void rogue_print_reg_writes(FILE *fp, const rogue_shader *shader);
2685
2686 void rogue_print_reg_uses(FILE *fp, const rogue_shader *shader);
2687
2688 void rogue_print_block_uses(FILE *fp, const rogue_shader *shader);
2689
2690 void rogue_print_drc_trxns(FILE *fp, const rogue_shader *shader);
2691
2692 /* Validation */
2693 bool rogue_validate_shader(rogue_shader *shader, const char *when);
2694
2695 /* Debug. */
2696 enum rogue_debug {
2697 ROGUE_DEBUG_NIR = BITFIELD_BIT(0),
2698 ROGUE_DEBUG_NIR_PASSES = BITFIELD_BIT(1),
2699 ROGUE_DEBUG_IR = BITFIELD_BIT(2),
2700 ROGUE_DEBUG_IR_PASSES = BITFIELD_BIT(3),
2701 ROGUE_DEBUG_IR_DETAILS = BITFIELD_BIT(4),
2702 ROGUE_DEBUG_VLD_SKIP = BITFIELD_BIT(5),
2703 ROGUE_DEBUG_VLD_NONFATAL = BITFIELD_BIT(6),
2704 };
2705
2706 extern unsigned long rogue_debug;
2707
2708 #define ROGUE_DEBUG(flag) unlikely(!!(rogue_debug & (ROGUE_DEBUG_##flag)))
2709
2710 extern bool rogue_color;
2711
2712 void rogue_debug_init(void);
2713
2714 static inline void
rogue_print_pass_debug(rogue_shader * shader,const char * pass,FILE * fp)2715 rogue_print_pass_debug(rogue_shader *shader, const char *pass, FILE *fp)
2716 {
2717 fprintf(fp, "%s\n", pass);
2718 rogue_print_shader(fp, shader);
2719 if (ROGUE_DEBUG(IR_DETAILS)) {
2720 rogue_print_reg_writes(fp, shader);
2721 rogue_print_reg_uses(fp, shader);
2722 rogue_print_block_uses(fp, shader);
2723 rogue_print_drc_trxns(fp, shader);
2724 }
2725 }
2726
2727 /* Passes */
2728 #define ROGUE_PASS(progress, shader, pass, ...) \
2729 do { \
2730 if (pass((shader), ##__VA_ARGS__)) { \
2731 if (ROGUE_DEBUG(IR_PASSES)) \
2732 rogue_print_pass_debug(shader, #pass, stdout); \
2733 rogue_validate_shader(shader, #pass); \
2734 progress = true; \
2735 } \
2736 } while (0)
2737
2738 #define ROGUE_PASS_V(shader, pass, ...) \
2739 do { \
2740 if (pass((shader), ##__VA_ARGS__)) { \
2741 if (ROGUE_DEBUG(IR_PASSES)) \
2742 rogue_print_pass_debug(shader, #pass, stdout); \
2743 rogue_validate_shader(shader, #pass); \
2744 } \
2745 } while (0)
2746
2747 bool rogue_constreg(rogue_shader *shader);
2748
2749 bool rogue_copy_prop(rogue_shader *shader);
2750
2751 bool rogue_dce(rogue_shader *shader);
2752
2753 bool rogue_lower_late_ops(rogue_shader *shader);
2754
2755 bool rogue_lower_pseudo_ops(rogue_shader *shader);
2756
2757 bool rogue_regalloc(rogue_shader *shader);
2758
2759 bool rogue_schedule_instr_groups(rogue_shader *shader, bool multi_instr_groups);
2760
2761 bool rogue_schedule_uvsw(rogue_shader *shader, bool latency_hiding);
2762
2763 bool rogue_schedule_wdf(rogue_shader *shader, bool latency_hiding);
2764
2765 bool rogue_trim(rogue_shader *shader);
2766
2767 void rogue_shader_passes(rogue_shader *shader);
2768
2769 struct pvr_device_info;
2770
2771 /**
2772 * \brief Compiler context.
2773 */
2774 typedef struct rogue_compiler {
2775 const struct pvr_device_info *dev_info;
2776 } rogue_compiler;
2777
2778 rogue_compiler *rogue_compiler_create(const struct pvr_device_info *dev_info);
2779
2780 /* Max number of I/O varying variables.
2781 * Fragment shader: MAX_VARYING + 1 (W coefficient).
2782 * Vertex shader: MAX_VARYING + 1 (position slot).
2783 */
2784 #define ROGUE_MAX_IO_VARYING_VARS (MAX_VARYING + 1)
2785
2786 /* VERT_ATTRIB_GENERIC0-15 */
2787 #define ROGUE_MAX_IO_ATTRIB_VARS 16
2788
2789 /* Max buffers entries that can be used. */
2790 /* TODO: Currently UBOs are the only supported buffers. */
2791 #define ROGUE_MAX_BUFFERS 24
2792
2793 /**
2794 * \brief UBO data.
2795 */
2796 typedef struct rogue_ubo_data {
2797 unsigned num_ubo_entries;
2798 unsigned desc_set[ROGUE_MAX_BUFFERS];
2799 unsigned binding[ROGUE_MAX_BUFFERS];
2800 unsigned dest[ROGUE_MAX_BUFFERS];
2801 unsigned size[ROGUE_MAX_BUFFERS];
2802 } rogue_ubo_data;
2803
2804 /**
2805 * \brief Compile time constants that need uploading.
2806 */
2807 typedef struct rogue_compile_time_consts_data {
2808 /* TODO: Output these from the compiler. */
2809 /* TODO: Add the other types. */
2810 struct {
2811 unsigned num;
2812 unsigned dest;
2813 /* TODO: This should probably be bigger. Big enough to account for all
2814 * available writable special constant regs.
2815 */
2816 uint32_t value[ROGUE_MAX_BUFFERS];
2817 } static_consts;
2818 } rogue_compile_time_consts_data;
2819
2820 /**
2821 * \brief Per-stage common build data.
2822 */
2823 typedef struct rogue_common_build_data {
2824 unsigned temps;
2825 unsigned internals;
2826 unsigned coeffs;
2827 unsigned shareds;
2828
2829 rogue_ubo_data ubo_data;
2830 rogue_compile_time_consts_data compile_time_consts_data;
2831 } rogue_common_build_data;
2832
2833 /**
2834 * \brief Arguments for the FPU iterator(s)
2835 * (produces varyings for the fragment shader).
2836 */
2837 typedef struct rogue_iterator_args {
2838 uint32_t num_fpu_iterators;
2839 uint32_t fpu_iterators[ROGUE_MAX_IO_VARYING_VARS];
2840 uint32_t destination[ROGUE_MAX_IO_VARYING_VARS];
2841 unsigned base[ROGUE_MAX_IO_VARYING_VARS];
2842 unsigned components[ROGUE_MAX_IO_VARYING_VARS];
2843 } rogue_iterator_args;
2844
2845 /**
2846 * \brief Vertex input register allocations.
2847 */
2848 typedef struct rogue_vertex_inputs {
2849 unsigned num_input_vars;
2850 unsigned base[ROGUE_MAX_IO_ATTRIB_VARS];
2851 unsigned components[ROGUE_MAX_IO_ATTRIB_VARS];
2852 } rogue_vertex_inputs;
2853
2854 /**
2855 * \brief Vertex output allocations.
2856 */
2857 typedef struct rogue_vertex_outputs {
2858 unsigned num_output_vars;
2859 unsigned base[ROGUE_MAX_IO_VARYING_VARS];
2860 unsigned components[ROGUE_MAX_IO_VARYING_VARS];
2861 } rogue_vertex_outputs;
2862
2863 enum rogue_msaa_mode {
2864 ROGUE_MSAA_MODE_UNDEF = 0, /* explicitly treat 0 as undefined */
2865 /* One task for all samples. */
2866 ROGUE_MSAA_MODE_PIXEL,
2867 /* For on-edge pixels only: separate tasks for each sample. */
2868 ROGUE_MSAA_MODE_SELECTIVE,
2869 /* For all pixels: separate tasks for each sample. */
2870 ROGUE_MSAA_MODE_FULL,
2871 };
2872
2873 /**
2874 * \brief Stage-specific build data.
2875 */
2876 typedef struct rogue_build_data {
2877 struct rogue_fs_build_data {
2878 rogue_iterator_args iterator_args;
2879 enum rogue_msaa_mode msaa_mode;
2880 bool phas; /* Indicates the presence of PHAS instruction. */
2881 } fs;
2882 struct rogue_vs_build_data {
2883 /* TODO: Should these be removed since the driver allocates the vertex
2884 * inputs?
2885 */
2886 rogue_vertex_inputs inputs;
2887 unsigned num_vertex_input_regs; /* Final number of inputs. */
2888
2889 rogue_vertex_outputs outputs;
2890 unsigned num_vertex_outputs; /* Final number of outputs. */
2891
2892 unsigned num_varyings; /* Final number of varyings. */
2893 } vs;
2894 } rogue_build_data;
2895
2896 /**
2897 * \brief Shared multi-stage build context.
2898 */
2899 typedef struct rogue_build_ctx {
2900 rogue_compiler *compiler;
2901
2902 /* Shaders in various stages of compilations. */
2903 nir_shader *nir[MESA_SHADER_FRAGMENT + 1];
2904 rogue_shader *rogue[MESA_SHADER_FRAGMENT + 1];
2905 struct util_dynarray binary[MESA_SHADER_FRAGMENT + 1];
2906
2907 rogue_common_build_data common_data[MESA_SHADER_FRAGMENT + 1];
2908 rogue_build_data stage_data;
2909 struct pvr_pipeline_layout *pipeline_layout;
2910 unsigned next_ssa_idx;
2911 } rogue_build_ctx;
2912
2913 rogue_build_ctx *
2914 rogue_build_context_create(rogue_compiler *compiler,
2915 struct pvr_pipeline_layout *pipeline_layout);
2916
2917 void rogue_collect_io_data(rogue_build_ctx *ctx, nir_shader *nir);
2918
2919 unsigned rogue_count_used_regs(const rogue_shader *shader,
2920 enum rogue_reg_class class);
2921
2922 unsigned rogue_coeff_index_fs(rogue_iterator_args *args,
2923 gl_varying_slot location,
2924 unsigned component);
2925
2926 unsigned rogue_output_index_vs(rogue_vertex_outputs *outputs,
2927 gl_varying_slot location,
2928 unsigned component);
2929
2930 unsigned rogue_ubo_reg(rogue_ubo_data *ubo_data,
2931 unsigned desc_set,
2932 unsigned binding,
2933 unsigned offset_bytes);
2934
2935 nir_shader *rogue_spirv_to_nir(rogue_build_ctx *ctx,
2936 gl_shader_stage stage,
2937 const char *entry,
2938 unsigned spirv_size,
2939 const uint32_t *spirv_data,
2940 unsigned num_spec,
2941 struct nir_spirv_specialization *spec);
2942
2943 /* Custom NIR passes. */
2944 void rogue_nir_pfo(nir_shader *shader);
2945
2946 bool rogue_nir_lower_io(nir_shader *shader);
2947
2948 rogue_shader *rogue_nir_to_rogue(rogue_build_ctx *ctx, const nir_shader *nir);
2949
2950 /* Encode/decode */
2951
2952 void rogue_encode_shader(rogue_build_ctx *ctx,
2953 rogue_shader *shader,
2954 struct util_dynarray *binary);
2955
2956 #endif /* ROGUE_H */
2957