• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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