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
39static 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 */
64enum 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 */
75struct 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 */
92struct 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
104static const
105struct 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 */
684static 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 */
704static 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 */
771bool 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 */
833bool 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