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