xref: /aosp_15_r20/external/mesa3d/src/imagination/rogue/rogue_encode.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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