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 <stdbool.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "hwdef/rogue_hw_defs.h"
31 #include "rogue_encode.h"
32 #include "rogue_encoders.h"
33 #include "rogue_operand.h"
34 #include "rogue_shader.h"
35 #include "rogue_util.h"
36 #include "util/bitscan.h"
37 #include "util/macros.h"
38
rogue_encode_reg_bank(const struct rogue_operand * operand)39 static size_t rogue_encode_reg_bank(const struct rogue_operand *operand)
40 {
41 switch (operand->type) {
42 case ROGUE_OPERAND_TYPE_REG_INTERNAL:
43 case ROGUE_OPERAND_TYPE_REG_PIXEL_OUT:
44 case ROGUE_OPERAND_TYPE_REG_CONST:
45 return 0;
46 case ROGUE_OPERAND_TYPE_REG_TEMP:
47 return 1;
48 case ROGUE_OPERAND_TYPE_REG_VERTEX_IN:
49 return 2;
50 case ROGUE_OPERAND_TYPE_REG_COEFF:
51 return 3;
52 case ROGUE_OPERAND_TYPE_REG_SHARED:
53 return 4;
54 default:
55 break;
56 }
57
58 unreachable("Unimplemented register bank.");
59 }
60
61 /**
62 * \brief Field mapping type.
63 */
64 enum rogue_map_type {
65 ROGUE_MAP_TYPE_INSTR_FLAG = 0,
66 ROGUE_MAP_TYPE_OPERAND_FLAG,
67 ROGUE_MAP_TYPE_OPERAND,
68
69 ROGUE_MAP_TYPE_COUNT,
70 };
71
72 /**
73 * \brief Field mapping rule description.
74 */
75 struct rogue_field_mapping {
76 /* Type of mapping being performed. */
77 enum rogue_map_type type;
78
79 /* Index of the source operand/flag being mapped. */
80 size_t index;
81
82 /* List of ranges to perform mapping. */
83 struct rogue_rangelist rangelist;
84
85 /* Function used to encode the input into the value to be mapped. */
86 field_encoder_t encoder_fn;
87 };
88
89 /**
90 * \brief Instruction encoding rule description.
91 */
92 struct rogue_instr_encoding {
93 /* Number of bytes making up the base mask. */
94 size_t num_bytes;
95 /* Base mask bytes. */
96 uint8_t *bytes;
97
98 /* Number of field mappings for this instruction. */
99 size_t num_mappings;
100 /* Field mappings. */
101 struct rogue_field_mapping *mappings;
102 };
103
104 static const
105 struct rogue_instr_encoding instr_encodings[ROGUE_OP_COUNT] = {
106 [ROGUE_OP_NOP] = {
107 .num_bytes = 8,
108 .bytes = (uint8_t []) { 0x04, 0x80, 0x6e, 0x00, 0xf2, 0xff, 0xff, 0xff },
109 },
110
111 [ROGUE_OP_END_FRAG] = {
112 .num_bytes = 8,
113 .bytes = (uint8_t []) { 0x04, 0x80, 0xee, 0x00, 0xf2, 0xff, 0xff, 0xff },
114 },
115
116 [ROGUE_OP_END_VERT] = {
117 .num_bytes = 8,
118 .bytes = (uint8_t []) { 0x44, 0xa0, 0x80, 0x05, 0x00, 0x00, 0x00, 0xff },
119 },
120
121 [ROGUE_OP_WDF] = {
122 .num_bytes = 8,
123 .bytes = (uint8_t []) { 0x04, 0x80, 0x6a, 0xff, 0xf2, 0xff, 0xff, 0xff },
124 .num_mappings = 1,
125 .mappings = (struct rogue_field_mapping []) {
126 {
127 .type = ROGUE_MAP_TYPE_OPERAND,
128 .index = 0,
129 .rangelist = {
130 .num_ranges = 1,
131 .ranges = (struct rogue_bitrange []) {
132 { .start = 47, .num = 1, },
133 },
134 },
135 .encoder_fn = &rogue_encoder_drc,
136 },
137 },
138 },
139
140 [ROGUE_OP_PIX_ITER_W] = {
141 .num_bytes = 16,
142 .bytes = (uint8_t []) { 0x48, 0x20, 0xb0, 0x01, 0x80, 0x40, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xff },
143 .num_mappings = 6,
144 .mappings = (struct rogue_field_mapping []) {
145 /* Instruction flag mappings. */
146 {
147 .type = ROGUE_MAP_TYPE_INSTR_FLAG,
148 .index = ROGUE_INSTR_FLAG_SAT,
149 .rangelist = {
150 .num_ranges = 1,
151 .ranges = (struct rogue_bitrange []) {
152 { .start = 100, .num = 1, },
153 },
154 },
155 .encoder_fn = NULL,
156 },
157 /* Operand mappings. */
158 {
159 .type = ROGUE_MAP_TYPE_OPERAND,
160 .index = 0,
161 .rangelist = {
162 .num_ranges = 5,
163 .ranges = (struct rogue_bitrange []) {
164 { .start = 43, .num = 2, }, /* SB3(2..1) */
165 { .start = 54, .num = 1, }, /* SB3(0) */
166 { .start = 34, .num = 3, }, /* S3(10..8) */
167 { .start = 41, .num = 2, }, /* S3(7..6) */
168 { .start = 53, .num = 6, }, /* S3(5..0) */
169 },
170 },
171 .encoder_fn = &rogue_encoder_reg_3_11,
172 },
173 {
174 .type = ROGUE_MAP_TYPE_OPERAND,
175 .index = 1,
176 .rangelist = {
177 .num_ranges = 1,
178 .ranges = (struct rogue_bitrange []) {
179 { .start = 59, .num = 1, },
180 },
181 },
182 .encoder_fn = &rogue_encoder_drc,
183 },
184 {
185 .type = ROGUE_MAP_TYPE_OPERAND,
186 .index = 2,
187 .rangelist = {
188 .num_ranges = 6,
189 .ranges = (struct rogue_bitrange []) {
190 { .start = 59, .num = 1, }, /* SB0(2) */
191 { .start = 76, .num = 1, }, /* SB0(1) */
192 { .start = 94, .num = 1, }, /* SB0(0) */
193 { .start = 57, .num = 1, }, /* S0(7) */
194 { .start = 74, .num = 1, }, /* S0(6) */
195 { .start = 93, .num = 6, }, /* S0(5..0) */
196 },
197 },
198 .encoder_fn = &rogue_encoder_reg_3_8,
199 },
200 {
201 .type = ROGUE_MAP_TYPE_OPERAND,
202 .index = 3,
203 .rangelist = {
204 .num_ranges = 4,
205 .ranges = (struct rogue_bitrange []) {
206 { .start = 63, .num = 1, }, /* SB2(2) */
207 { .start = 71, .num = 2, }, /* SB2(1..0) */
208 { .start = 62, .num = 2, }, /* S2(7..6) */
209 { .start = 69, .num = 6, }, /* S2(5..0) */
210 },
211 },
212 .encoder_fn = &rogue_encoder_reg_3_8,
213 },
214 {
215 .type = ROGUE_MAP_TYPE_OPERAND,
216 .index = 4,
217 .rangelist = {
218 .num_ranges = 1,
219 .ranges = (struct rogue_bitrange []) {
220 { .start = 99, .num = 4, },
221 },
222 },
223 .encoder_fn = &rogue_encoder_ls_1_16,
224 },
225 },
226 },
227
228 [ROGUE_OP_MAX] = {
229 .num_bytes = 16,
230 .bytes = (uint8_t []) { 0x68, 0x42, 0xd0, 0x3c, 0xfa, 0x10, 0x87, 0x80, 0xc0, 0x80, 0x10, 0x00, 0x32, 0x80, 0x00, 0xff },
231 .num_mappings = 3,
232 .mappings = (struct rogue_field_mapping []) {
233 /* Operand mappings. */
234 {
235 .type = ROGUE_MAP_TYPE_OPERAND,
236 .index = 0,
237 .rangelist = {
238 .num_ranges = 5,
239 .ranges = (struct rogue_bitrange []) {
240 { .start = 11, .num = 2, }, /* DBn(2..1) */
241 { .start = 22, .num = 1, }, /* DBn(0) */
242 { .start = 14, .num = 3, }, /* Dn(10..8) */
243 { .start = 9, .num = 2, }, /* Dn(7..6) */
244 { .start = 21, .num = 6, }, /* Dn(5..0) */
245 },
246 },
247 .encoder_fn = &rogue_encoder_reg_3_11,
248 },
249 {
250 .type = ROGUE_MAP_TYPE_OPERAND,
251 .index = 1,
252 .rangelist = {
253 .num_ranges = 7,
254 .ranges = (struct rogue_bitrange []) {
255 { .start = 43, .num = 1, }, /* SB0(2) */
256 { .start = 52, .num = 1, }, /* SB0(1) */
257 { .start = 70, .num = 1, }, /* SB0(0) */
258 { .start = 47, .num = 3, }, /* S0(10..8) */
259 { .start = 41, .num = 1, }, /* S0(7) */
260 { .start = 50, .num = 1, }, /* S0(6) */
261 { .start = 69, .num = 6, }, /* S0(5..0) */
262 },
263 },
264 .encoder_fn = &rogue_encoder_reg_3_11,
265 },
266 {
267 .type = ROGUE_MAP_TYPE_OPERAND,
268 .index = 2,
269 .rangelist = {
270 .num_ranges = 5,
271 .ranges = (struct rogue_bitrange []) {
272 { .start = 51, .num = 1, }, /* SB1(1) */
273 { .start = 61, .num = 1, }, /* SB1(0) */
274 { .start = 40, .num = 1, }, /* S1(7) */
275 { .start = 49, .num = 2, }, /* S1(6..5) */
276 { .start = 60, .num = 5, }, /* S1(4..0) */
277 },
278 },
279 .encoder_fn = &rogue_encoder_reg_2_8,
280 },
281 },
282 },
283
284 [ROGUE_OP_MIN] = {
285 .num_bytes = 16,
286 .bytes = (uint8_t []) { 0x68, 0x42, 0xd0, 0x3c, 0xf0, 0x11, 0x87, 0x80, 0xc0, 0x80, 0x10, 0x00, 0x32, 0x80, 0x00, 0xff },
287 .num_mappings = 3,
288 .mappings = (struct rogue_field_mapping []) {
289 /* Operand mappings. */
290 {
291 .type = ROGUE_MAP_TYPE_OPERAND,
292 .index = 0,
293 .rangelist = {
294 .num_ranges = 5,
295 .ranges = (struct rogue_bitrange []) {
296 { .start = 11, .num = 2, }, /* DBn(2..1) */
297 { .start = 22, .num = 1, }, /* DBn(0) */
298 { .start = 14, .num = 3, }, /* Dn(10..8) */
299 { .start = 9, .num = 2, }, /* Dn(7..6) */
300 { .start = 21, .num = 6, }, /* Dn(5..0) */
301 },
302 },
303 .encoder_fn = &rogue_encoder_reg_3_11,
304 },
305 {
306 .type = ROGUE_MAP_TYPE_OPERAND,
307 .index = 1,
308 .rangelist = {
309 .num_ranges = 7,
310 .ranges = (struct rogue_bitrange []) {
311 { .start = 43, .num = 1, }, /* SB0(2) */
312 { .start = 52, .num = 1, }, /* SB0(1) */
313 { .start = 70, .num = 1, }, /* SB0(0) */
314 { .start = 47, .num = 3, }, /* S0(10..8) */
315 { .start = 41, .num = 1, }, /* S0(7) */
316 { .start = 50, .num = 1, }, /* S0(6) */
317 { .start = 69, .num = 6, }, /* S0(5..0) */
318 },
319 },
320 .encoder_fn = &rogue_encoder_reg_3_11,
321 },
322 {
323 .type = ROGUE_MAP_TYPE_OPERAND,
324 .index = 2,
325 .rangelist = {
326 .num_ranges = 5,
327 .ranges = (struct rogue_bitrange []) {
328 { .start = 51, .num = 1, }, /* SB1(1) */
329 { .start = 61, .num = 1, }, /* SB1(0) */
330 { .start = 40, .num = 1, }, /* S1(7) */
331 { .start = 49, .num = 2, }, /* S1(6..5) */
332 { .start = 60, .num = 5, }, /* S1(4..0) */
333 },
334 },
335 .encoder_fn = &rogue_encoder_reg_2_8,
336 },
337 },
338 },
339
340 [ROGUE_OP_PACK_U8888] = {
341 .num_bytes = 16,
342 .bytes = (uint8_t []) { 0x58, 0x92, 0x06, 0x9c, 0x20, 0x80, 0x00, 0x00, 0x00, 0x2c, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
343 .num_mappings = 2,
344 .mappings = (struct rogue_field_mapping []) {
345 /* Operand mappings. */
346 {
347 .type = ROGUE_MAP_TYPE_OPERAND,
348 .index = 0,
349 .rangelist = {
350 .num_ranges = 5,
351 .ranges = (struct rogue_bitrange []) {
352 { .start = 35, .num = 2, }, /* DBn(2..1) */
353 { .start = 46, .num = 1, }, /* DBn(0) */
354 { .start = 38, .num = 3, }, /* Dn(10..8) */
355 { .start = 33, .num = 2, }, /* Dn(7..6) */
356 { .start = 45, .num = 6, }, /* Dn(5..0) */
357 },
358 },
359 .encoder_fn = &rogue_encoder_reg_3_11,
360 },
361 {
362 .type = ROGUE_MAP_TYPE_OPERAND,
363 .index = 1,
364 .rangelist = {
365 .num_ranges = 5,
366 .ranges = (struct rogue_bitrange []) {
367 { .start = 75, .num = 2, }, /* SB0(2..1) */
368 { .start = 86, .num = 1, }, /* SB0(0) */
369 { .start = 66, .num = 3, }, /* S0(10..8) */
370 { .start = 73, .num = 2, }, /* S0(7..6) */
371 { .start = 85, .num = 6, }, /* S0(5..0) */
372 },
373 },
374 .encoder_fn = &rogue_encoder_reg_3_11,
375 },
376 },
377 },
378
379 [ROGUE_OP_MOV] = {
380 .num_bytes = 16,
381 .bytes = (uint8_t []) { 0x48, 0x42, 0xd0, 0x3f, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
382 .num_mappings = 3,
383 .mappings = (struct rogue_field_mapping []) {
384 /* Instruction flag mappings. */
385 {
386 .type = ROGUE_MAP_TYPE_INSTR_FLAG,
387 .index = ROGUE_INSTR_FLAG_OLCHK,
388 .rangelist = {
389 .num_ranges = 1,
390 .ranges = (struct rogue_bitrange []) {
391 { .start = 115, .num = 1, },
392 },
393 },
394 .encoder_fn = NULL,
395 },
396 /* Operand mappings. */
397 {
398 .type = ROGUE_MAP_TYPE_OPERAND,
399 .index = 0,
400 .rangelist = {
401 .num_ranges = 5,
402 .ranges = (struct rogue_bitrange []) {
403 { .start = 35, .num = 2, }, /* DBn(2..1) */
404 { .start = 46, .num = 1, }, /* DBn(0) */
405 { .start = 38, .num = 3, }, /* Dn(10..8) */
406 { .start = 33, .num = 2, }, /* Dn(7..6) */
407 { .start = 45, .num = 6, }, /* Dn(5..0) */
408 },
409 },
410 .encoder_fn = &rogue_encoder_reg_3_11,
411 },
412 {
413 .type = ROGUE_MAP_TYPE_OPERAND,
414 .index = 1,
415 .rangelist = {
416 .num_ranges = 5,
417 .ranges = (struct rogue_bitrange []) {
418 { .start = 75, .num = 2, }, /* SB0(2..1) */
419 { .start = 86, .num = 1, }, /* SB0(0) */
420 { .start = 66, .num = 3, }, /* S0(10..8) */
421 { .start = 73, .num = 2, }, /* S0(7..6) */
422 { .start = 85, .num = 6, }, /* S0(5..0) */
423 },
424 },
425 .encoder_fn = &rogue_encoder_reg_3_11,
426 },
427 },
428 },
429
430 [ROGUE_OP_MOV_IMM] = {
431 .num_bytes = 16,
432 .bytes = (uint8_t []) { 0x88, 0x92, 0x40, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
433 .num_mappings = 2,
434 .mappings = (struct rogue_field_mapping []) {
435 /* Operand mappings. */
436 {
437 .type = ROGUE_MAP_TYPE_OPERAND,
438 .index = 0,
439 .rangelist = {
440 .num_ranges = 5,
441 .ranges = (struct rogue_bitrange []) {
442 { .start = 35, .num = 2, }, /* DBn(2..1) */
443 { .start = 46, .num = 1, }, /* DBn(0) */
444 { .start = 38, .num = 3, }, /* Dn(10..8) */
445 { .start = 33, .num = 2, }, /* Dn(7..6) */
446 { .start = 45, .num = 6, }, /* Dn(5..0) */
447 },
448 },
449 .encoder_fn = &rogue_encoder_reg_3_11,
450 },
451 {
452 .type = ROGUE_MAP_TYPE_OPERAND,
453 .index = 1,
454 .rangelist = {
455 .num_ranges = 4,
456 .ranges = (struct rogue_bitrange []) {
457 { .start = 71, .num = 8, }, /* imm(31:24) */
458 { .start = 79, .num = 8, }, /* imm(23:16) */
459 { .start = 87, .num = 8, }, /* imm(15:8) */
460 { .start = 95, .num = 8, }, /* imm(7:0) */
461 },
462 },
463 .encoder_fn = &rogue_encoder_imm,
464 },
465 },
466 },
467
468 [ROGUE_OP_FMA] = {
469 .num_bytes = 16,
470 .bytes = (uint8_t []) { 0x28, 0x02, 0xd0, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xff, 0xf1, 0xff },
471 .num_mappings = 6,
472 .mappings = (struct rogue_field_mapping []) {
473 /* Instruction flag mappings. */
474 {
475 .type = ROGUE_MAP_TYPE_INSTR_FLAG,
476 .index = ROGUE_INSTR_FLAG_SAT,
477 .rangelist = {
478 .num_ranges = 1,
479 .ranges = (struct rogue_bitrange []) {
480 { .start = 104, .num = 1, },
481 },
482 },
483 .encoder_fn = NULL,
484 },
485 {
486 .type = ROGUE_MAP_TYPE_INSTR_FLAG,
487 .index = ROGUE_INSTR_FLAG_LP,
488 .rangelist = {
489 .num_ranges = 1,
490 .ranges = (struct rogue_bitrange []) {
491 { .start = 100, .num = 1, },
492 },
493 },
494 .encoder_fn = NULL,
495 },
496 /* Operand mappings. */
497 {
498 .type = ROGUE_MAP_TYPE_OPERAND,
499 .index = 0,
500 .rangelist = {
501 .num_ranges = 5,
502 .ranges = (struct rogue_bitrange []) {
503 { .start = 27, .num = 2, }, /* DBn(2..1) */
504 { .start = 38, .num = 1, }, /* DBn(0) */
505 { .start = 30, .num = 3, }, /* Dn(10..8) */
506 { .start = 25, .num = 2, }, /* Dn(7..6) */
507 { .start = 37, .num = 6, }, /* Dn(5..0) */
508 },
509 },
510 .encoder_fn = &rogue_encoder_reg_3_11,
511 },
512 {
513 .type = ROGUE_MAP_TYPE_OPERAND,
514 .index = 1,
515 .rangelist = {
516 .num_ranges = 6,
517 .ranges = (struct rogue_bitrange []) {
518 { .start = 59, .num = 1, }, /* SB0(2) */
519 { .start = 76, .num = 1, }, /* SB0(1) */
520 { .start = 94, .num = 1, }, /* SB0(0) */
521 { .start = 57, .num = 1, }, /* S0(7) */
522 { .start = 74, .num = 1, }, /* S0(6) */
523 { .start = 93, .num = 6, }, /* S0(5..0) */
524 },
525 },
526 .encoder_fn = &rogue_encoder_reg_3_8,
527 },
528 {
529 .type = ROGUE_MAP_TYPE_OPERAND,
530 .index = 2,
531 .rangelist = {
532 .num_ranges = 5,
533 .ranges = (struct rogue_bitrange []) {
534 { .start = 75, .num = 1, }, /* SB1(1) */
535 { .start = 85, .num = 1, }, /* SB1(0) */
536 { .start = 56, .num = 1, }, /* S1(7) */
537 { .start = 73, .num = 2, }, /* S1(6..5) */
538 { .start = 84, .num = 5, }, /* S1(4..0) */
539 },
540 },
541 .encoder_fn = &rogue_encoder_reg_2_8,
542 },
543 {
544 .type = ROGUE_MAP_TYPE_OPERAND,
545 .index = 3,
546 .rangelist = {
547 .num_ranges = 4,
548 .ranges = (struct rogue_bitrange []) {
549 { .start = 63, .num = 1, }, /* SB2(2) */
550 { .start = 71, .num = 2, }, /* SB2(1..0) */
551 { .start = 62, .num = 2, }, /* S2(7..6) */
552 { .start = 69, .num = 6, }, /* S2(5..0) */
553 },
554 },
555 .encoder_fn = &rogue_encoder_reg_3_8,
556 },
557 },
558 },
559
560 [ROGUE_OP_MUL] = {
561 .num_bytes = 16,
562 .bytes = (uint8_t []) { 0x28, 0x02, 0x40, 0x80, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xff, 0xf2, 0xff, 0xff, 0xff },
563 .num_mappings = 5,
564 .mappings = (struct rogue_field_mapping []) {
565 /* Instruction flag mappings. */
566 {
567 .type = ROGUE_MAP_TYPE_INSTR_FLAG,
568 .index = ROGUE_INSTR_FLAG_SAT,
569 .rangelist = {
570 .num_ranges = 1,
571 .ranges = (struct rogue_bitrange []) {
572 { .start = 108, .num = 1, },
573 },
574 },
575 .encoder_fn = NULL,
576 },
577 {
578 .type = ROGUE_MAP_TYPE_INSTR_FLAG,
579 .index = ROGUE_INSTR_FLAG_LP,
580 .rangelist = {
581 .num_ranges = 1,
582 .ranges = (struct rogue_bitrange []) {
583 { .start = 109, .num = 1, },
584 },
585 },
586 .encoder_fn = NULL,
587 },
588 /* Operand mappings. */
589 {
590 .type = ROGUE_MAP_TYPE_OPERAND,
591 .index = 0,
592 .rangelist = {
593 .num_ranges = 5,
594 .ranges = (struct rogue_bitrange []) {
595 { .start = 43, .num = 2, }, /* DBn(2..1) */
596 { .start = 54, .num = 1, }, /* DBn(0) */
597 { .start = 46, .num = 3, }, /* Dn(10..8) */
598 { .start = 41, .num = 2, }, /* Dn(7..6) */
599 { .start = 53, .num = 6, }, /* Dn(5..0) */
600 },
601 },
602 .encoder_fn = &rogue_encoder_reg_3_11,
603 },
604 {
605 .type = ROGUE_MAP_TYPE_OPERAND,
606 .index = 1,
607 .rangelist = {
608 .num_ranges = 7,
609 .ranges = (struct rogue_bitrange []) {
610 { .start = 75, .num = 1, }, /* SB0(2) */
611 { .start = 84, .num = 1, }, /* SB0(1) */
612 { .start = 102, .num = 1, }, /* SB0(0) */
613 { .start = 79, .num = 3, }, /* S0(10..8) */
614 { .start = 73, .num = 1, }, /* S0(7) */
615 { .start = 82, .num = 1, }, /* S0(6) */
616 { .start = 101, .num = 6, }, /* S0(5..0) */
617 },
618 },
619 .encoder_fn = &rogue_encoder_reg_3_11,
620 },
621 {
622 .type = ROGUE_MAP_TYPE_OPERAND,
623 .index = 2,
624 .rangelist = {
625 .num_ranges = 5,
626 .ranges = (struct rogue_bitrange []) {
627 { .start = 83, .num = 1, }, /* SB1(1) */
628 { .start = 93, .num = 1, }, /* SB1(0) */
629 { .start = 72, .num = 1, }, /* S1(7) */
630 { .start = 81, .num = 2, }, /* S1(6..5) */
631 { .start = 92, .num = 5, }, /* S1(4..0) */
632 },
633 },
634 .encoder_fn = &rogue_encoder_reg_2_8,
635 },
636 },
637 },
638
639 [ROGUE_OP_VTXOUT] = {
640 .num_bytes = 16,
641 .bytes = (uint8_t []) { 0x48, 0x20, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x30, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff },
642 .num_mappings = 2,
643 .mappings = (struct rogue_field_mapping []) {
644 /* Operand mappings. */
645 {
646 .type = ROGUE_MAP_TYPE_OPERAND,
647 .index = 0,
648 .rangelist = {
649 .num_ranges = 1,
650 .ranges = (struct rogue_bitrange []) {
651 { .start = 103, .num = 8, }, /* Immediate address. */
652 },
653 },
654 .encoder_fn = &rogue_encoder_imm,
655 },
656 {
657 .type = ROGUE_MAP_TYPE_OPERAND,
658 .index = 1,
659 .rangelist = {
660 .num_ranges = 5,
661 .ranges = (struct rogue_bitrange []) {
662 { .start = 83, .num = 2, }, /* SB0(2..1) */
663 { .start = 94, .num = 1, }, /* SB0(0) */
664 { .start = 74, .num = 3, }, /* S0(10..8) */
665 { .start = 81, .num = 2, }, /* S0(7..6) */
666 { .start = 93, .num = 6, }, /* S0(5..0) */
667 },
668 },
669 .encoder_fn = &rogue_encoder_reg_3_11,
670 },
671 },
672 },
673 };
674
675 /**
676 * \brief Applies a boolean flag encoding onto an instruction mask.
677 *
678 * \param[in] set Whether to set/unset the flag.
679 * \param[in] mapping The field mapping to apply.
680 * \param[in] instr_size The size of the instruction mask in bytes.
681 * \param[in] instr_bytes The instruction mask.
682 * \return true if encoding was successful.
683 */
rogue_encode_flag(bool set,const struct rogue_field_mapping * mapping,size_t instr_size,uint8_t instr_bytes[instr_size])684 static bool rogue_encode_flag(bool set,
685 const struct rogue_field_mapping *mapping,
686 size_t instr_size,
687 uint8_t instr_bytes[instr_size])
688 {
689 return rogue_distribute_value((uint64_t)set,
690 &mapping->rangelist,
691 instr_size,
692 instr_bytes);
693 }
694
695 /**
696 * \brief Applies an operand encoding onto an instruction mask.
697 *
698 * \param[in] operand The operand to apply.
699 * \param[in] mapping The field mapping to apply.
700 * \param[in] instr_size The size of the instruction mask in bytes.
701 * \param[in] instr_bytes The instruction mask.
702 * \return true if encoding was successful.
703 */
rogue_encode_operand(const struct rogue_operand * operand,const struct rogue_field_mapping * mapping,size_t instr_size,uint8_t instr_bytes[instr_size])704 static bool rogue_encode_operand(const struct rogue_operand *operand,
705 const struct rogue_field_mapping *mapping,
706 size_t instr_size,
707 uint8_t instr_bytes[instr_size])
708 {
709 uint64_t value = 0U;
710
711 switch (operand->type) {
712 case ROGUE_OPERAND_TYPE_REG_PIXEL_OUT:
713 CHECKF(
714 mapping->encoder_fn(&value,
715 2,
716 rogue_encode_reg_bank(operand),
717 operand->reg.number + ROGUE_PIXEL_OUT_REG_OFFSET),
718 "Failed to encode pixel output register operand.");
719 break;
720 case ROGUE_OPERAND_TYPE_REG_INTERNAL:
721 CHECKF(
722 mapping->encoder_fn(&value,
723 2,
724 rogue_encode_reg_bank(operand),
725 operand->reg.number + ROGUE_INTERNAL_REG_OFFSET),
726 "Failed to encode internal register operand.");
727 break;
728 case ROGUE_OPERAND_TYPE_REG_TEMP:
729 case ROGUE_OPERAND_TYPE_REG_COEFF:
730 case ROGUE_OPERAND_TYPE_REG_CONST:
731 case ROGUE_OPERAND_TYPE_REG_SHARED:
732 case ROGUE_OPERAND_TYPE_REG_VERTEX_IN:
733 CHECKF(mapping->encoder_fn(&value,
734 2,
735 rogue_encode_reg_bank(operand),
736 operand->reg.number),
737 "Failed to encode register operand.");
738 break;
739
740 case ROGUE_OPERAND_TYPE_IMMEDIATE:
741 CHECKF(mapping->encoder_fn(&value, 1, operand->immediate.value),
742 "Failed to encode immediate operand.");
743 break;
744
745 case ROGUE_OPERAND_TYPE_DRC:
746 CHECKF(mapping->encoder_fn(&value, 1, (uint64_t)operand->drc.number),
747 "Failed to encode DRC operand.");
748 break;
749
750 default:
751 return false;
752 }
753
754 CHECKF(rogue_distribute_value(value,
755 &mapping->rangelist,
756 instr_size,
757 instr_bytes),
758 "Failed to distribute value.");
759
760 return true;
761 }
762
763 /**
764 * \brief Applies operand and flag encodings to the base instruction bytes, then
765 * writes the result to file pointer "fp".
766 *
767 * \param[in] instr The instruction to be encoded.
768 * \param[in] fp The file pointer.
769 * \return true if encoding was successful.
770 */
rogue_encode_instr(const struct rogue_instr * instr,FILE * fp)771 bool rogue_encode_instr(const struct rogue_instr *instr, FILE *fp)
772 {
773 const struct rogue_instr_encoding *instr_encoding;
774 size_t instr_size;
775 uint8_t instr_bytes[ROGUE_MAX_INSTR_BYTES];
776
777 ASSERT_OPCODE_RANGE(instr->opcode);
778
779 instr_encoding = &instr_encodings[instr->opcode];
780
781 /* Set up base instruction bytes. */
782 instr_size = instr_encoding->num_bytes;
783 assert(instr_size <= ARRAY_SIZE(instr_bytes));
784 memcpy(instr_bytes, instr_encoding->bytes, instr_size);
785
786 /* Encode the operands and flags. */
787 for (size_t u = 0U; u < instr_encoding->num_mappings; ++u) {
788 const struct rogue_field_mapping *mapping = &instr_encoding->mappings[u];
789
790 switch (mapping->type) {
791 case ROGUE_MAP_TYPE_INSTR_FLAG: {
792 uint64_t flag = rogue_onehot(mapping->index);
793 CHECKF(rogue_encode_flag(!!(instr->flags & flag),
794 mapping,
795 instr_size,
796 instr_bytes),
797 "Failed to encode instruction flag.");
798 break;
799 }
800
801 case ROGUE_MAP_TYPE_OPERAND_FLAG:
802 return false;
803
804 case ROGUE_MAP_TYPE_OPERAND: {
805 size_t operand_index = mapping->index;
806 CHECKF(rogue_encode_operand(&instr->operands[operand_index],
807 mapping,
808 instr_size,
809 instr_bytes),
810 "Failed to encode instruction operand.");
811 break;
812 }
813
814 default:
815 return false;
816 }
817 }
818
819 CHECKF(fwrite(instr_bytes, 1, instr_size, fp) == instr_size,
820 "Failed to write encoded instruction bytes.");
821 fflush(fp);
822
823 return true;
824 }
825
826 /**
827 * \brief Encodes each instruction in "shader", writing the output to "fp".
828 *
829 * \param[in] shader The shader to be encoded.
830 * \param[in] fp The file pointer.
831 * \return true if encoding was successful.
832 */
rogue_encode_shader(const struct rogue_shader * shader,FILE * fp)833 bool rogue_encode_shader(const struct rogue_shader *shader, FILE *fp)
834 {
835 long bytes_written;
836
837 /* Encode each instruction. */
838 foreach_instr (instr, &shader->instr_list)
839 CHECKF(rogue_encode_instr(instr, fp), "Failed to encode instruction.");
840
841 /* Pad end of shader if required. */
842 bytes_written = ftell(fp);
843 if (bytes_written <= 0)
844 return false;
845
846 /* FIXME: Figure out the define for alignment of 16. */
847 for (size_t u = 0; u < (bytes_written % 16); ++u)
848 fputc(0xff, fp);
849
850 return true;
851 }
852