2
* Copyright © 2022 Imagination Technologies Ltd.
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:
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
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
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"
39
static size_t rogue_encode_reg_bank(const struct rogue_operand *operand)
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:
46
case ROGUE_OPERAND_TYPE_REG_TEMP:
48
case ROGUE_OPERAND_TYPE_REG_VERTEX_IN:
50
case ROGUE_OPERAND_TYPE_REG_COEFF:
52
case ROGUE_OPERAND_TYPE_REG_SHARED:
58
unreachable("Unimplemented register bank.");
62
* \brief Field mapping type.
65
ROGUE_MAP_TYPE_INSTR_FLAG = 0,
66
ROGUE_MAP_TYPE_OPERAND_FLAG,
67
ROGUE_MAP_TYPE_OPERAND,
73
* \brief Field mapping rule description.
75
struct rogue_field_mapping {
76
/* Type of mapping being performed. */
77
enum rogue_map_type type;
79
/* Index of the source operand/flag being mapped. */
82
/* List of ranges to perform mapping. */
83
struct rogue_rangelist rangelist;
85
/* Function used to encode the input into the value to be mapped. */
86
field_encoder_t encoder_fn;
90
* \brief Instruction encoding rule description.
92
struct rogue_instr_encoding {
93
/* Number of bytes making up the base mask. */
95
/* Base mask bytes. */
98
/* Number of field mappings for this instruction. */
100
/* Field mappings. */
101
struct rogue_field_mapping *mappings;
105
struct rogue_instr_encoding instr_encodings[ROGUE_OP_COUNT] = {
108
.bytes = (uint8_t []) { 0x04, 0x80, 0x6e, 0x00, 0xf2, 0xff, 0xff, 0xff },
111
[ROGUE_OP_END_FRAG] = {
113
.bytes = (uint8_t []) { 0x04, 0x80, 0xee, 0x00, 0xf2, 0xff, 0xff, 0xff },
116
[ROGUE_OP_END_VERT] = {
118
.bytes = (uint8_t []) { 0x44, 0xa0, 0x80, 0x05, 0x00, 0x00, 0x00, 0xff },
123
.bytes = (uint8_t []) { 0x04, 0x80, 0x6a, 0xff, 0xf2, 0xff, 0xff, 0xff },
125
.mappings = (struct rogue_field_mapping []) {
127
.type = ROGUE_MAP_TYPE_OPERAND,
131
.ranges = (struct rogue_bitrange []) {
132
{ .start = 47, .num = 1, },
135
.encoder_fn = &rogue_encoder_drc,
140
[ROGUE_OP_PIX_ITER_W] = {
142
.bytes = (uint8_t []) { 0x48, 0x20, 0xb0, 0x01, 0x80, 0x40, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xff },
144
.mappings = (struct rogue_field_mapping []) {
145
/* Instruction flag mappings. */
147
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
148
.index = ROGUE_INSTR_FLAG_SAT,
151
.ranges = (struct rogue_bitrange []) {
152
{ .start = 100, .num = 1, },
157
/* Operand mappings. */
159
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
171
.encoder_fn = &rogue_encoder_reg_3_11,
174
.type = ROGUE_MAP_TYPE_OPERAND,
178
.ranges = (struct rogue_bitrange []) {
179
{ .start = 59, .num = 1, },
182
.encoder_fn = &rogue_encoder_drc,
185
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
198
.encoder_fn = &rogue_encoder_reg_3_8,
201
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
212
.encoder_fn = &rogue_encoder_reg_3_8,
215
.type = ROGUE_MAP_TYPE_OPERAND,
219
.ranges = (struct rogue_bitrange []) {
220
{ .start = 99, .num = 4, },
223
.encoder_fn = &rogue_encoder_ls_1_16,
230
.bytes = (uint8_t []) { 0x68, 0x42, 0xd0, 0x3c, 0xfa, 0x10, 0x87, 0x80, 0xc0, 0x80, 0x10, 0x00, 0x32, 0x80, 0x00, 0xff },
232
.mappings = (struct rogue_field_mapping []) {
233
/* Operand mappings. */
235
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
247
.encoder_fn = &rogue_encoder_reg_3_11,
250
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
264
.encoder_fn = &rogue_encoder_reg_3_11,
267
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
279
.encoder_fn = &rogue_encoder_reg_2_8,
286
.bytes = (uint8_t []) { 0x68, 0x42, 0xd0, 0x3c, 0xf0, 0x11, 0x87, 0x80, 0xc0, 0x80, 0x10, 0x00, 0x32, 0x80, 0x00, 0xff },
288
.mappings = (struct rogue_field_mapping []) {
289
/* Operand mappings. */
291
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
303
.encoder_fn = &rogue_encoder_reg_3_11,
306
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
320
.encoder_fn = &rogue_encoder_reg_3_11,
323
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
335
.encoder_fn = &rogue_encoder_reg_2_8,
340
[ROGUE_OP_PACK_U8888] = {
342
.bytes = (uint8_t []) { 0x58, 0x92, 0x06, 0x9c, 0x20, 0x80, 0x00, 0x00, 0x00, 0x2c, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
344
.mappings = (struct rogue_field_mapping []) {
345
/* Operand mappings. */
347
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
359
.encoder_fn = &rogue_encoder_reg_3_11,
362
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
374
.encoder_fn = &rogue_encoder_reg_3_11,
381
.bytes = (uint8_t []) { 0x48, 0x42, 0xd0, 0x3f, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
383
.mappings = (struct rogue_field_mapping []) {
384
/* Instruction flag mappings. */
386
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
387
.index = ROGUE_INSTR_FLAG_OLCHK,
390
.ranges = (struct rogue_bitrange []) {
391
{ .start = 115, .num = 1, },
396
/* Operand mappings. */
398
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
410
.encoder_fn = &rogue_encoder_reg_3_11,
413
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
425
.encoder_fn = &rogue_encoder_reg_3_11,
430
[ROGUE_OP_MOV_IMM] = {
432
.bytes = (uint8_t []) { 0x88, 0x92, 0x40, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
434
.mappings = (struct rogue_field_mapping []) {
435
/* Operand mappings. */
437
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
449
.encoder_fn = &rogue_encoder_reg_3_11,
452
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
463
.encoder_fn = &rogue_encoder_imm,
470
.bytes = (uint8_t []) { 0x28, 0x02, 0xd0, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xff, 0xf1, 0xff },
472
.mappings = (struct rogue_field_mapping []) {
473
/* Instruction flag mappings. */
475
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
476
.index = ROGUE_INSTR_FLAG_SAT,
479
.ranges = (struct rogue_bitrange []) {
480
{ .start = 104, .num = 1, },
486
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
487
.index = ROGUE_INSTR_FLAG_LP,
490
.ranges = (struct rogue_bitrange []) {
491
{ .start = 100, .num = 1, },
496
/* Operand mappings. */
498
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
510
.encoder_fn = &rogue_encoder_reg_3_11,
513
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
526
.encoder_fn = &rogue_encoder_reg_3_8,
529
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
541
.encoder_fn = &rogue_encoder_reg_2_8,
544
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
555
.encoder_fn = &rogue_encoder_reg_3_8,
562
.bytes = (uint8_t []) { 0x28, 0x02, 0x40, 0x80, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xff, 0xf2, 0xff, 0xff, 0xff },
564
.mappings = (struct rogue_field_mapping []) {
565
/* Instruction flag mappings. */
567
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
568
.index = ROGUE_INSTR_FLAG_SAT,
571
.ranges = (struct rogue_bitrange []) {
572
{ .start = 108, .num = 1, },
578
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
579
.index = ROGUE_INSTR_FLAG_LP,
582
.ranges = (struct rogue_bitrange []) {
583
{ .start = 109, .num = 1, },
588
/* Operand mappings. */
590
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
602
.encoder_fn = &rogue_encoder_reg_3_11,
605
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
619
.encoder_fn = &rogue_encoder_reg_3_11,
622
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
634
.encoder_fn = &rogue_encoder_reg_2_8,
639
[ROGUE_OP_VTXOUT] = {
641
.bytes = (uint8_t []) { 0x48, 0x20, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x30, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff },
643
.mappings = (struct rogue_field_mapping []) {
644
/* Operand mappings. */
646
.type = ROGUE_MAP_TYPE_OPERAND,
650
.ranges = (struct rogue_bitrange []) {
651
{ .start = 103, .num = 8, }, /* Immediate address. */
654
.encoder_fn = &rogue_encoder_imm,
657
.type = ROGUE_MAP_TYPE_OPERAND,
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) */
669
.encoder_fn = &rogue_encoder_reg_3_11,
676
* \brief Applies a boolean flag encoding onto an instruction mask.
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.
684
static bool rogue_encode_flag(bool set,
685
const struct rogue_field_mapping *mapping,
687
uint8_t instr_bytes[instr_size])
689
return rogue_distribute_value((uint64_t)set,
696
* \brief Applies an operand encoding onto an instruction mask.
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.
704
static bool rogue_encode_operand(const struct rogue_operand *operand,
705
const struct rogue_field_mapping *mapping,
707
uint8_t instr_bytes[instr_size])
711
switch (operand->type) {
712
case ROGUE_OPERAND_TYPE_REG_PIXEL_OUT:
714
mapping->encoder_fn(&value,
716
rogue_encode_reg_bank(operand),
717
operand->reg.number + ROGUE_PIXEL_OUT_REG_OFFSET),
718
"Failed to encode pixel output register operand.");
720
case ROGUE_OPERAND_TYPE_REG_INTERNAL:
722
mapping->encoder_fn(&value,
724
rogue_encode_reg_bank(operand),
725
operand->reg.number + ROGUE_INTERNAL_REG_OFFSET),
726
"Failed to encode internal register operand.");
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,
735
rogue_encode_reg_bank(operand),
736
operand->reg.number),
737
"Failed to encode register operand.");
740
case ROGUE_OPERAND_TYPE_IMMEDIATE:
741
CHECKF(mapping->encoder_fn(&value, 1, operand->immediate.value),
742
"Failed to encode immediate operand.");
745
case ROGUE_OPERAND_TYPE_DRC:
746
CHECKF(mapping->encoder_fn(&value, 1, (uint64_t)operand->drc.number),
747
"Failed to encode DRC operand.");
754
CHECKF(rogue_distribute_value(value,
758
"Failed to distribute value.");
764
* \brief Applies operand and flag encodings to the base instruction bytes, then
765
* writes the result to file pointer "fp".
767
* \param[in] instr The instruction to be encoded.
768
* \param[in] fp The file pointer.
769
* \return true if encoding was successful.
771
bool rogue_encode_instr(const struct rogue_instr *instr, FILE *fp)
773
const struct rogue_instr_encoding *instr_encoding;
775
uint8_t instr_bytes[ROGUE_MAX_INSTR_BYTES];
777
ASSERT_OPCODE_RANGE(instr->opcode);
779
instr_encoding = &instr_encodings[instr->opcode];
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);
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];
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),
797
"Failed to encode instruction flag.");
801
case ROGUE_MAP_TYPE_OPERAND_FLAG:
804
case ROGUE_MAP_TYPE_OPERAND: {
805
size_t operand_index = mapping->index;
806
CHECKF(rogue_encode_operand(&instr->operands[operand_index],
810
"Failed to encode instruction operand.");
819
CHECKF(fwrite(instr_bytes, 1, instr_size, fp) == instr_size,
820
"Failed to write encoded instruction bytes.");
827
* \brief Encodes each instruction in "shader", writing the output to "fp".
829
* \param[in] shader The shader to be encoded.
830
* \param[in] fp The file pointer.
831
* \return true if encoding was successful.
833
bool rogue_encode_shader(const struct rogue_shader *shader, FILE *fp)
837
/* Encode each instruction. */
838
foreach_instr (instr, &shader->instr_list)
839
CHECKF(rogue_encode_instr(instr, fp), "Failed to encode instruction.");
841
/* Pad end of shader if required. */
842
bytes_written = ftell(fp);
843
if (bytes_written <= 0)
846
/* FIXME: Figure out the define for alignment of 16. */
847
for (size_t u = 0; u < (bytes_written % 16); ++u)