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 #include "rogue.h"
25 #include "rogue_isa.h"
26 #include "util/macros.h"
27 #include "util/u_dynarray.h"
28
29 #include <stdbool.h>
30
31 /**
32 * \file rogue_encode.c
33 *
34 * \brief Contains hardware encoding functions.
35 */
36
37 #define util_dynarray_append_mem(buf, size, mem) \
38 memcpy(util_dynarray_grow_bytes((buf), 1, size), mem, size)
39
rogue_calc_da(const rogue_instr_group * group)40 static unsigned rogue_calc_da(const rogue_instr_group *group)
41 {
42 unsigned da = group->size.header;
43
44 if (group->header.alu == ROGUE_ALU_MAIN) {
45 for (unsigned u = ROGUE_INSTR_PHASE_COUNT; u > 0; --u) {
46 enum rogue_instr_phase p = u - 1;
47 if (p > ROGUE_INSTR_PHASE_1)
48 da += group->size.instrs[p];
49 }
50 } else if (group->header.alu == ROGUE_ALU_BITWISE) {
51 for (unsigned u = ROGUE_INSTR_PHASE_COUNT; u > 0; --u) {
52 enum rogue_instr_phase p = u - 1;
53 da += group->size.instrs[p];
54 }
55 } else if (group->header.alu == ROGUE_ALU_CONTROL) {
56 const rogue_instr *instr = group->instrs[ROGUE_INSTR_PHASE_CTRL];
57 const rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
58
59 if (!rogue_ctrl_op_has_srcs(ctrl->op) &&
60 !rogue_ctrl_op_has_dsts(ctrl->op)) {
61 da = 0;
62 } else {
63 da += group->size.instrs[ROGUE_INSTR_PHASE_CTRL];
64 }
65
66 } else {
67 unreachable("Unsupported instruction group ALU.");
68 }
69
70 return da;
71 }
72
73 #define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type)
rogue_calc_oporg(uint64_t alu_phases)74 static enum oporg rogue_calc_oporg(uint64_t alu_phases)
75 {
76 bool P0 = !!(alu_phases & P(0));
77 bool P1 = !!(alu_phases & P(1));
78 bool P2 = !!(alu_phases & (P(2_PCK) | P(2_TST) | P(2_MOV)));
79 bool PBE = !!(alu_phases & P(BACKEND));
80
81 if (P0 && P1 && P2 && PBE)
82 return OPORG_P0_P1_P2_BE;
83 else if (P0 && !P1 && P2 && PBE)
84 return OPORG_P0_P2_BE;
85 else if (P0 && P1 && P2 && !PBE)
86 return OPORG_P0_P1_P2;
87 else if (P0 && !P1 && P2 && !PBE)
88 return OPORG_P0_P2;
89 else if (P0 && P1 && !P2 && !PBE)
90 return OPORG_P0_P1;
91 else if (!P0 && !P1 && !P2 && PBE)
92 return OPORG_BE;
93 else if (!P0 && !P1 && P2 && !PBE)
94 return OPORG_P2;
95 else if (P0 && !P1 && !P2 && !PBE)
96 return OPORG_P0;
97
98 unreachable("Invalid ALU phase combination.");
99 }
100
rogue_calc_opcnt(uint64_t bitwise_phases)101 static enum opcnt rogue_calc_opcnt(uint64_t bitwise_phases)
102 {
103 enum opcnt opcnt = 0;
104
105 if (bitwise_phases & P(0_BITMASK) || bitwise_phases & P(0_SHIFT1) ||
106 bitwise_phases & P(0_COUNT)) {
107 opcnt |= OPCNT_P0;
108 }
109
110 if (bitwise_phases & P(1_LOGICAL))
111 opcnt |= OPCNT_P1;
112
113 if (bitwise_phases & P(2_SHIFT2) || bitwise_phases & P(2_TEST))
114 opcnt |= OPCNT_P2;
115
116 return opcnt;
117 }
118
rogue_encode_instr_group_header(rogue_instr_group * group,struct util_dynarray * binary)119 static void rogue_encode_instr_group_header(rogue_instr_group *group,
120 struct util_dynarray *binary)
121 {
122 rogue_instr_group_header_encoding h = { 0 };
123
124 h.da = rogue_calc_da(group);
125 h.length = (group->size.total / 2) % 16;
126 h.ext = (group->size.header == 3);
127
128 rogue_ref *w0ref = rogue_instr_group_io_sel_ref(&group->io_sel, ROGUE_IO_W0);
129 rogue_ref *w1ref = rogue_instr_group_io_sel_ref(&group->io_sel, ROGUE_IO_W1);
130
131 /* TODO: Update this - needs to be set for MOVMSK, and if instruction group
132 * READS OR WRITES to/from pixout regs. */
133 h.olchk = rogue_ref_is_pixout(w0ref) || rogue_ref_is_pixout(w1ref);
134 h.w1p = !rogue_ref_is_null(w1ref);
135 h.w0p = !rogue_ref_is_null(w0ref);
136
137 rogue_cc cc = { 0 };
138 switch (group->header.exec_cond) {
139 case ROGUE_EXEC_COND_PE_TRUE:
140 cc._ = CC_PE_TRUE;
141 break;
142
143 case ROGUE_EXEC_COND_P0_TRUE:
144 cc._ = CC_P0_TRUE;
145 break;
146
147 case ROGUE_EXEC_COND_PE_ANY:
148 cc._ = CC_PE_ANY;
149 break;
150
151 case ROGUE_EXEC_COND_P0_FALSE:
152 cc._ = CC_P0_FALSE;
153 break;
154
155 default:
156 unreachable("Unsupported condition code.");
157 }
158
159 h.cc = cc.cc;
160 h.ccext = cc.ccext;
161
162 switch (group->header.alu) {
163 case ROGUE_ALU_MAIN:
164 h.alutype = ALUTYPE_MAIN;
165 h.oporg = rogue_calc_oporg(group->header.phases);
166 break;
167
168 case ROGUE_ALU_BITWISE:
169 h.alutype = ALUTYPE_BITWISE;
170 h.opcnt = rogue_calc_opcnt(group->header.phases);
171 break;
172
173 case ROGUE_ALU_CONTROL:
174 h.alutype = ALUTYPE_CONTROL;
175 #define OM(op_mod) ROGUE_CTRL_OP_MOD_##op_mod
176 const rogue_instr *instr = group->instrs[ROGUE_INSTR_PHASE_CTRL];
177 const rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
178 switch (ctrl->op) {
179 case ROGUE_CTRL_OP_NOP:
180 h.ctrlop = CTRLOP_NOP;
181 h.miscctl = rogue_ctrl_op_mod_is_set(ctrl, OM(END));
182 break;
183
184 case ROGUE_CTRL_OP_WOP:
185 h.ctrlop = CTRLOP_WOP;
186 break;
187
188 case ROGUE_CTRL_OP_BR:
189 case ROGUE_CTRL_OP_BA:
190 h.ctrlop = CTRLOP_BA;
191 break;
192
193 case ROGUE_CTRL_OP_WDF:
194 h.ctrlop = CTRLOP_WDF;
195 h.miscctl = rogue_ref_get_drc_index(&ctrl->src[0].ref);
196 break;
197
198 default:
199 unreachable("Unsupported ctrl op.");
200 }
201 #undef OM
202 break;
203
204 default:
205 unreachable("Unsupported instruction group ALU.");
206 }
207
208 if (group->header.alu != ROGUE_ALU_CONTROL) {
209 h.end = group->header.end;
210 /* h.atom = ; */ /* Unused for now */
211 h.rpt = group->header.repeat - 1;
212 }
213
214 util_dynarray_append_mem(binary, group->size.header, &h);
215 }
216 #undef P
217
218 typedef union rogue_instr_encoding {
219 rogue_alu_instr_encoding alu;
220 rogue_backend_instr_encoding backend;
221 rogue_ctrl_instr_encoding ctrl;
222 rogue_bitwise_instr_encoding bitwise;
223 } PACKED rogue_instr_encoding;
224
rogue_alu_movc_ft(const rogue_ref * ref)225 static unsigned rogue_alu_movc_ft(const rogue_ref *ref)
226 {
227 switch (rogue_ref_get_io(ref)) {
228 case ROGUE_IO_NONE:
229 case ROGUE_IO_FT0:
230 return MOVW_FT0;
231
232 case ROGUE_IO_FT1:
233 return MOVW_FT1;
234
235 case ROGUE_IO_FT2:
236 return MOVW_FT2;
237
238 case ROGUE_IO_FTE:
239 return MOVW_FTE;
240
241 default:
242 break;
243 }
244
245 unreachable("Invalid source.");
246 }
247
248 #define SM(src_mod) ROGUE_ALU_SRC_MOD_##src_mod
249 #define DM(dst_mod) ROGUE_ALU_DST_MOD_##dst_mod
250 #define OM(op_mod) ROGUE_ALU_OP_MOD_##op_mod
rogue_encode_alu_instr(const rogue_alu_instr * alu,unsigned instr_size,rogue_instr_encoding * instr_encoding)251 static void rogue_encode_alu_instr(const rogue_alu_instr *alu,
252 unsigned instr_size,
253 rogue_instr_encoding *instr_encoding)
254 {
255 switch (alu->op) {
256 case ROGUE_ALU_OP_MBYP:
257 instr_encoding->alu.op = ALUOP_SNGL;
258 instr_encoding->alu.sngl.snglop = SNGLOP_BYP;
259
260 if (instr_size == 2) {
261 instr_encoding->alu.sngl.ext0 = 1;
262 instr_encoding->alu.sngl.mbyp.s0neg =
263 rogue_alu_src_mod_is_set(alu, 0, SM(NEG));
264 instr_encoding->alu.sngl.mbyp.s0abs =
265 rogue_alu_src_mod_is_set(alu, 0, SM(ABS));
266 }
267 break;
268
269 case ROGUE_ALU_OP_FMUL:
270 instr_encoding->alu.op = ALUOP_FMUL;
271 instr_encoding->alu.fmul.lp = rogue_alu_op_mod_is_set(alu, OM(LP));
272 instr_encoding->alu.fmul.sat = rogue_alu_op_mod_is_set(alu, OM(SAT));
273 instr_encoding->alu.fmul.s0neg =
274 rogue_alu_src_mod_is_set(alu, 0, SM(NEG));
275 instr_encoding->alu.fmul.s0abs =
276 rogue_alu_src_mod_is_set(alu, 0, SM(ABS));
277 instr_encoding->alu.fmul.s1abs =
278 rogue_alu_src_mod_is_set(alu, 1, SM(ABS));
279 instr_encoding->alu.fmul.s0flr =
280 rogue_alu_src_mod_is_set(alu, 0, SM(FLR));
281 break;
282
283 case ROGUE_ALU_OP_FMAD:
284 instr_encoding->alu.op = ALUOP_FMAD;
285 instr_encoding->alu.fmad.s0neg =
286 rogue_alu_src_mod_is_set(alu, 0, SM(NEG));
287 instr_encoding->alu.fmad.s0abs =
288 rogue_alu_src_mod_is_set(alu, 0, SM(ABS));
289 instr_encoding->alu.fmad.s2neg =
290 rogue_alu_src_mod_is_set(alu, 2, SM(NEG));
291 instr_encoding->alu.fmad.sat = rogue_alu_op_mod_is_set(alu, OM(SAT));
292
293 if (instr_size == 2) {
294 instr_encoding->alu.fmad.ext = 1;
295 instr_encoding->alu.fmad.lp = rogue_alu_op_mod_is_set(alu, OM(LP));
296 instr_encoding->alu.fmad.s1abs =
297 rogue_alu_src_mod_is_set(alu, 1, SM(ABS));
298 instr_encoding->alu.fmad.s1neg =
299 rogue_alu_src_mod_is_set(alu, 1, SM(NEG));
300 instr_encoding->alu.fmad.s2flr =
301 rogue_alu_src_mod_is_set(alu, 2, SM(FLR));
302 instr_encoding->alu.fmad.s2abs =
303 rogue_alu_src_mod_is_set(alu, 2, SM(ABS));
304 }
305 break;
306
307 case ROGUE_ALU_OP_TST: {
308 instr_encoding->alu.op = ALUOP_TST;
309 instr_encoding->alu.tst.pwen = rogue_ref_is_io_p0(&alu->dst[1].ref);
310
311 rogue_tstop tstop = { 0 };
312 if (rogue_alu_op_mod_is_set(alu, OM(Z)))
313 tstop._ = TSTOP_Z;
314 else if (rogue_alu_op_mod_is_set(alu, OM(GZ)))
315 tstop._ = TSTOP_GZ;
316 else if (rogue_alu_op_mod_is_set(alu, OM(GEZ)))
317 tstop._ = TSTOP_GEZ;
318 else if (rogue_alu_op_mod_is_set(alu, OM(C)))
319 tstop._ = TSTOP_C;
320 else if (rogue_alu_op_mod_is_set(alu, OM(E)))
321 tstop._ = TSTOP_E;
322 else if (rogue_alu_op_mod_is_set(alu, OM(G)))
323 tstop._ = TSTOP_G;
324 else if (rogue_alu_op_mod_is_set(alu, OM(GE)))
325 tstop._ = TSTOP_GE;
326 else if (rogue_alu_op_mod_is_set(alu, OM(NE)))
327 tstop._ = TSTOP_NE;
328 else if (rogue_alu_op_mod_is_set(alu, OM(L)))
329 tstop._ = TSTOP_L;
330 else if (rogue_alu_op_mod_is_set(alu, OM(LE)))
331 tstop._ = TSTOP_LE;
332 else
333 unreachable("Invalid comparison test.");
334
335 instr_encoding->alu.tst.tstop_2_0 = tstop._2_0;
336
337 if (instr_size == 2) {
338 instr_encoding->alu.tst.ext = 1;
339 instr_encoding->alu.tst.tstop_3 = tstop._3;
340
341 if (rogue_alu_src_mod_is_set(alu, 0, SM(E0)))
342 instr_encoding->alu.tst.elem = TST_E0;
343 else if (rogue_alu_src_mod_is_set(alu, 0, SM(E1)))
344 instr_encoding->alu.tst.elem = TST_E1;
345 else if (rogue_alu_src_mod_is_set(alu, 0, SM(E2)))
346 instr_encoding->alu.tst.elem = TST_E2;
347 else if (rogue_alu_src_mod_is_set(alu, 0, SM(E3)))
348 instr_encoding->alu.tst.elem = TST_E3;
349
350 instr_encoding->alu.tst.p2end =
351 !rogue_phase_occupied(ROGUE_INSTR_PHASE_2_PCK,
352 alu->instr.group->header.phases);
353
354 if (rogue_alu_op_mod_is_set(alu, OM(F32)))
355 instr_encoding->alu.tst.type = TSTTYPE_F32;
356 else if (rogue_alu_op_mod_is_set(alu, OM(U16)))
357 instr_encoding->alu.tst.type = TSTTYPE_U16;
358 else if (rogue_alu_op_mod_is_set(alu, OM(S16)))
359 instr_encoding->alu.tst.type = TSTTYPE_S16;
360 else if (rogue_alu_op_mod_is_set(alu, OM(U8)))
361 instr_encoding->alu.tst.type = TSTTYPE_U8;
362 else if (rogue_alu_op_mod_is_set(alu, OM(S8)))
363 instr_encoding->alu.tst.type = TSTTYPE_S8;
364 else if (rogue_alu_op_mod_is_set(alu, OM(U32)))
365 instr_encoding->alu.tst.type = TSTTYPE_U32;
366 else if (rogue_alu_op_mod_is_set(alu, OM(S32)))
367 instr_encoding->alu.tst.type = TSTTYPE_S32;
368 else
369 unreachable("Invalid comparison type.");
370 }
371 break;
372 }
373
374 case ROGUE_ALU_OP_MOVC: {
375 instr_encoding->alu.op = ALUOP_MOVC;
376
377 bool e0 = rogue_alu_dst_mod_is_set(alu, 0, DM(E0));
378 bool e1 = rogue_alu_dst_mod_is_set(alu, 0, DM(E1));
379 bool e2 = rogue_alu_dst_mod_is_set(alu, 0, DM(E2));
380 bool e3 = rogue_alu_dst_mod_is_set(alu, 0, DM(E3));
381 bool e_none = !e0 && !e1 && !e2 && !e3;
382
383 instr_encoding->alu.movc.movw0 = rogue_alu_movc_ft(&alu->src[1].ref);
384 instr_encoding->alu.movc.movw1 = rogue_alu_movc_ft(&alu->src[2].ref);
385
386 if (instr_size == 2) {
387 instr_encoding->alu.movc.ext = 1;
388 instr_encoding->alu.movc.p2end =
389 !rogue_phase_occupied(ROGUE_INSTR_PHASE_2_TST,
390 alu->instr.group->header.phases) &&
391 !rogue_phase_occupied(ROGUE_INSTR_PHASE_2_PCK,
392 alu->instr.group->header.phases);
393 instr_encoding->alu.movc.aw = !rogue_ref_is_io_ftt(&alu->src[0].ref);
394
395 if (e_none) {
396 instr_encoding->alu.movc.maskw0 = MASKW0_EALL;
397 } else {
398 instr_encoding->alu.movc.maskw0 |= e0 ? MASKW0_E0 : 0;
399 instr_encoding->alu.movc.maskw0 |= e1 ? MASKW0_E1 : 0;
400 instr_encoding->alu.movc.maskw0 |= e2 ? MASKW0_E2 : 0;
401 instr_encoding->alu.movc.maskw0 |= e3 ? MASKW0_E3 : 0;
402 }
403 }
404 break;
405 }
406
407 case ROGUE_ALU_OP_PCK_U8888:
408 instr_encoding->alu.op = ALUOP_SNGL;
409 instr_encoding->alu.sngl.snglop = SNGLOP_PCK;
410 instr_encoding->alu.sngl.ext0 = 1;
411
412 instr_encoding->alu.sngl.pck.pck.prog = 0;
413 instr_encoding->alu.sngl.pck.pck.rtz =
414 rogue_alu_op_mod_is_set(alu, OM(ROUNDZERO));
415 instr_encoding->alu.sngl.pck.pck.scale =
416 rogue_alu_op_mod_is_set(alu, OM(SCALE));
417 instr_encoding->alu.sngl.pck.pck.format = PCK_FMT_U8888;
418 break;
419
420 case ROGUE_ALU_OP_ADD64:
421 instr_encoding->alu.op = ALUOP_INT32_64;
422
423 instr_encoding->alu.int32_64.int32_64_op = INT32_64_OP_ADD64_NMX;
424 instr_encoding->alu.int32_64.s2neg =
425 rogue_alu_src_mod_is_set(alu, 2, SM(NEG));
426 instr_encoding->alu.int32_64.s = 0;
427
428 if (instr_size == 2) {
429 instr_encoding->alu.int32_64.ext = 1;
430 instr_encoding->alu.int32_64.s2abs =
431 rogue_alu_src_mod_is_set(alu, 2, SM(ABS));
432 instr_encoding->alu.int32_64.s1abs =
433 rogue_alu_src_mod_is_set(alu, 1, SM(ABS));
434 instr_encoding->alu.int32_64.s0abs =
435 rogue_alu_src_mod_is_set(alu, 0, SM(ABS));
436 instr_encoding->alu.int32_64.s0neg =
437 rogue_alu_src_mod_is_set(alu, 0, SM(NEG));
438 instr_encoding->alu.int32_64.s1neg =
439 rogue_alu_src_mod_is_set(alu, 1, SM(NEG));
440 instr_encoding->alu.int32_64.cin =
441 rogue_ref_is_io_p0(&alu->src[4].ref);
442 }
443 break;
444
445 default:
446 unreachable("Unsupported alu op.");
447 }
448 }
449 #undef OM
450 #undef DM
451 #undef SM
452
453 #define OM(op_mod) ROGUE_BACKEND_OP_MOD_##op_mod
rogue_backend_get_cachemode(const rogue_backend_instr * backend)454 static unsigned rogue_backend_get_cachemode(const rogue_backend_instr *backend)
455 {
456 if (rogue_backend_op_mod_is_set(backend, OM(BYPASS)))
457 return CACHEMODE_LD_BYPASS;
458 else if (rogue_backend_op_mod_is_set(backend, OM(FORCELINEFILL)))
459 return CACHEMODE_LD_FORCE_LINE_FILL;
460 else if (rogue_backend_op_mod_is_set(backend, OM(WRITETHROUGH)))
461 return CACHEMODE_ST_WRITE_THROUGH;
462 else if (rogue_backend_op_mod_is_set(backend, OM(WRITEBACK)))
463 return CACHEMODE_ST_WRITE_BACK;
464 else if (rogue_backend_op_mod_is_set(backend, OM(LAZYWRITEBACK)))
465 return CACHEMODE_ST_WRITE_BACK_LAZY;
466
467 /* Default cache mode. */
468 return CACHEMODE_LD_NORMAL; /* == CACHEMODE_ST_WRITE_THROUGH */
469 }
470
471 static unsigned
rogue_backend_get_slccachemode(const rogue_backend_instr * backend)472 rogue_backend_get_slccachemode(const rogue_backend_instr *backend)
473 {
474 if (rogue_backend_op_mod_is_set(backend, OM(SLCBYPASS)))
475 return SLCCACHEMODE_BYPASS;
476 else if (rogue_backend_op_mod_is_set(backend, OM(SLCWRITEBACK)))
477 return SLCCACHEMODE_WRITE_BACK;
478 else if (rogue_backend_op_mod_is_set(backend, OM(SLCWRITETHROUGH)))
479 return SLCCACHEMODE_WRITE_THROUGH;
480 else if (rogue_backend_op_mod_is_set(backend, OM(SLCNOALLOC)))
481 return SLCCACHEMODE_CACHED_READS;
482
483 /* Default SLC cache mode. */
484 return SLCCACHEMODE_BYPASS;
485 }
486
rogue_encode_backend_instr(const rogue_backend_instr * backend,unsigned instr_size,rogue_instr_encoding * instr_encoding)487 static void rogue_encode_backend_instr(const rogue_backend_instr *backend,
488 unsigned instr_size,
489 rogue_instr_encoding *instr_encoding)
490 {
491 switch (backend->op) {
492 case ROGUE_BACKEND_OP_FITR_PIXEL:
493 instr_encoding->backend.op = BACKENDOP_FITR;
494 instr_encoding->backend.fitr.p = 0;
495 instr_encoding->backend.fitr.drc =
496 rogue_ref_get_drc_index(&backend->src[0].ref);
497 instr_encoding->backend.fitr.mode = FITR_MODE_PIXEL;
498 instr_encoding->backend.fitr.sat =
499 rogue_backend_op_mod_is_set(backend, OM(SAT));
500 instr_encoding->backend.fitr.count =
501 rogue_ref_get_val(&backend->src[2].ref);
502 break;
503
504 case ROGUE_BACKEND_OP_FITRP_PIXEL:
505 instr_encoding->backend.op = BACKENDOP_FITR;
506 instr_encoding->backend.fitr.p = 1;
507 instr_encoding->backend.fitr.drc =
508 rogue_ref_get_drc_index(&backend->src[0].ref);
509 instr_encoding->backend.fitr.mode = FITR_MODE_PIXEL;
510 instr_encoding->backend.fitr.sat =
511 rogue_backend_op_mod_is_set(backend, OM(SAT));
512 instr_encoding->backend.fitr.count =
513 rogue_ref_get_val(&backend->src[3].ref);
514 break;
515
516 case ROGUE_BACKEND_OP_UVSW_WRITE:
517 instr_encoding->backend.op = BACKENDOP_UVSW;
518 instr_encoding->backend.uvsw.writeop = UVSW_WRITEOP_WRITE;
519 instr_encoding->backend.uvsw.imm = 1;
520 instr_encoding->backend.uvsw.imm_src.imm_addr =
521 rogue_ref_get_reg_index(&backend->dst[0].ref);
522 break;
523
524 case ROGUE_BACKEND_OP_UVSW_EMIT:
525 instr_encoding->backend.op = BACKENDOP_UVSW;
526 instr_encoding->backend.uvsw.writeop = UVSW_WRITEOP_EMIT;
527 break;
528
529 case ROGUE_BACKEND_OP_UVSW_ENDTASK:
530 instr_encoding->backend.op = BACKENDOP_UVSW;
531 instr_encoding->backend.uvsw.writeop = UVSW_WRITEOP_END;
532 break;
533
534 case ROGUE_BACKEND_OP_UVSW_EMITTHENENDTASK:
535 instr_encoding->backend.op = BACKENDOP_UVSW;
536 instr_encoding->backend.uvsw.writeop = UVSW_WRITEOP_EMIT_END;
537 break;
538
539 case ROGUE_BACKEND_OP_UVSW_WRITETHENEMITTHENENDTASK:
540 instr_encoding->backend.op = BACKENDOP_UVSW;
541 instr_encoding->backend.uvsw.writeop = UVSW_WRITEOP_WRITE_EMIT_END;
542 instr_encoding->backend.uvsw.imm = 1;
543 instr_encoding->backend.uvsw.imm_src.imm_addr =
544 rogue_ref_get_reg_index(&backend->dst[0].ref);
545 break;
546
547 case ROGUE_BACKEND_OP_LD: {
548 instr_encoding->backend.op = BACKENDOP_DMA;
549 instr_encoding->backend.dma.dmaop = DMAOP_LD;
550 instr_encoding->backend.dma.ld.drc =
551 rogue_ref_get_drc_index(&backend->src[0].ref);
552 instr_encoding->backend.dma.ld.cachemode =
553 rogue_backend_get_cachemode(backend);
554
555 bool imm_burstlen = rogue_ref_is_val(&backend->src[1].ref);
556
557 rogue_burstlen burstlen = {
558 ._ = imm_burstlen ? rogue_ref_get_val(&backend->src[1].ref) : 0
559 };
560
561 if (imm_burstlen) {
562 instr_encoding->backend.dma.ld.burstlen_2_0 = burstlen._2_0;
563 } else {
564 instr_encoding->backend.dma.ld.srcselbl =
565 rogue_ref_get_io_src_index(&backend->src[1].ref);
566 }
567
568 instr_encoding->backend.dma.ld.srcseladd =
569 rogue_ref_get_io_src_index(&backend->src[2].ref);
570
571 if (instr_size == 3) {
572 instr_encoding->backend.dma.ld.ext = 1;
573 if (imm_burstlen)
574 instr_encoding->backend.dma.ld.burstlen_3 = burstlen._3;
575
576 instr_encoding->backend.dma.ld.slccachemode =
577 rogue_backend_get_slccachemode(backend);
578 instr_encoding->backend.dma.ld.notimmbl = !imm_burstlen;
579 }
580
581 break;
582 }
583
584 case ROGUE_BACKEND_OP_ST: {
585 instr_encoding->backend.op = BACKENDOP_DMA;
586 instr_encoding->backend.dma.dmaop = DMAOP_ST;
587 instr_encoding->backend.dma.st.drc =
588 rogue_ref_get_drc_index(&backend->src[2].ref);
589
590 bool imm_burstlen = rogue_ref_is_val(&backend->src[3].ref);
591
592 instr_encoding->backend.dma.st.immbl = imm_burstlen;
593
594 if (imm_burstlen) {
595 rogue_burstlen burstlen = { ._ = rogue_ref_get_val(
596 &backend->src[3].ref) };
597 instr_encoding->backend.dma.st.burstlen_2_0 = burstlen._2_0;
598 instr_encoding->backend.dma.st.burstlen_3 = burstlen._3;
599 } else {
600 instr_encoding->backend.dma.st.srcselbl =
601 rogue_ref_get_io_src_index(&backend->src[3].ref);
602 }
603
604 instr_encoding->backend.dma.st.cachemode =
605 rogue_backend_get_cachemode(backend);
606 instr_encoding->backend.dma.st.srcseladd =
607 rogue_ref_get_io_src_index(&backend->src[4].ref);
608
609 instr_encoding->backend.dma.st.dsize =
610 rogue_ref_get_val(&backend->src[1].ref);
611 instr_encoding->backend.dma.st.srcseldata =
612 rogue_ref_get_io_src_index(&backend->src[0].ref);
613
614 if (instr_size == 4) {
615 instr_encoding->backend.dma.st.ext = 1;
616 instr_encoding->backend.dma.st.srcmask =
617 rogue_ref_get_io_src_index(&backend->src[5].ref);
618 instr_encoding->backend.dma.st.slccachemode =
619 rogue_backend_get_slccachemode(backend);
620 instr_encoding->backend.dma.st.nottiled =
621 !rogue_backend_op_mod_is_set(backend, OM(TILED));
622 }
623
624 break;
625 }
626
627 case ROGUE_BACKEND_OP_SMP1D:
628 case ROGUE_BACKEND_OP_SMP2D:
629 case ROGUE_BACKEND_OP_SMP3D:
630 instr_encoding->backend.op = BACKENDOP_DMA;
631 instr_encoding->backend.dma.dmaop = DMAOP_SMP;
632
633 instr_encoding->backend.dma.smp.drc =
634 rogue_ref_get_drc_index(&backend->src[0].ref);
635 instr_encoding->backend.dma.smp.fcnorm =
636 rogue_backend_op_mod_is_set(backend, OM(FCNORM));
637
638 if (rogue_backend_op_mod_is_set(backend, OM(BIAS)))
639 instr_encoding->backend.dma.smp.lodm = LODM_BIAS;
640 else if (rogue_backend_op_mod_is_set(backend, OM(REPLACE)))
641 instr_encoding->backend.dma.smp.lodm = LODM_REPLACE;
642 else if (rogue_backend_op_mod_is_set(backend, OM(GRADIENT)))
643 instr_encoding->backend.dma.smp.lodm = LODM_GRADIENTS;
644 else
645 instr_encoding->backend.dma.smp.lodm = LODM_NORMAL;
646
647 switch (rogue_ref_get_val(&backend->src[5].ref)) {
648 case 1:
649 instr_encoding->backend.dma.smp.chan = SMPCHAN_1;
650 break;
651
652 case 2:
653 instr_encoding->backend.dma.smp.chan = SMPCHAN_2;
654 break;
655
656 case 3:
657 instr_encoding->backend.dma.smp.chan = SMPCHAN_3;
658 break;
659
660 case 4:
661 instr_encoding->backend.dma.smp.chan = SMPCHAN_4;
662 break;
663
664 default:
665 unreachable("Unsupported number of channels.");
666 }
667
668 switch (backend->op) {
669 case ROGUE_BACKEND_OP_SMP1D:
670 instr_encoding->backend.dma.smp.dmn = DMN_1D;
671 break;
672
673 case ROGUE_BACKEND_OP_SMP2D:
674 instr_encoding->backend.dma.smp.dmn = DMN_2D;
675 break;
676
677 case ROGUE_BACKEND_OP_SMP3D:
678 instr_encoding->backend.dma.smp.dmn = DMN_3D;
679 break;
680
681 default:
682 unreachable("Unsupported sampler op.");
683 }
684
685 if (instr_size > 2) {
686 instr_encoding->backend.dma.smp.exta = 1;
687
688 instr_encoding->backend.dma.smp.tao =
689 rogue_backend_op_mod_is_set(backend, OM(TAO));
690 instr_encoding->backend.dma.smp.soo =
691 rogue_backend_op_mod_is_set(backend, OM(SOO));
692 instr_encoding->backend.dma.smp.sno =
693 rogue_backend_op_mod_is_set(backend, OM(SNO));
694 instr_encoding->backend.dma.smp.nncoords =
695 rogue_backend_op_mod_is_set(backend, OM(NNCOORDS));
696
697 if (rogue_backend_op_mod_is_set(backend, OM(DATA)))
698 instr_encoding->backend.dma.smp.sbmode = SBMODE_DATA;
699 else if (rogue_backend_op_mod_is_set(backend, OM(INFO)))
700 instr_encoding->backend.dma.smp.sbmode = SBMODE_INFO;
701 else if (rogue_backend_op_mod_is_set(backend, OM(BOTH)))
702 instr_encoding->backend.dma.smp.sbmode = SBMODE_BOTH;
703 else
704 instr_encoding->backend.dma.smp.sbmode = SBMODE_NONE;
705
706 instr_encoding->backend.dma.smp.proj =
707 rogue_backend_op_mod_is_set(backend, OM(PROJ));
708 instr_encoding->backend.dma.smp.pplod =
709 rogue_backend_op_mod_is_set(backend, OM(PPLOD));
710 }
711
712 if (instr_size > 3) {
713 instr_encoding->backend.dma.smp.extb = 1;
714
715 instr_encoding->backend.dma.smp.w =
716 rogue_backend_op_mod_is_set(backend, OM(WRT));
717
718 instr_encoding->backend.dma.smp.cachemode =
719 rogue_backend_get_cachemode(backend);
720
721 instr_encoding->backend.dma.smp.swap =
722 rogue_backend_op_mod_is_set(backend, OM(SCHEDSWAP));
723 instr_encoding->backend.dma.smp.f16 =
724 rogue_backend_op_mod_is_set(backend, OM(F16));
725
726 instr_encoding->backend.dma.smp.slccachemode =
727 rogue_backend_get_slccachemode(backend);
728 }
729
730 if (instr_size > 4) {
731 instr_encoding->backend.dma.smp.extc = 1;
732
733 instr_encoding->backend.dma.smp.array =
734 rogue_backend_op_mod_is_set(backend, OM(ARRAY));
735 }
736
737 break;
738
739 case ROGUE_BACKEND_OP_IDF:
740 instr_encoding->backend.op = BACKENDOP_DMA;
741 instr_encoding->backend.dma.dmaop = DMAOP_IDF;
742 instr_encoding->backend.dma.idf.drc =
743 rogue_ref_get_drc_index(&backend->src[0].ref);
744 instr_encoding->backend.dma.idf.srcseladd =
745 rogue_ref_get_io_src_index(&backend->src[1].ref);
746 break;
747
748 case ROGUE_BACKEND_OP_EMITPIX:
749 instr_encoding->backend.op = BACKENDOP_EMIT;
750 instr_encoding->backend.emitpix.freep =
751 rogue_backend_op_mod_is_set(backend, OM(FREEP));
752 break;
753
754 default:
755 unreachable("Unsupported backend op.");
756 }
757 }
758 #undef OM
759
760 #define OM(op_mod) ROGUE_CTRL_OP_MOD_##op_mod
rogue_encode_ctrl_instr(const rogue_ctrl_instr * ctrl,unsigned instr_size,rogue_instr_encoding * instr_encoding)761 static void rogue_encode_ctrl_instr(const rogue_ctrl_instr *ctrl,
762 unsigned instr_size,
763 rogue_instr_encoding *instr_encoding)
764 {
765 /* Only some control instructions have additional bytes. */
766 switch (ctrl->op) {
767 case ROGUE_CTRL_OP_NOP:
768 memset(&instr_encoding->ctrl.nop, 0, sizeof(instr_encoding->ctrl.nop));
769 break;
770
771 case ROGUE_CTRL_OP_BR:
772 case ROGUE_CTRL_OP_BA: {
773 bool branch_abs = (ctrl->op == ROGUE_CTRL_OP_BA);
774 rogue_offset32 offset;
775
776 instr_encoding->ctrl.ba.abs = branch_abs;
777 instr_encoding->ctrl.ba.allp =
778 rogue_ctrl_op_mod_is_set(ctrl, OM(ALLINST));
779 instr_encoding->ctrl.ba.anyp =
780 rogue_ctrl_op_mod_is_set(ctrl, OM(ANYINST));
781 instr_encoding->ctrl.ba.link = rogue_ctrl_op_mod_is_set(ctrl, OM(LINK));
782
783 if (branch_abs) {
784 offset._ = rogue_ref_get_val(&ctrl->src[0].ref);
785 } else {
786 rogue_instr_group *block_group =
787 list_entry(ctrl->target_block->instrs.next,
788 rogue_instr_group,
789 link);
790 offset._ = block_group->size.offset - (ctrl->instr.group->size.offset +
791 ctrl->instr.group->size.total);
792 }
793
794 instr_encoding->ctrl.ba.offset_7_1 = offset._7_1;
795 instr_encoding->ctrl.ba.offset_15_8 = offset._15_8;
796 instr_encoding->ctrl.ba.offset_23_16 = offset._23_16;
797 instr_encoding->ctrl.ba.offset_31_24 = offset._31_24;
798
799 break;
800 }
801
802 default:
803 unreachable("Unsupported ctrl op.");
804 }
805 }
806 #undef OM
807
rogue_encode_bitwise_instr(const rogue_bitwise_instr * bitwise,unsigned instr_size,rogue_instr_encoding * instr_encoding)808 static void rogue_encode_bitwise_instr(const rogue_bitwise_instr *bitwise,
809 unsigned instr_size,
810 rogue_instr_encoding *instr_encoding)
811 {
812 switch (bitwise->op) {
813 case ROGUE_BITWISE_OP_BYP0: {
814 instr_encoding->bitwise.phase0 = 1;
815 instr_encoding->bitwise.ph0.shft = SHFT1_BYP;
816 instr_encoding->bitwise.ph0.cnt_byp = 1;
817
818 rogue_imm32 imm32;
819 if (rogue_ref_is_val(&bitwise->src[1].ref))
820 imm32._ = rogue_ref_get_val(&bitwise->src[1].ref);
821
822 if (instr_size > 1) {
823 instr_encoding->bitwise.ph0.ext = 1;
824 instr_encoding->bitwise.ph0.imm_7_0 = imm32._7_0;
825 instr_encoding->bitwise.ph0.imm_15_8 = imm32._15_8;
826 }
827
828 if (instr_size > 3) {
829 instr_encoding->bitwise.ph0.bm = 1;
830 instr_encoding->bitwise.ph0.imm_23_16 = imm32._23_16;
831 instr_encoding->bitwise.ph0.imm_31_24 = imm32._31_24;
832 }
833
834 break;
835 }
836
837 default:
838 unreachable("Invalid bitwise op.");
839 }
840 }
841
rogue_encode_instr_group_instrs(rogue_instr_group * group,struct util_dynarray * binary)842 static void rogue_encode_instr_group_instrs(rogue_instr_group *group,
843 struct util_dynarray *binary)
844 {
845 rogue_instr_encoding instr_encoding;
846
847 /* Reverse order for encoding. */
848 rogue_foreach_phase_in_set_rev (p, group->header.phases) {
849 if (!group->size.instrs[p])
850 continue;
851
852 memset(&instr_encoding, 0, sizeof(instr_encoding));
853
854 const rogue_instr *instr = group->instrs[p];
855 switch (instr->type) {
856 case ROGUE_INSTR_TYPE_ALU:
857 rogue_encode_alu_instr(rogue_instr_as_alu(instr),
858 group->size.instrs[p],
859 &instr_encoding);
860 break;
861
862 case ROGUE_INSTR_TYPE_BACKEND:
863 rogue_encode_backend_instr(rogue_instr_as_backend(instr),
864 group->size.instrs[p],
865 &instr_encoding);
866 break;
867
868 case ROGUE_INSTR_TYPE_CTRL:
869 rogue_encode_ctrl_instr(rogue_instr_as_ctrl(instr),
870 group->size.instrs[p],
871 &instr_encoding);
872 break;
873
874 case ROGUE_INSTR_TYPE_BITWISE:
875 rogue_encode_bitwise_instr(rogue_instr_as_bitwise(instr),
876 group->size.instrs[p],
877 &instr_encoding);
878 break;
879
880 default:
881 unreachable("Unsupported instruction type.");
882 }
883
884 util_dynarray_append_mem(binary, group->size.instrs[p], &instr_encoding);
885 }
886 }
887
rogue_encode_source_map(const rogue_instr_group * group,bool upper_srcs,rogue_source_map_encoding * e)888 static void rogue_encode_source_map(const rogue_instr_group *group,
889 bool upper_srcs,
890 rogue_source_map_encoding *e)
891 {
892 unsigned base = upper_srcs ? 3 : 0;
893 unsigned index = upper_srcs ? group->encode_info.upper_src_index
894 : group->encode_info.lower_src_index;
895 const rogue_reg_src_info *info = upper_srcs
896 ? &rogue_reg_upper_src_infos[index]
897 : &rogue_reg_lower_src_infos[index];
898 const rogue_instr_group_io_sel *io_sel = &group->io_sel;
899
900 rogue_mux mux = { 0 };
901
902 if (!upper_srcs && rogue_ref_is_io(&io_sel->iss[0])) {
903 switch (io_sel->iss[0].io) {
904 case ROGUE_IO_S0:
905 mux._ = IS0_S0;
906 break;
907 case ROGUE_IO_S3:
908 mux._ = IS0_S3;
909 break;
910 case ROGUE_IO_S4:
911 mux._ = IS0_S4;
912 break;
913 case ROGUE_IO_S5:
914 mux._ = IS0_S5;
915 break;
916 case ROGUE_IO_S1:
917 mux._ = IS0_S1;
918 break;
919 case ROGUE_IO_S2:
920 mux._ = IS0_S2;
921 break;
922
923 default:
924 unreachable("IS0 set to unsupported value.");
925 }
926 }
927
928 rogue_sbA sbA = { 0 };
929 rogue_sA sA = { 0 };
930
931 if (!rogue_ref_is_null(&io_sel->srcs[base + 0])) {
932 sbA._ = rogue_reg_bank_encoding(
933 rogue_ref_get_reg_class(&io_sel->srcs[base + 0]));
934 sA._ = rogue_ref_get_reg_index(&io_sel->srcs[base + 0]);
935 }
936
937 rogue_sbB sbB = { 0 };
938 rogue_sB sB = { 0 };
939
940 if (!rogue_ref_is_null(&io_sel->srcs[base + 1])) {
941 sbB._ = rogue_reg_bank_encoding(
942 rogue_ref_get_reg_class(&io_sel->srcs[base + 1]));
943 sB._ = rogue_ref_get_reg_index(&io_sel->srcs[base + 1]);
944 }
945
946 rogue_sbC sbC = { 0 };
947 rogue_sC sC = { 0 };
948
949 if (!rogue_ref_is_null(&io_sel->srcs[base + 2])) {
950 sbC._ = rogue_reg_bank_encoding(
951 rogue_ref_get_reg_class(&io_sel->srcs[base + 2]));
952 sC._ = rogue_ref_get_reg_index(&io_sel->srcs[base + 2]);
953 }
954
955 /* Byte 0 is common for all encodings. */
956 e->sbA_0 = sbA._0;
957 e->sA_5_0 = sA._5_0;
958
959 switch (info->num_srcs) {
960 case 1:
961 switch (info->bytes) {
962 case 3:
963 /* Byte 1 */
964 assert(!upper_srcs || !mux._1_0);
965
966 e->sA_1.mux_1_0 = mux._1_0;
967 e->sA_1.sbA_2_1 = sbA._2_1;
968 e->sA_1.sA_7_6 = sA._7_6;
969
970 /* Byte 2 */
971 e->sA_2.sA_10_8 = sA._10_8;
972
973 e->ext0 = 1;
974 FALLTHROUGH;
975
976 case 1:
977 break;
978
979 default:
980 unreachable("Unsupported source/bytes combination.");
981 }
982 break;
983
984 case 2:
985 e->ext0 = 1;
986 e->sel = 1;
987 switch (info->bytes) {
988 case 4:
989 /* Byte 3 */
990 assert(!upper_srcs || !mux._2);
991
992 e->sB_3.sA_10_8 = sA._10_8;
993 e->sB_3.mux_2 = mux._2;
994 e->sB_3.sbA_2 = sbA._2;
995 e->sB_3.sA_7 = sA._7;
996 e->sB_3.sB_7 = sB._7;
997
998 e->ext2 = 1;
999 FALLTHROUGH;
1000
1001 case 3:
1002 /* Byte 2 */
1003 assert(!upper_srcs || !mux._1_0);
1004
1005 e->mux_1_0 = mux._1_0;
1006 e->sbA_1 = sbA._1;
1007 e->sbB_1 = sbB._1;
1008 e->sA_6 = sA._6;
1009 e->sB_6_5 = sB._6_5;
1010
1011 e->ext1 = 1;
1012 FALLTHROUGH;
1013
1014 case 2:
1015 /* Byte 1 */
1016 e->sbB_0 = sbB._0;
1017 e->sB_4_0 = sB._4_0;
1018 break;
1019
1020 default:
1021 unreachable("Unsupported source/bytes combination.");
1022 }
1023 break;
1024
1025 case 3:
1026 e->ext0 = 1;
1027 e->ext1 = 1;
1028 switch (info->bytes) {
1029 case 6:
1030 /* Byte 5 */
1031 assert(!upper_srcs || !sC._10_8);
1032
1033 e->sC_5.sC_10_8 = sC._10_8;
1034 e->sC_5.sA_10_8 = sA._10_8;
1035
1036 e->sC_4.ext4 = 1;
1037 FALLTHROUGH;
1038
1039 case 5:
1040 /* Byte 4 */
1041 assert(!upper_srcs || !mux._2);
1042 assert(!upper_srcs || !sbC._2);
1043
1044 e->sC_4.sbC_2 = sbC._2;
1045 e->sC_4.sC_7_6 = sC._7_6;
1046 e->sC_4.mux_2 = mux._2;
1047 e->sC_4.sbA_2 = sbA._2;
1048 e->sC_4.sA_7 = sA._7;
1049 e->sC_4.sB_7 = sB._7;
1050
1051 e->ext2 = 1;
1052 FALLTHROUGH;
1053
1054 case 4:
1055 /* Byte 1 */
1056 e->sbB_0 = sbB._0;
1057 e->sB_4_0 = sB._4_0;
1058
1059 /* Byte 2 */
1060 assert(!upper_srcs || !mux._1_0);
1061
1062 e->mux_1_0 = mux._1_0;
1063 e->sbA_1 = sbA._1;
1064 e->sbB_1 = sbB._1;
1065 e->sA_6 = sA._6;
1066 e->sB_6_5 = sB._6_5;
1067
1068 /* Byte 3 */
1069 e->sbC_1_0 = sbC._1_0;
1070 e->sC_5_0 = sC._5_0;
1071 break;
1072
1073 default:
1074 unreachable("Unsupported source/bytes combination.");
1075 }
1076 break;
1077
1078 default:
1079 unreachable("Unsupported source/bytes combination.");
1080 }
1081 }
1082
rogue_encode_dest_map(const rogue_instr_group * group,rogue_dest_map_encoding * e)1083 static void rogue_encode_dest_map(const rogue_instr_group *group,
1084 rogue_dest_map_encoding *e)
1085 {
1086 const rogue_reg_dst_info *info =
1087 &rogue_reg_dst_infos[group->encode_info.dst_index];
1088 const rogue_instr_group_io_sel *io_sel = &group->io_sel;
1089
1090 unsigned num_dsts = !rogue_ref_is_null(&io_sel->dsts[0]) +
1091 !rogue_ref_is_null(&io_sel->dsts[1]);
1092
1093 switch (num_dsts) {
1094 case 1: {
1095 const rogue_ref *dst_ref = !rogue_ref_is_null(&io_sel->dsts[0])
1096 ? &io_sel->dsts[0]
1097 : &io_sel->dsts[1];
1098
1099 rogue_dbN dbN = { ._ = rogue_reg_bank_encoding(
1100 rogue_ref_get_reg_class(dst_ref)) };
1101 rogue_dN dN = { ._ = rogue_ref_get_reg_index(dst_ref) };
1102
1103 switch (info->bytes) {
1104 case 2:
1105 e->dN_10_8 = dN._10_8;
1106 e->dbN_2_1 = dbN._2_1;
1107 e->dN_7_6 = dN._7_6;
1108
1109 e->ext0 = 1;
1110 FALLTHROUGH;
1111
1112 case 1:
1113 e->dbN_0 = dbN._0;
1114 e->dN_5_0 = dN._5_0;
1115 break;
1116
1117 default:
1118 unreachable("Unsupported dest/bytes combination.");
1119 }
1120 break;
1121 }
1122 case 2: {
1123 rogue_db0 db0 = { ._ = rogue_reg_bank_encoding(
1124 rogue_ref_get_reg_class(&io_sel->dsts[0])) };
1125 rogue_d0 d0 = { ._ = rogue_ref_get_reg_index(&io_sel->dsts[0]) };
1126 rogue_db1 db1 = { ._ = rogue_reg_bank_encoding(
1127 rogue_ref_get_reg_class(&io_sel->dsts[1])) };
1128 rogue_d1 d1 = { ._ = rogue_ref_get_reg_index(&io_sel->dsts[1]) };
1129
1130 switch (info->bytes) {
1131 case 4:
1132 e->d1_10_8 = d1._10_8;
1133 e->d0_10_8 = d0._10_8;
1134
1135 e->ext2 = 1;
1136 FALLTHROUGH;
1137
1138 case 3:
1139 e->db1_2_1 = db1._2_1;
1140 e->d1_7_6 = d1._7_6;
1141 e->db0_2_1 = db0._2_1;
1142 e->d0_7 = d0._7;
1143
1144 e->ext1 = 1;
1145 FALLTHROUGH;
1146
1147 case 2:
1148 e->db0_0 = db0._0;
1149 e->d0_6_0 = d0._6_0;
1150
1151 e->db1_0 = db1._0;
1152 e->d1_5_0 = d1._5_0;
1153 break;
1154
1155 default:
1156 unreachable("Unsupported dest/bytes combination.");
1157 }
1158 } break;
1159
1160 default:
1161 unreachable("Unsupported dest/bytes combination.");
1162 }
1163 }
1164
rogue_encode_iss_map(const rogue_instr_group * group,rogue_iss_encoding * e)1165 static void rogue_encode_iss_map(const rogue_instr_group *group,
1166 rogue_iss_encoding *e)
1167 {
1168 const rogue_instr_group_io_sel *io_sel = &group->io_sel;
1169
1170 if (rogue_ref_is_io(&io_sel->iss[1]))
1171 switch (rogue_ref_get_io(&io_sel->iss[1])) {
1172 case ROGUE_IO_FT0:
1173 e->is1 = IS1_FT0;
1174 break;
1175 case ROGUE_IO_FTE:
1176 e->is1 = IS1_FTE;
1177 break;
1178
1179 default:
1180 unreachable("Unsupported setting for IS1.");
1181 }
1182
1183 if (rogue_ref_is_io(&io_sel->iss[2]))
1184 switch (rogue_ref_get_io(&io_sel->iss[2])) {
1185 case ROGUE_IO_FT1:
1186 e->is2 = IS2_FT1;
1187 break;
1188 case ROGUE_IO_FTE:
1189 e->is2 = IS2_FTE;
1190 break;
1191
1192 default:
1193 unreachable("Unsupported setting for IS2.");
1194 }
1195
1196 if (rogue_ref_is_io(&io_sel->iss[3]))
1197 switch (rogue_ref_get_io(&io_sel->iss[3])) {
1198 case ROGUE_IO_FT0:
1199 e->is3 = IS3_FT0;
1200 break;
1201 case ROGUE_IO_FT1:
1202 e->is3 = IS3_FT1;
1203 break;
1204 case ROGUE_IO_S2:
1205 e->is3 = IS3_S2;
1206 break;
1207 case ROGUE_IO_FTE:
1208 e->is3 = IS3_FTE;
1209 break;
1210
1211 default:
1212 unreachable("Unsupported setting for IS3.");
1213 }
1214
1215 if (rogue_ref_is_io(&io_sel->iss[4]))
1216 switch (rogue_ref_get_io(&io_sel->iss[4])) {
1217 case ROGUE_IO_FT0:
1218 e->is4 = IS4_FT0;
1219 break;
1220 case ROGUE_IO_FT1:
1221 e->is4 = IS4_FT1;
1222 break;
1223 case ROGUE_IO_FT2:
1224 e->is4 = IS4_FT2;
1225 break;
1226 case ROGUE_IO_FTE:
1227 e->is4 = IS4_FTE;
1228 break;
1229
1230 default:
1231 unreachable("Unsupported setting for IS4.");
1232 }
1233
1234 if (rogue_ref_is_io(&io_sel->iss[5]))
1235 switch (rogue_ref_get_io(&io_sel->iss[5])) {
1236 case ROGUE_IO_FT0:
1237 e->is5 = IS5_FT0;
1238 break;
1239 case ROGUE_IO_FT1:
1240 e->is5 = IS5_FT1;
1241 break;
1242 case ROGUE_IO_FT2:
1243 e->is5 = IS5_FT2;
1244 break;
1245 case ROGUE_IO_FTE:
1246 e->is5 = IS5_FTE;
1247 break;
1248
1249 default:
1250 unreachable("Unsupported setting for IS5.");
1251 }
1252 }
1253
rogue_encode_instr_group_io(const rogue_instr_group * group,struct util_dynarray * binary)1254 static void rogue_encode_instr_group_io(const rogue_instr_group *group,
1255 struct util_dynarray *binary)
1256 {
1257 if (group->size.lower_srcs) {
1258 rogue_source_map_encoding lower_srcs = { 0 };
1259 rogue_encode_source_map(group, false, &lower_srcs);
1260 util_dynarray_append_mem(binary, group->size.lower_srcs, &lower_srcs);
1261 }
1262
1263 if (group->size.upper_srcs) {
1264 rogue_source_map_encoding upper_srcs = { 0 };
1265 rogue_encode_source_map(group, true, &upper_srcs);
1266 util_dynarray_append_mem(binary, group->size.upper_srcs, &upper_srcs);
1267 }
1268
1269 if (group->size.iss) {
1270 rogue_iss_encoding internal_src_sel = { 0 };
1271 rogue_encode_iss_map(group, &internal_src_sel);
1272 util_dynarray_append_mem(binary, group->size.iss, &internal_src_sel);
1273 }
1274
1275 if (group->size.dsts) {
1276 rogue_dest_map_encoding dests = { 0 };
1277 rogue_encode_dest_map(group, &dests);
1278 util_dynarray_append_mem(binary, group->size.dsts, &dests);
1279 }
1280 }
1281
rogue_encode_instr_group_padding(const rogue_instr_group * group,struct util_dynarray * binary)1282 static void rogue_encode_instr_group_padding(const rogue_instr_group *group,
1283 struct util_dynarray *binary)
1284 {
1285 if (group->size.word_padding)
1286 util_dynarray_append(binary, uint8_t, 0xff);
1287
1288 if (group->size.align_padding) {
1289 assert(!(group->size.align_padding % 2));
1290 unsigned align_words = group->size.align_padding / 2;
1291 util_dynarray_append(binary, uint8_t, 0xf0 | align_words);
1292 for (unsigned u = 0; u < group->size.align_padding - 1; ++u)
1293 util_dynarray_append(binary, uint8_t, 0xff);
1294 }
1295 }
1296
rogue_encode_instr_group(rogue_instr_group * group,struct util_dynarray * binary)1297 static void rogue_encode_instr_group(rogue_instr_group *group,
1298 struct util_dynarray *binary)
1299 {
1300 rogue_encode_instr_group_header(group, binary);
1301 rogue_encode_instr_group_instrs(group, binary);
1302 rogue_encode_instr_group_io(group, binary);
1303 rogue_encode_instr_group_padding(group, binary);
1304 }
1305
1306 PUBLIC
rogue_encode_shader(rogue_build_ctx * ctx,rogue_shader * shader,struct util_dynarray * binary)1307 void rogue_encode_shader(rogue_build_ctx *ctx,
1308 rogue_shader *shader,
1309 struct util_dynarray *binary)
1310 {
1311 if (!shader->is_grouped)
1312 unreachable("Can't encode shader with ungrouped instructions.");
1313
1314 util_dynarray_init(binary, ctx);
1315
1316 rogue_foreach_instr_group_in_shader (group, shader)
1317 rogue_encode_instr_group(group, binary);
1318 }
1319