1 /* 2 * Copyright (c) 2013 Rob Clark <robclark (at) freedesktop.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is 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 18 * THE 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 %code requires { 25 #include "ir3/ir3_assembler.h" 26 #include "ir3/ir3_shader.h" 27 28 struct ir3 * ir3_parse(struct ir3_shader_variant *v, 29 struct ir3_kernel_info *k, FILE *f); 30 } 31 32 %{ 33 #define YYDEBUG 0 34 35 #include <stdlib.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <math.h> 39 40 #include "util/half_float.h" 41 #include "util/u_math.h" 42 43 #include "ir3/ir3.h" 44 #include "ir3/ir3_shader.h" 45 #include "ir3/instr-a3xx.h" 46 47 #include "ir3_parser.h" 48 49 #define swap(a, b) \ 50 do { __typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) 51 52 /* ir3 treats the abs/neg flags as separate flags for float vs integer, 53 * but in the instruction encoding they are the same thing. Tracking 54 * them separately is only for the benefit of ir3 opt passes, and not 55 * required here, so just use the float versions: 56 */ 57 #define IR3_REG_ABS IR3_REG_FABS 58 #define IR3_REG_NEGATE IR3_REG_FNEG 59 60 static struct ir3_kernel_info *info; 61 static struct ir3_shader_variant *variant; 62 /* NOTE the assembler doesn't really use the ir3_block construction 63 * like the compiler does. Everything is treated as one large block. 64 * Which might happen to contain flow control. But since we don't 65 * use any of the ir3 backend passes (sched, RA, etc) this doesn't 66 * really matter. 67 */ 68 static struct ir3_block *block; /* current shader block */ 69 static struct ir3_instruction *instr; /* current instruction */ 70 static unsigned ip; /* current instruction pointer */ 71 static struct hash_table *labels; 72 73 void *ir3_parser_dead_ctx; 74 75 static struct { 76 unsigned flags; 77 unsigned repeat; 78 unsigned nop; 79 } iflags; 80 81 static struct { 82 unsigned flags; 83 unsigned wrmask; 84 } rflags; 85 86 int ir3_yyget_lineno(void); 87 88 static void new_label(const char *name) 89 { 90 ralloc_steal(labels, (void *) name); 91 _mesa_hash_table_insert(labels, name, (void *)(uintptr_t)ip); 92 } 93 94 static struct ir3_instruction * new_instr(opc_t opc) 95 { 96 instr = ir3_instr_create(block, opc, 4, 6); 97 instr->flags = iflags.flags; 98 instr->repeat = iflags.repeat; 99 instr->nop = iflags.nop; 100 instr->line = ir3_yyget_lineno(); 101 iflags.flags = iflags.repeat = iflags.nop = 0; 102 ip++; 103 return instr; 104 } 105 106 static void new_shader(void) 107 { 108 variant->ir = ir3_create(variant->shader->compiler, variant); 109 block = ir3_block_create(variant->ir); 110 list_addtail(&block->node, &variant->ir->block_list); 111 ip = 0; 112 labels = _mesa_hash_table_create(variant, _mesa_hash_string, _mesa_key_string_equal); 113 ir3_parser_dead_ctx = ralloc_context(NULL); 114 } 115 116 static type_t parse_type(const char **type) 117 { 118 if (!strncmp("f16", *type, 3)) { 119 *type += 3; 120 return TYPE_F16; 121 } else if (!strncmp("f32", *type, 3)) { 122 *type += 3; 123 return TYPE_F32; 124 } else if (!strncmp("u16", *type, 3)) { 125 *type += 3; 126 return TYPE_U16; 127 } else if (!strncmp("u32", *type, 3)) { 128 *type += 3; 129 return TYPE_U32; 130 } else if (!strncmp("s16", *type, 3)) { 131 *type += 3; 132 return TYPE_S16; 133 } else if (!strncmp("s32", *type, 3)) { 134 *type += 3; 135 return TYPE_S32; 136 } else if (!strncmp("u8", *type, 2)) { 137 *type += 2; 138 return TYPE_U8; 139 } else if (!strncmp("s8", *type, 2)) { 140 *type += 2; 141 return TYPE_S8; 142 } else { 143 assert(0); /* shouldn't get here */ 144 return ~0; 145 } 146 } 147 148 static struct ir3_instruction * parse_type_type(struct ir3_instruction *instr, 149 const char *type_type) 150 { 151 instr->cat1.src_type = parse_type(&type_type); 152 instr->cat1.dst_type = parse_type(&type_type); 153 return instr; 154 } 155 156 static struct ir3_register * new_src(int num, unsigned flags) 157 { 158 struct ir3_register *reg; 159 flags |= rflags.flags; 160 if (num & 0x1) 161 flags |= IR3_REG_HALF; 162 reg = ir3_src_create(instr, num>>1, flags); 163 reg->wrmask = MAX2(1, rflags.wrmask); 164 rflags.flags = rflags.wrmask = 0; 165 return reg; 166 } 167 168 static struct ir3_register * new_dst(int num, unsigned flags) 169 { 170 struct ir3_register *reg; 171 flags |= rflags.flags; 172 if (num & 0x1) 173 flags |= IR3_REG_HALF; 174 reg = ir3_dst_create(instr, num>>1, flags); 175 reg->wrmask = MAX2(1, rflags.wrmask); 176 rflags.flags = rflags.wrmask = 0; 177 return reg; 178 } 179 180 static struct ir3_register * dummy_dst(void) 181 { 182 return new_dst(0, 0); 183 } 184 185 static void fixup_cat5_s2en(void) 186 { 187 assert(opc_cat(instr->opc) == 5); 188 if (!(instr->flags & IR3_INSTR_S2EN)) 189 return; 190 /* For various reasons (ie. mainly to make the .s2en src easier to 191 * find, given that various different cat5 tex instructions can have 192 * different # of src registers), in ir3 the samp/tex src register 193 * is first, rather than last. So we have to detect this case and 194 * fix things up. 195 */ 196 struct ir3_register *s2en_src = instr->srcs[instr->srcs_count - 1]; 197 198 if (instr->flags & IR3_INSTR_B) 199 assert(!(s2en_src->flags & IR3_REG_HALF)); 200 else 201 assert(s2en_src->flags & IR3_REG_HALF); 202 203 for (int i = 0; i < instr->srcs_count - 1; i++) { 204 instr->srcs[i+1] = instr->srcs[i]; 205 } 206 instr->srcs[0] = s2en_src; 207 } 208 209 static void add_const(unsigned reg, unsigned c0, unsigned c1, unsigned c2, unsigned c3) 210 { 211 struct ir3_const_state *const_state = ir3_const_state(variant); 212 assert((reg & 0x7) == 0); 213 int idx = reg >> (1 + 2); /* low bit is half vs full, next two bits are swiz */ 214 if (idx * 4 + 4 > const_state->immediates_size) { 215 const_state->immediates = rerzalloc(const_state, 216 const_state->immediates, 217 __typeof__(const_state->immediates[0]), 218 const_state->immediates_size, 219 idx * 4 + 4); 220 for (unsigned i = const_state->immediates_size; i < idx * 4; i++) 221 const_state->immediates[i] = 0xd0d0d0d0; 222 const_state->immediates_size = const_state->immediates_count = idx * 4 + 4; 223 } 224 const_state->immediates[idx * 4 + 0] = c0; 225 const_state->immediates[idx * 4 + 1] = c1; 226 const_state->immediates[idx * 4 + 2] = c2; 227 const_state->immediates[idx * 4 + 3] = c3; 228 } 229 230 static void add_sysval(unsigned reg, unsigned compmask, gl_system_value sysval) 231 { 232 unsigned n = variant->inputs_count++; 233 variant->inputs[n].regid = reg; 234 variant->inputs[n].sysval = true; 235 variant->inputs[n].slot = sysval; 236 variant->inputs[n].compmask = compmask; 237 variant->total_in++; 238 } 239 240 static bool resolve_labels(void) 241 { 242 int instr_ip = 0; 243 foreach_instr (instr, &block->instr_list) { 244 if (opc_cat(instr->opc) == 0 && instr->cat0.target_label) { 245 struct hash_entry *entry = _mesa_hash_table_search(labels, instr->cat0.target_label); 246 if (!entry) { 247 fprintf(stderr, "unknown label %s\n", instr->cat0.target_label); 248 return false; 249 } 250 int target_ip = (uintptr_t)entry->data; 251 instr->cat0.immed = target_ip - instr_ip; 252 } 253 instr_ip++; 254 } 255 return true; 256 } 257 258 #ifdef YYDEBUG 259 int yydebug; 260 #endif 261 262 extern int yylex(void); 263 void ir3_yyset_lineno(int _line_number); 264 void ir3_yyset_input(FILE *f); 265 266 int yyparse(void); 267 268 static void yyerror(const char *error) 269 { 270 fprintf(stderr, "error at line %d: %s\n", ir3_yyget_lineno(), error); 271 } 272 273 struct ir3 * ir3_parse(struct ir3_shader_variant *v, 274 struct ir3_kernel_info *k, FILE *f) 275 { 276 ir3_yyset_lineno(1); 277 ir3_yyset_input(f); 278 #ifdef YYDEBUG 279 yydebug = 1; 280 #endif 281 info = k; 282 variant = v; 283 if (yyparse() || !resolve_labels()) { 284 ir3_destroy(variant->ir); 285 variant->ir = NULL; 286 } 287 ralloc_free(labels); 288 ralloc_free(ir3_parser_dead_ctx); 289 return variant->ir; 290 } 291 %} 292 293 %union { 294 int tok; 295 int num; 296 uint32_t unum; 297 double flt; 298 const char *str; 299 struct ir3_register *reg; 300 struct { 301 int start; 302 int num; 303 } range; 304 type_t type; 305 } 306 307 %{ 308 #if YYDEBUG 309 static void print_token(FILE *file, int type, YYSTYPE value) 310 { 311 fprintf(file, "\ntype: %d\n", type); 312 } 313 314 #define YYPRINT(file, type, value) print_token(file, type, value) 315 #endif 316 %} 317 318 %token <num> T_INT 319 %token <unum> T_HEX 320 %token <flt> T_FLOAT 321 %token <str> T_IDENTIFIER 322 %token <num> T_REGISTER 323 %token <num> T_CONSTANT 324 325 /* @ headers (@const/@sampler/@uniform/@varying) */ 326 %token <tok> T_A_LOCALSIZE 327 %token <tok> T_A_CONST 328 %token <tok> T_A_BUF 329 %token <tok> T_A_INVOCATIONID 330 %token <tok> T_A_WGID 331 %token <tok> T_A_NUMWG 332 %token <tok> T_A_BRANCHSTACK 333 %token <tok> T_A_IN 334 %token <tok> T_A_OUT 335 %token <tok> T_A_TEX 336 %token <tok> T_A_PVTMEM 337 /* todo, re-add @sampler/@uniform/@varying if needed someday */ 338 339 /* src register flags */ 340 %token <tok> T_ABSNEG 341 %token <tok> T_NEG 342 %token <tok> T_ABS 343 %token <tok> T_R 344 345 %token <tok> T_HR 346 %token <tok> T_HC 347 348 /* dst register flags */ 349 %token <tok> T_EVEN 350 %token <tok> T_POS_INFINITY 351 %token <tok> T_NEG_INFINITY 352 %token <tok> T_EI 353 %token <num> T_WRMASK 354 355 /* Float LUT values accepted as immed: */ 356 %token <num> T_FLUT_0_0 357 %token <num> T_FLUT_0_5 358 %token <num> T_FLUT_1_0 359 %token <num> T_FLUT_2_0 360 %token <num> T_FLUT_E 361 %token <num> T_FLUT_PI 362 %token <num> T_FLUT_INV_PI 363 %token <num> T_FLUT_INV_LOG2_E 364 %token <num> T_FLUT_LOG2_E 365 %token <num> T_FLUT_INV_LOG2_10 366 %token <num> T_FLUT_LOG2_10 367 %token <num> T_FLUT_4_0 368 369 /* instruction flags */ 370 %token <tok> T_SY 371 %token <tok> T_SS 372 %token <tok> T_JP 373 %token <tok> T_SAT 374 %token <num> T_RPT 375 %token <tok> T_UL 376 %token <tok> T_NOP 377 378 /* category 0: */ 379 %token <tok> T_OP_NOP 380 %token <tok> T_OP_BR 381 %token <tok> T_OP_BRAO 382 %token <tok> T_OP_BRAA 383 %token <tok> T_OP_BRAC 384 %token <tok> T_OP_BANY 385 %token <tok> T_OP_BALL 386 %token <tok> T_OP_BRAX 387 %token <tok> T_OP_JUMP 388 %token <tok> T_OP_CALL 389 %token <tok> T_OP_RET 390 %token <tok> T_OP_KILL 391 %token <tok> T_OP_END 392 %token <tok> T_OP_EMIT 393 %token <tok> T_OP_CUT 394 %token <tok> T_OP_CHMASK 395 %token <tok> T_OP_CHSH 396 %token <tok> T_OP_FLOW_REV 397 %token <tok> T_OP_BKT 398 %token <tok> T_OP_STKS 399 %token <tok> T_OP_STKR 400 %token <tok> T_OP_XSET 401 %token <tok> T_OP_XCLR 402 %token <tok> T_OP_GETONE 403 %token <tok> T_OP_DBG 404 %token <tok> T_OP_SHPS 405 %token <tok> T_OP_SHPE 406 %token <tok> T_OP_PREDT 407 %token <tok> T_OP_PREDF 408 %token <tok> T_OP_PREDE 409 410 /* category 1: */ 411 %token <tok> T_OP_MOVMSK 412 %token <tok> T_OP_MOVA1 413 %token <tok> T_OP_MOVA 414 %token <tok> T_OP_MOV 415 %token <tok> T_OP_COV 416 %token <tok> T_OP_SWZ 417 %token <tok> T_OP_GAT 418 %token <tok> T_OP_SCT 419 420 /* category 2: */ 421 %token <tok> T_OP_ADD_F 422 %token <tok> T_OP_MIN_F 423 %token <tok> T_OP_MAX_F 424 %token <tok> T_OP_MUL_F 425 %token <tok> T_OP_SIGN_F 426 %token <tok> T_OP_CMPS_F 427 %token <tok> T_OP_ABSNEG_F 428 %token <tok> T_OP_CMPV_F 429 %token <tok> T_OP_FLOOR_F 430 %token <tok> T_OP_CEIL_F 431 %token <tok> T_OP_RNDNE_F 432 %token <tok> T_OP_RNDAZ_F 433 %token <tok> T_OP_TRUNC_F 434 %token <tok> T_OP_ADD_U 435 %token <tok> T_OP_ADD_S 436 %token <tok> T_OP_SUB_U 437 %token <tok> T_OP_SUB_S 438 %token <tok> T_OP_CMPS_U 439 %token <tok> T_OP_CMPS_S 440 %token <tok> T_OP_MIN_U 441 %token <tok> T_OP_MIN_S 442 %token <tok> T_OP_MAX_U 443 %token <tok> T_OP_MAX_S 444 %token <tok> T_OP_ABSNEG_S 445 %token <tok> T_OP_AND_B 446 %token <tok> T_OP_OR_B 447 %token <tok> T_OP_NOT_B 448 %token <tok> T_OP_XOR_B 449 %token <tok> T_OP_CMPV_U 450 %token <tok> T_OP_CMPV_S 451 %token <tok> T_OP_MUL_U24 452 %token <tok> T_OP_MUL_S24 453 %token <tok> T_OP_MULL_U 454 %token <tok> T_OP_BFREV_B 455 %token <tok> T_OP_CLZ_S 456 %token <tok> T_OP_CLZ_B 457 %token <tok> T_OP_SHL_B 458 %token <tok> T_OP_SHR_B 459 %token <tok> T_OP_ASHR_B 460 %token <tok> T_OP_BARY_F 461 %token <tok> T_OP_MGEN_B 462 %token <tok> T_OP_GETBIT_B 463 %token <tok> T_OP_SETRM 464 %token <tok> T_OP_CBITS_B 465 %token <tok> T_OP_SHB 466 %token <tok> T_OP_MSAD 467 468 /* category 3: */ 469 %token <tok> T_OP_MAD_U16 470 %token <tok> T_OP_MADSH_U16 471 %token <tok> T_OP_MAD_S16 472 %token <tok> T_OP_MADSH_M16 473 %token <tok> T_OP_MAD_U24 474 %token <tok> T_OP_MAD_S24 475 %token <tok> T_OP_MAD_F16 476 %token <tok> T_OP_MAD_F32 477 %token <tok> T_OP_SEL_B16 478 %token <tok> T_OP_SEL_B32 479 %token <tok> T_OP_SEL_S16 480 %token <tok> T_OP_SEL_S32 481 %token <tok> T_OP_SEL_F16 482 %token <tok> T_OP_SEL_F32 483 %token <tok> T_OP_SAD_S16 484 %token <tok> T_OP_SAD_S32 485 %token <tok> T_OP_SHLG_B16 486 487 /* category 4: */ 488 %token <tok> T_OP_RCP 489 %token <tok> T_OP_RSQ 490 %token <tok> T_OP_LOG2 491 %token <tok> T_OP_EXP2 492 %token <tok> T_OP_SIN 493 %token <tok> T_OP_COS 494 %token <tok> T_OP_SQRT 495 %token <tok> T_OP_HRSQ 496 %token <tok> T_OP_HLOG2 497 %token <tok> T_OP_HEXP2 498 499 /* category 5: */ 500 %token <tok> T_OP_ISAM 501 %token <tok> T_OP_ISAML 502 %token <tok> T_OP_ISAMM 503 %token <tok> T_OP_SAM 504 %token <tok> T_OP_SAMB 505 %token <tok> T_OP_SAML 506 %token <tok> T_OP_SAMGQ 507 %token <tok> T_OP_GETLOD 508 %token <tok> T_OP_CONV 509 %token <tok> T_OP_CONVM 510 %token <tok> T_OP_GETSIZE 511 %token <tok> T_OP_GETBUF 512 %token <tok> T_OP_GETPOS 513 %token <tok> T_OP_GETINFO 514 %token <tok> T_OP_DSX 515 %token <tok> T_OP_DSY 516 %token <tok> T_OP_GATHER4R 517 %token <tok> T_OP_GATHER4G 518 %token <tok> T_OP_GATHER4B 519 %token <tok> T_OP_GATHER4A 520 %token <tok> T_OP_SAMGP0 521 %token <tok> T_OP_SAMGP1 522 %token <tok> T_OP_SAMGP2 523 %token <tok> T_OP_SAMGP3 524 %token <tok> T_OP_DSXPP_1 525 %token <tok> T_OP_DSYPP_1 526 %token <tok> T_OP_RGETPOS 527 %token <tok> T_OP_RGETINFO 528 529 /* category 6: */ 530 %token <tok> T_OP_LDG 531 %token <tok> T_OP_LDG_A 532 %token <tok> T_OP_LDL 533 %token <tok> T_OP_LDP 534 %token <tok> T_OP_STG 535 %token <tok> T_OP_STG_A 536 %token <tok> T_OP_STL 537 %token <tok> T_OP_STP 538 %token <tok> T_OP_LDIB 539 %token <tok> T_OP_G2L 540 %token <tok> T_OP_L2G 541 %token <tok> T_OP_PREFETCH 542 %token <tok> T_OP_LDLW 543 %token <tok> T_OP_STLW 544 %token <tok> T_OP_RESFMT 545 %token <tok> T_OP_RESINFO 546 %token <tok> T_OP_ATOMIC_ADD 547 %token <tok> T_OP_ATOMIC_SUB 548 %token <tok> T_OP_ATOMIC_XCHG 549 %token <tok> T_OP_ATOMIC_INC 550 %token <tok> T_OP_ATOMIC_DEC 551 %token <tok> T_OP_ATOMIC_CMPXCHG 552 %token <tok> T_OP_ATOMIC_MIN 553 %token <tok> T_OP_ATOMIC_MAX 554 %token <tok> T_OP_ATOMIC_AND 555 %token <tok> T_OP_ATOMIC_OR 556 %token <tok> T_OP_ATOMIC_XOR 557 %token <tok> T_OP_RESINFO_B 558 %token <tok> T_OP_LDIB_B 559 %token <tok> T_OP_STIB_B 560 %token <tok> T_OP_ATOMIC_B_ADD 561 %token <tok> T_OP_ATOMIC_B_SUB 562 %token <tok> T_OP_ATOMIC_B_XCHG 563 %token <tok> T_OP_ATOMIC_B_INC 564 %token <tok> T_OP_ATOMIC_B_DEC 565 %token <tok> T_OP_ATOMIC_B_CMPXCHG 566 %token <tok> T_OP_ATOMIC_B_MIN 567 %token <tok> T_OP_ATOMIC_B_MAX 568 %token <tok> T_OP_ATOMIC_B_AND 569 %token <tok> T_OP_ATOMIC_B_OR 570 %token <tok> T_OP_ATOMIC_B_XOR 571 %token <tok> T_OP_LDGB 572 %token <tok> T_OP_STGB 573 %token <tok> T_OP_STIB 574 %token <tok> T_OP_LDC 575 %token <tok> T_OP_LDLV 576 %token <tok> T_OP_GETSPID 577 %token <tok> T_OP_GETWID 578 579 /* category 7: */ 580 %token <tok> T_OP_BAR 581 %token <tok> T_OP_FENCE 582 583 /* type qualifiers: */ 584 %token <tok> T_TYPE_F16 585 %token <tok> T_TYPE_F32 586 %token <tok> T_TYPE_U16 587 %token <tok> T_TYPE_U32 588 %token <tok> T_TYPE_S16 589 %token <tok> T_TYPE_S32 590 %token <tok> T_TYPE_U8 591 %token <tok> T_TYPE_S8 592 593 %token <tok> T_UNTYPED 594 %token <tok> T_TYPED 595 596 %token <tok> T_1D 597 %token <tok> T_2D 598 %token <tok> T_3D 599 %token <tok> T_4D 600 601 /* condition qualifiers: */ 602 %token <tok> T_LT 603 %token <tok> T_LE 604 %token <tok> T_GT 605 %token <tok> T_GE 606 %token <tok> T_EQ 607 %token <tok> T_NE 608 609 %token <tok> T_S2EN 610 %token <tok> T_SAMP 611 %token <tok> T_TEX 612 %token <tok> T_BASE 613 %token <tok> T_OFFSET 614 %token <tok> T_UNIFORM 615 %token <tok> T_NONUNIFORM 616 %token <tok> T_IMM 617 618 %token <tok> T_NAN 619 %token <tok> T_INF 620 %token <num> T_A0 621 %token <num> T_A1 622 %token <num> T_P0 623 %token <num> T_W 624 %token <str> T_CAT1_TYPE_TYPE 625 626 %type <num> integer offset 627 %type <num> flut_immed 628 %type <flt> float 629 %type <reg> src dst const 630 %type <tok> cat1_opc 631 %type <tok> cat2_opc_1src cat2_opc_2src_cnd cat2_opc_2src 632 %type <tok> cat3_opc 633 %type <tok> cat4_opc 634 %type <tok> cat5_opc cat5_samp cat5_tex cat5_type 635 %type <type> type 636 %type <unum> const_val 637 638 %error-verbose 639 640 %start shader 641 642 %% 643 644 shader: { new_shader(); } headers instrs 645 646 headers: 647 | header headers 648 649 header: localsize_header 650 | const_header 651 | buf_header 652 | invocationid_header 653 | wgid_header 654 | numwg_header 655 | branchstack_header 656 | in_header 657 | out_header 658 | tex_header 659 | pvtmem_header 660 661 const_val: T_FLOAT { $$ = fui($1); } 662 | T_INT { $$ = $1; } 663 | '-' T_INT { $$ = -$2; } 664 | T_HEX { $$ = $1; } 665 666 localsize_header: T_A_LOCALSIZE const_val ',' const_val ',' const_val { 667 variant->local_size[0] = $2; 668 variant->local_size[1] = $4; 669 variant->local_size[2] = $6; 670 } 671 672 const_header: T_A_CONST '(' T_CONSTANT ')' const_val ',' const_val ',' const_val ',' const_val { 673 add_const($3, $5, $7, $9, $11); 674 } 675 676 buf_header_addr_reg: 677 '(' T_CONSTANT ')' { 678 assert(($2 & 0x1) == 0); /* half-reg not allowed */ 679 unsigned reg = $2 >> 1; 680 681 info->buf_addr_regs[info->num_bufs - 1] = reg; 682 /* reserve space in immediates for the actual value to be plugged in later: */ 683 add_const($2, 0, 0, 0, 0); 684 } 685 | 686 687 buf_header: T_A_BUF const_val { 688 int idx = info->num_bufs++; 689 assert(idx < MAX_BUFS); 690 info->buf_sizes[idx] = $2; 691 } buf_header_addr_reg 692 693 invocationid_header: T_A_INVOCATIONID '(' T_REGISTER ')' { 694 assert(($3 & 0x1) == 0); /* half-reg not allowed */ 695 unsigned reg = $3 >> 1; 696 add_sysval(reg, 0x7, SYSTEM_VALUE_LOCAL_INVOCATION_ID); 697 } 698 699 wgid_header: T_A_WGID '(' T_REGISTER ')' { 700 assert(($3 & 0x1) == 0); /* half-reg not allowed */ 701 unsigned reg = $3 >> 1; 702 assert(variant->shader->compiler->gen >= 5); 703 assert(reg >= regid(48, 0)); /* must be a high reg */ 704 add_sysval(reg, 0x7, SYSTEM_VALUE_WORKGROUP_ID); 705 } 706 | T_A_WGID '(' T_CONSTANT ')' { 707 assert(($3 & 0x1) == 0); /* half-reg not allowed */ 708 unsigned reg = $3 >> 1; 709 assert(variant->shader->compiler->gen < 5); 710 info->wgid = reg; 711 } 712 713 numwg_header: T_A_NUMWG '(' T_CONSTANT ')' { 714 assert(($3 & 0x1) == 0); /* half-reg not allowed */ 715 unsigned reg = $3 >> 1; 716 info->numwg = reg; 717 /* reserve space in immediates for the actual value to be plugged in later: */ 718 if (variant->shader->compiler->gen >= 5) 719 add_const($3, 0, 0, 0, 0); 720 } 721 722 branchstack_header: T_A_BRANCHSTACK const_val { variant->branchstack = $2; } 723 724 pvtmem_header: T_A_PVTMEM const_val { variant->pvtmem_size = $2; } 725 726 /* Stubs for now */ 727 in_header: T_A_IN '(' T_REGISTER ')' T_IDENTIFIER '(' T_IDENTIFIER '=' integer ')' { } 728 729 out_header: T_A_OUT '(' T_REGISTER ')' T_IDENTIFIER '(' T_IDENTIFIER '=' integer ')' { } 730 731 tex_header: T_A_TEX '(' T_REGISTER ')' 732 T_IDENTIFIER '=' integer ',' /* src */ 733 T_IDENTIFIER '=' integer ',' /* samp */ 734 T_IDENTIFIER '=' integer ',' /* tex */ 735 T_IDENTIFIER '=' integer ',' /* wrmask */ 736 T_IDENTIFIER '=' integer /* cmd */ { } 737 738 iflag: T_SY { iflags.flags |= IR3_INSTR_SY; } 739 | T_SS { iflags.flags |= IR3_INSTR_SS; } 740 | T_JP { iflags.flags |= IR3_INSTR_JP; } 741 | T_SAT { iflags.flags |= IR3_INSTR_SAT; } 742 | T_RPT { iflags.repeat = $1; } 743 | T_UL { iflags.flags |= IR3_INSTR_UL; } 744 | T_NOP { iflags.nop = $1; } 745 746 iflags: 747 | iflag iflags 748 749 instrs: instr instrs 750 | instr 751 752 instr: iflags cat0_instr 753 | iflags cat1_instr 754 | iflags cat2_instr 755 | iflags cat3_instr 756 | iflags cat4_instr 757 | iflags cat5_instr { fixup_cat5_s2en(); } 758 | iflags cat6_instr 759 | iflags cat7_instr 760 | label 761 762 label: T_IDENTIFIER ':' { new_label($1); } 763 764 cat0_src1: '!' T_P0 { instr->cat0.inv1 = true; instr->cat0.comp1 = $2 >> 1; } 765 | T_P0 { instr->cat0.comp1 = $1 >> 1; } 766 767 cat0_src2: '!' T_P0 { instr->cat0.inv2 = true; instr->cat0.comp2 = $2 >> 1; } 768 | T_P0 { instr->cat0.comp2 = $1 >> 1; } 769 770 cat0_immed: '#' integer { instr->cat0.immed = $2; } 771 | '#' T_IDENTIFIER { ralloc_steal(instr, (void *)$2); instr->cat0.target_label = $2; } 772 773 cat0_instr: T_OP_NOP { new_instr(OPC_NOP); } 774 | T_OP_BR { new_instr(OPC_B)->cat0.brtype = BRANCH_PLAIN; } cat0_src1 ',' cat0_immed 775 | T_OP_BRAO { new_instr(OPC_B)->cat0.brtype = BRANCH_OR; } cat0_src1 ',' cat0_src2 ',' cat0_immed 776 | T_OP_BRAA { new_instr(OPC_B)->cat0.brtype = BRANCH_AND; } cat0_src1 ',' cat0_src2 ',' cat0_immed 777 | T_OP_BRAC '.' integer { new_instr(OPC_B)->cat0.brtype = BRANCH_CONST; instr->cat0.idx = $3; } cat0_immed 778 | T_OP_BANY { new_instr(OPC_B)->cat0.brtype = BRANCH_ANY; } cat0_src1 ',' cat0_immed 779 | T_OP_BALL { new_instr(OPC_B)->cat0.brtype = BRANCH_ALL; } cat0_src1 ',' cat0_immed 780 | T_OP_BRAX { new_instr(OPC_B)->cat0.brtype = BRANCH_X; } cat0_immed 781 | T_OP_JUMP { new_instr(OPC_JUMP); } cat0_immed 782 | T_OP_CALL { new_instr(OPC_CALL); } cat0_immed 783 | T_OP_RET { new_instr(OPC_RET); } 784 | T_OP_KILL { new_instr(OPC_KILL); } cat0_src1 785 | T_OP_END { new_instr(OPC_END); } 786 | T_OP_EMIT { new_instr(OPC_EMIT); } 787 | T_OP_CUT { new_instr(OPC_CUT); } 788 | T_OP_CHMASK { new_instr(OPC_CHMASK); } 789 | T_OP_CHSH { new_instr(OPC_CHSH); } 790 | T_OP_FLOW_REV { new_instr(OPC_FLOW_REV); } 791 | T_OP_BKT { new_instr(OPC_BKT); } cat0_immed 792 | T_OP_STKS { new_instr(OPC_STKS); } 793 | T_OP_STKR { new_instr(OPC_STKR); } 794 | T_OP_XSET { new_instr(OPC_XSET); } 795 | T_OP_XCLR { new_instr(OPC_XCLR); } 796 | T_OP_GETONE { new_instr(OPC_GETONE); } cat0_immed 797 | T_OP_DBG { new_instr(OPC_DBG); } 798 | T_OP_SHPS { new_instr(OPC_SHPS); } cat0_immed 799 | T_OP_SHPE { new_instr(OPC_SHPE); } 800 | T_OP_PREDT { new_instr(OPC_PREDT); } cat0_src1 801 | T_OP_PREDF { new_instr(OPC_PREDF); } cat0_src1 802 | T_OP_PREDE { new_instr(OPC_PREDE); } 803 804 cat1_opc: T_OP_MOV '.' T_CAT1_TYPE_TYPE { 805 parse_type_type(new_instr(OPC_MOV), $3); 806 } 807 | T_OP_COV '.' T_CAT1_TYPE_TYPE { 808 parse_type_type(new_instr(OPC_MOV), $3); 809 } 810 811 cat1_src: src_reg_or_const_or_rel 812 | immediate_cat1 813 814 cat1_movmsk: T_OP_MOVMSK '.' T_W { 815 new_instr(OPC_MOVMSK); 816 instr->cat1.src_type = TYPE_U32; 817 instr->cat1.dst_type = TYPE_U32; 818 instr->repeat = $3 - 1; 819 } dst_reg { 820 instr->dsts[0]->wrmask = (1 << $3) - 1; 821 } 822 823 cat1_mova1: T_OP_MOVA1 T_A1 ',' { 824 new_instr(OPC_MOV); 825 instr->cat1.src_type = TYPE_U16; 826 instr->cat1.dst_type = TYPE_U16; 827 new_dst((61 << 3) + 2, IR3_REG_HALF); 828 } cat1_src 829 830 cat1_mova: T_OP_MOVA T_A0 ',' { 831 new_instr(OPC_MOV); 832 instr->cat1.src_type = TYPE_S16; 833 instr->cat1.dst_type = TYPE_S16; 834 new_dst((61 << 3), IR3_REG_HALF); 835 } cat1_src 836 837 cat1_swz: T_OP_SWZ '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_SWZ), $3); } dst_reg ',' dst_reg ',' src_reg ',' src_reg 838 839 cat1_gat: T_OP_GAT '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_GAT), $3); } dst_reg ',' src_reg ',' src_reg ',' src_reg ',' src_reg 840 841 cat1_sct: T_OP_SCT '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_SCT), $3); } dst_reg ',' dst_reg ',' dst_reg ',' dst_reg ',' src_reg 842 843 /* NOTE: cat1 can also *write* to relative gpr */ 844 cat1_instr: cat1_movmsk 845 | cat1_mova1 846 | cat1_mova 847 | cat1_swz 848 | cat1_gat 849 | cat1_sct 850 | cat1_opc dst_reg ',' cat1_src 851 | cat1_opc relative_gpr_dst ',' cat1_src 852 853 cat2_opc_1src: T_OP_ABSNEG_F { new_instr(OPC_ABSNEG_F); } 854 | T_OP_ABSNEG_S { new_instr(OPC_ABSNEG_S); } 855 | T_OP_CLZ_B { new_instr(OPC_CLZ_B); } 856 | T_OP_CLZ_S { new_instr(OPC_CLZ_S); } 857 | T_OP_SIGN_F { new_instr(OPC_SIGN_F); } 858 | T_OP_FLOOR_F { new_instr(OPC_FLOOR_F); } 859 | T_OP_CEIL_F { new_instr(OPC_CEIL_F); } 860 | T_OP_RNDNE_F { new_instr(OPC_RNDNE_F); } 861 | T_OP_RNDAZ_F { new_instr(OPC_RNDAZ_F); } 862 | T_OP_TRUNC_F { new_instr(OPC_TRUNC_F); } 863 | T_OP_NOT_B { new_instr(OPC_NOT_B); } 864 | T_OP_BFREV_B { new_instr(OPC_BFREV_B); } 865 | T_OP_SETRM { new_instr(OPC_SETRM); } 866 | T_OP_CBITS_B { new_instr(OPC_CBITS_B); } 867 868 cat2_opc_2src_cnd: T_OP_CMPS_F { new_instr(OPC_CMPS_F); } 869 | T_OP_CMPS_U { new_instr(OPC_CMPS_U); } 870 | T_OP_CMPS_S { new_instr(OPC_CMPS_S); } 871 | T_OP_CMPV_F { new_instr(OPC_CMPV_F); } 872 | T_OP_CMPV_U { new_instr(OPC_CMPV_U); } 873 | T_OP_CMPV_S { new_instr(OPC_CMPV_S); } 874 875 cat2_opc_2src: T_OP_ADD_F { new_instr(OPC_ADD_F); } 876 | T_OP_MIN_F { new_instr(OPC_MIN_F); } 877 | T_OP_MAX_F { new_instr(OPC_MAX_F); } 878 | T_OP_MUL_F { new_instr(OPC_MUL_F); } 879 | T_OP_ADD_U { new_instr(OPC_ADD_U); } 880 | T_OP_ADD_S { new_instr(OPC_ADD_S); } 881 | T_OP_SUB_U { new_instr(OPC_SUB_U); } 882 | T_OP_SUB_S { new_instr(OPC_SUB_S); } 883 | T_OP_MIN_U { new_instr(OPC_MIN_U); } 884 | T_OP_MIN_S { new_instr(OPC_MIN_S); } 885 | T_OP_MAX_U { new_instr(OPC_MAX_U); } 886 | T_OP_MAX_S { new_instr(OPC_MAX_S); } 887 | T_OP_AND_B { new_instr(OPC_AND_B); } 888 | T_OP_OR_B { new_instr(OPC_OR_B); } 889 | T_OP_XOR_B { new_instr(OPC_XOR_B); } 890 | T_OP_MUL_U24 { new_instr(OPC_MUL_U24); } 891 | T_OP_MUL_S24 { new_instr(OPC_MUL_S24); } 892 | T_OP_MULL_U { new_instr(OPC_MULL_U); } 893 | T_OP_SHL_B { new_instr(OPC_SHL_B); } 894 | T_OP_SHR_B { new_instr(OPC_SHR_B); } 895 | T_OP_ASHR_B { new_instr(OPC_ASHR_B); } 896 | T_OP_BARY_F { new_instr(OPC_BARY_F); } 897 | T_OP_MGEN_B { new_instr(OPC_MGEN_B); } 898 | T_OP_GETBIT_B { new_instr(OPC_GETBIT_B); } 899 | T_OP_SHB { new_instr(OPC_SHB); } 900 | T_OP_MSAD { new_instr(OPC_MSAD); } 901 902 cond: T_LT { instr->cat2.condition = IR3_COND_LT; } 903 | T_LE { instr->cat2.condition = IR3_COND_LE; } 904 | T_GT { instr->cat2.condition = IR3_COND_GT; } 905 | T_GE { instr->cat2.condition = IR3_COND_GE; } 906 | T_EQ { instr->cat2.condition = IR3_COND_EQ; } 907 | T_NE { instr->cat2.condition = IR3_COND_NE; } 908 909 cat2_instr: cat2_opc_1src dst_reg ',' src_reg_or_const_or_rel_or_imm 910 | cat2_opc_2src_cnd '.' cond dst_reg ',' src_reg_or_const_or_rel_or_imm ',' src_reg_or_const_or_rel_or_imm 911 | cat2_opc_2src dst_reg ',' src_reg_or_const_or_rel_or_imm ',' src_reg_or_const_or_rel_or_imm 912 913 cat3_opc: T_OP_MAD_U16 { new_instr(OPC_MAD_U16); } 914 | T_OP_MADSH_U16 { new_instr(OPC_MADSH_U16); } 915 | T_OP_MAD_S16 { new_instr(OPC_MAD_S16); } 916 | T_OP_MADSH_M16 { new_instr(OPC_MADSH_M16); } 917 | T_OP_MAD_U24 { new_instr(OPC_MAD_U24); } 918 | T_OP_MAD_S24 { new_instr(OPC_MAD_S24); } 919 | T_OP_MAD_F16 { new_instr(OPC_MAD_F16); } 920 | T_OP_MAD_F32 { new_instr(OPC_MAD_F32); } 921 | T_OP_SEL_B16 { new_instr(OPC_SEL_B16); } 922 | T_OP_SEL_B32 { new_instr(OPC_SEL_B32); } 923 | T_OP_SEL_S16 { new_instr(OPC_SEL_S16); } 924 | T_OP_SEL_S32 { new_instr(OPC_SEL_S32); } 925 | T_OP_SEL_F16 { new_instr(OPC_SEL_F16); } 926 | T_OP_SEL_F32 { new_instr(OPC_SEL_F32); } 927 | T_OP_SAD_S16 { new_instr(OPC_SAD_S16); } 928 | T_OP_SAD_S32 { new_instr(OPC_SAD_S32); } 929 930 cat3_instr: cat3_opc dst_reg ',' src_reg_or_const_or_rel ',' src_reg_or_const ',' src_reg_or_const_or_rel 931 | T_OP_SHLG_B16 { new_instr(OPC_SHLG_B16); } dst_reg ',' src_reg_or_rel_or_imm ',' src_reg_or_const ',' src_reg_or_rel_or_imm 932 933 cat4_opc: T_OP_RCP { new_instr(OPC_RCP); } 934 | T_OP_RSQ { new_instr(OPC_RSQ); } 935 | T_OP_LOG2 { new_instr(OPC_LOG2); } 936 | T_OP_EXP2 { new_instr(OPC_EXP2); } 937 | T_OP_SIN { new_instr(OPC_SIN); } 938 | T_OP_COS { new_instr(OPC_COS); } 939 | T_OP_SQRT { new_instr(OPC_SQRT); } 940 | T_OP_HRSQ { new_instr(OPC_HRSQ); } 941 | T_OP_HLOG2 { new_instr(OPC_HLOG2); } 942 | T_OP_HEXP2 { new_instr(OPC_HEXP2); } 943 944 cat4_instr: cat4_opc dst_reg ',' src_reg_or_const_or_rel_or_imm 945 946 cat5_opc_dsxypp: T_OP_DSXPP_1 { new_instr(OPC_DSXPP_1)->cat5.type = TYPE_F32; } 947 | T_OP_DSYPP_1 { new_instr(OPC_DSYPP_1)->cat5.type = TYPE_F32; } 948 949 cat5_opc: T_OP_ISAM { new_instr(OPC_ISAM); } 950 | T_OP_ISAML { new_instr(OPC_ISAML); } 951 | T_OP_ISAMM { new_instr(OPC_ISAMM); } 952 | T_OP_SAM { new_instr(OPC_SAM); } 953 | T_OP_SAMB { new_instr(OPC_SAMB); } 954 | T_OP_SAML { new_instr(OPC_SAML); } 955 | T_OP_SAMGQ { new_instr(OPC_SAMGQ); } 956 | T_OP_GETLOD { new_instr(OPC_GETLOD); } 957 | T_OP_CONV { new_instr(OPC_CONV); } 958 | T_OP_CONVM { new_instr(OPC_CONVM); } 959 | T_OP_GETSIZE { new_instr(OPC_GETSIZE); } 960 | T_OP_GETBUF { new_instr(OPC_GETBUF); } 961 | T_OP_GETPOS { new_instr(OPC_GETPOS); } 962 | T_OP_GETINFO { new_instr(OPC_GETINFO); } 963 | T_OP_DSX { new_instr(OPC_DSX); } 964 | T_OP_DSY { new_instr(OPC_DSY); } 965 | T_OP_GATHER4R { new_instr(OPC_GATHER4R); } 966 | T_OP_GATHER4G { new_instr(OPC_GATHER4G); } 967 | T_OP_GATHER4B { new_instr(OPC_GATHER4B); } 968 | T_OP_GATHER4A { new_instr(OPC_GATHER4A); } 969 | T_OP_SAMGP0 { new_instr(OPC_SAMGP0); } 970 | T_OP_SAMGP1 { new_instr(OPC_SAMGP1); } 971 | T_OP_SAMGP2 { new_instr(OPC_SAMGP2); } 972 | T_OP_SAMGP3 { new_instr(OPC_SAMGP3); } 973 | T_OP_RGETPOS { new_instr(OPC_RGETPOS); } 974 | T_OP_RGETINFO { new_instr(OPC_RGETINFO); } 975 976 cat5_flag: '.' T_3D { instr->flags |= IR3_INSTR_3D; } 977 | '.' 'a' { instr->flags |= IR3_INSTR_A; } 978 | '.' 'o' { instr->flags |= IR3_INSTR_O; } 979 | '.' 'p' { instr->flags |= IR3_INSTR_P; } 980 | '.' 's' { instr->flags |= IR3_INSTR_S; } 981 | '.' T_S2EN { instr->flags |= IR3_INSTR_S2EN; } 982 | '.' T_NONUNIFORM { instr->flags |= IR3_INSTR_NONUNIF; } 983 | '.' T_BASE { instr->flags |= IR3_INSTR_B; instr->cat5.tex_base = $2; } 984 cat5_flags: 985 | cat5_flag cat5_flags 986 987 cat5_samp: T_SAMP { instr->cat5.samp = $1; } 988 cat5_tex: T_TEX { if (instr->flags & IR3_INSTR_B) instr->cat5.samp |= ($1 << 4); else instr->cat5.tex = $1; } 989 cat5_type: '(' type ')' { instr->cat5.type = $2; } 990 cat5_a1: src_reg { instr->flags |= IR3_INSTR_A1EN; } 991 992 cat5_instr: cat5_opc_dsxypp cat5_flags dst_reg ',' src_reg 993 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' src_reg ',' src_reg 994 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' src_reg ',' cat5_samp ',' cat5_tex 995 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' src_reg ',' cat5_samp 996 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' src_reg ',' cat5_tex 997 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' src_reg 998 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' cat5_samp ',' cat5_tex 999 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' cat5_samp ',' cat5_a1 1000 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' cat5_samp 1001 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' cat5_tex 1002 | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg 1003 | cat5_opc cat5_flags cat5_type dst_reg ',' cat5_samp ',' cat5_tex 1004 | cat5_opc cat5_flags cat5_type dst_reg ',' cat5_samp 1005 | cat5_opc cat5_flags cat5_type dst_reg ',' cat5_tex 1006 | cat5_opc cat5_flags cat5_type dst_reg 1007 1008 cat6_typed: '.' T_UNTYPED { instr->cat6.typed = 0; } 1009 | '.' T_TYPED { instr->cat6.typed = 1; } 1010 1011 cat6_dim: '.' T_1D { instr->cat6.d = 1; } 1012 | '.' T_2D { instr->cat6.d = 2; } 1013 | '.' T_3D { instr->cat6.d = 3; } 1014 | '.' T_4D { instr->cat6.d = 4; } 1015 1016 cat6_type: '.' type { instr->cat6.type = $2; } 1017 cat6_imm_offset: offset { new_src(0, IR3_REG_IMMED)->iim_val = $1; } 1018 cat6_offset: cat6_imm_offset 1019 | '+' src 1020 cat6_dst_offset: offset { instr->cat6.dst_offset = $1; } 1021 | '+' src { instr->flags |= IR3_INSTR_G; } 1022 1023 cat6_immed: integer { instr->cat6.iim_val = $1; } 1024 1025 cat6_stg_ldg_a6xx_offset: 1026 '+' '(' src offset ')' '<' '<' integer { 1027 assert($8 == 2); 1028 new_src(0, IR3_REG_IMMED)->uim_val = 0; 1029 new_src(0, IR3_REG_IMMED)->uim_val = $4; 1030 } 1031 | '+' src '<' '<' integer offset '<' '<' integer { 1032 assert($9 == 2); 1033 new_src(0, IR3_REG_IMMED)->uim_val = $5 - 2; 1034 new_src(0, IR3_REG_IMMED)->uim_val = $6; 1035 } 1036 1037 cat6_load: T_OP_LDG { new_instr(OPC_LDG); } cat6_type dst_reg ',' 'g' '[' src cat6_offset ']' ',' immediate 1038 | T_OP_LDG_A { new_instr(OPC_LDG_A); } cat6_type dst_reg ',' 'g' '[' src cat6_stg_ldg_a6xx_offset ']' ',' immediate 1039 | T_OP_LDP { new_instr(OPC_LDP); } cat6_type dst_reg ',' 'p' '[' src cat6_offset ']' ',' immediate 1040 | T_OP_LDL { new_instr(OPC_LDL); } cat6_type dst_reg ',' 'l' '[' src cat6_offset ']' ',' immediate 1041 | T_OP_LDLW { new_instr(OPC_LDLW); } cat6_type dst_reg ',' 'l' '[' src cat6_offset ']' ',' immediate 1042 | T_OP_LDLV { new_instr(OPC_LDLV); } cat6_type dst_reg ',' 'l' '[' integer ']' { 1043 new_src(0, IR3_REG_IMMED)->iim_val = $8; 1044 } ',' immediate 1045 1046 cat6_store: T_OP_STG { new_instr(OPC_STG); dummy_dst(); } cat6_type 'g' '[' src cat6_imm_offset ']' ',' src ',' immediate 1047 | T_OP_STG_A { new_instr(OPC_STG_A); dummy_dst(); } cat6_type 'g' '[' src cat6_stg_ldg_a6xx_offset ']' ',' src ',' immediate 1048 | T_OP_STP { new_instr(OPC_STP); dummy_dst(); } cat6_type 'p' '[' src cat6_dst_offset ']' ',' src ',' immediate 1049 | T_OP_STL { new_instr(OPC_STL); dummy_dst(); } cat6_type 'l' '[' src cat6_dst_offset ']' ',' src ',' immediate 1050 | T_OP_STLW { new_instr(OPC_STLW); dummy_dst(); } cat6_type 'l' '[' src cat6_dst_offset ']' ',' src ',' immediate 1051 1052 cat6_loadib: T_OP_LDIB { new_instr(OPC_LDIB); } cat6_typed cat6_dim cat6_type '.' cat6_immed dst_reg ',' 'g' '[' immediate ']' ',' src ',' src 1053 cat6_storeib: T_OP_STIB { new_instr(OPC_STIB); dummy_dst(); } cat6_typed cat6_dim cat6_type '.' cat6_immed'g' '[' immediate ']' ',' src ',' src ',' src 1054 1055 cat6_prefetch: T_OP_PREFETCH { new_instr(OPC_PREFETCH); new_dst(0,0); /* dummy dst */ } 'g' '[' src cat6_offset ']' ',' cat6_immed 1056 1057 cat6_atomic_opc: T_OP_ATOMIC_ADD { new_instr(OPC_ATOMIC_ADD); } 1058 | T_OP_ATOMIC_SUB { new_instr(OPC_ATOMIC_SUB); } 1059 | T_OP_ATOMIC_XCHG { new_instr(OPC_ATOMIC_XCHG); } 1060 | T_OP_ATOMIC_INC { new_instr(OPC_ATOMIC_INC); } 1061 | T_OP_ATOMIC_DEC { new_instr(OPC_ATOMIC_DEC); } 1062 | T_OP_ATOMIC_CMPXCHG { new_instr(OPC_ATOMIC_CMPXCHG); } 1063 | T_OP_ATOMIC_MIN { new_instr(OPC_ATOMIC_MIN); } 1064 | T_OP_ATOMIC_MAX { new_instr(OPC_ATOMIC_MAX); } 1065 | T_OP_ATOMIC_AND { new_instr(OPC_ATOMIC_AND); } 1066 | T_OP_ATOMIC_OR { new_instr(OPC_ATOMIC_OR); } 1067 | T_OP_ATOMIC_XOR { new_instr(OPC_ATOMIC_XOR); } 1068 1069 cat6_atomic_g: cat6_atomic_opc cat6_typed cat6_dim cat6_type '.' cat6_immed '.' 'g' dst_reg ',' 'g' '[' cat6_reg_or_immed ']' ',' src ',' src ',' src { 1070 instr->flags |= IR3_INSTR_G; 1071 } 1072 1073 cat6_atomic_l: cat6_atomic_opc cat6_typed cat6_dim cat6_type '.' cat6_immed '.' 'l' dst_reg ',' 'l' '[' cat6_reg_or_immed ']' ',' src 1074 1075 cat6_atomic: cat6_atomic_g 1076 | cat6_atomic_l 1077 1078 cat6_ibo_opc_1src: T_OP_RESINFO { new_instr(OPC_RESINFO); } 1079 1080 cat6_ibo_opc_ldgb: T_OP_LDGB { new_instr(OPC_LDGB); } 1081 cat6_ibo_opc_stgb: T_OP_STGB { new_instr(OPC_STGB); } 1082 1083 cat6_ibo: cat6_ibo_opc_1src cat6_type cat6_dim dst_reg ',' 'g' '[' cat6_reg_or_immed ']' 1084 | cat6_ibo_opc_ldgb cat6_typed cat6_dim cat6_type '.' cat6_immed dst_reg ',' 'g' '[' cat6_reg_or_immed ']' ',' src ',' src 1085 | cat6_ibo_opc_stgb cat6_typed cat6_dim cat6_type '.' cat6_immed { dummy_dst(); } 'g' '[' cat6_reg_or_immed ']' ',' src ',' cat6_reg_or_immed ',' src 1086 1087 cat6_id_opc: 1088 T_OP_GETSPID { new_instr(OPC_GETSPID); } 1089 | T_OP_GETWID { new_instr(OPC_GETWID); } 1090 1091 cat6_id: cat6_id_opc cat6_type dst_reg 1092 1093 cat6_bindless_base: 1094 | '.' T_BASE { instr->flags |= IR3_INSTR_B; instr->cat6.base = $2; } 1095 1096 cat6_bindless_mode: T_IMM cat6_bindless_base 1097 | T_UNIFORM cat6_bindless_base 1098 | T_NONUNIFORM cat6_bindless_base { instr->flags |= IR3_INSTR_NONUNIF; } 1099 1100 cat6_reg_or_immed: src 1101 | integer { new_src(0, IR3_REG_IMMED)->iim_val = $1; } 1102 1103 cat6_bindless_ibo_opc_1src: T_OP_RESINFO_B { new_instr(OPC_RESINFO); } 1104 1105 cat6_bindless_ibo_opc_2src: T_OP_ATOMIC_B_ADD { new_instr(OPC_ATOMIC_ADD)->flags |= IR3_INSTR_G; dummy_dst(); } 1106 | T_OP_ATOMIC_B_SUB { new_instr(OPC_ATOMIC_SUB)->flags |= IR3_INSTR_G; dummy_dst(); } 1107 | T_OP_ATOMIC_B_XCHG { new_instr(OPC_ATOMIC_XCHG)->flags |= IR3_INSTR_G; dummy_dst(); } 1108 | T_OP_ATOMIC_B_INC { new_instr(OPC_ATOMIC_INC)->flags |= IR3_INSTR_G; dummy_dst(); } 1109 | T_OP_ATOMIC_B_DEC { new_instr(OPC_ATOMIC_DEC)->flags |= IR3_INSTR_G; dummy_dst(); } 1110 | T_OP_ATOMIC_B_CMPXCHG { new_instr(OPC_ATOMIC_CMPXCHG)->flags |= IR3_INSTR_G; dummy_dst(); } 1111 | T_OP_ATOMIC_B_MIN { new_instr(OPC_ATOMIC_MIN)->flags |= IR3_INSTR_G; dummy_dst(); } 1112 | T_OP_ATOMIC_B_MAX { new_instr(OPC_ATOMIC_MAX)->flags |= IR3_INSTR_G; dummy_dst(); } 1113 | T_OP_ATOMIC_B_AND { new_instr(OPC_ATOMIC_AND)->flags |= IR3_INSTR_G; dummy_dst(); } 1114 | T_OP_ATOMIC_B_OR { new_instr(OPC_ATOMIC_OR)->flags |= IR3_INSTR_G; dummy_dst(); } 1115 | T_OP_ATOMIC_B_XOR { new_instr(OPC_ATOMIC_XOR)->flags |= IR3_INSTR_G; dummy_dst(); } 1116 | T_OP_STIB_B { new_instr(OPC_STIB); dummy_dst(); } 1117 1118 cat6_bindless_ibo_opc_2src_dst: T_OP_LDIB_B { new_instr(OPC_LDIB); } 1119 1120 cat6_bindless_ibo: cat6_bindless_ibo_opc_1src cat6_typed cat6_dim cat6_type '.' cat6_immed '.' cat6_bindless_mode dst_reg ',' cat6_reg_or_immed 1121 | cat6_bindless_ibo_opc_2src cat6_typed cat6_dim cat6_type '.' cat6_immed '.' cat6_bindless_mode src_reg ',' cat6_reg_or_immed ',' cat6_reg_or_immed { swap(instr->srcs[0], instr->srcs[2]); } 1122 | cat6_bindless_ibo_opc_2src_dst cat6_typed cat6_dim cat6_type '.' cat6_immed '.' cat6_bindless_mode dst_reg ',' cat6_reg_or_immed ',' cat6_reg_or_immed { swap(instr->srcs[0], instr->srcs[1]); } 1123 1124 cat6_bindless_ldc_opc: T_OP_LDC { new_instr(OPC_LDC); } 1125 1126 cat6_bindless_ldc: cat6_bindless_ldc_opc '.' T_OFFSET '.' cat6_immed '.' cat6_bindless_mode dst_reg ',' cat6_reg_or_immed ',' cat6_reg_or_immed { 1127 instr->cat6.d = $3; 1128 instr->cat6.type = TYPE_U32; 1129 /* TODO cleanup ir3 src order: */ 1130 swap(instr->srcs[0], instr->srcs[1]); 1131 } 1132 1133 cat6_todo: T_OP_G2L { new_instr(OPC_G2L); } 1134 | T_OP_L2G { new_instr(OPC_L2G); } 1135 | T_OP_RESFMT { new_instr(OPC_RESFMT); } 1136 1137 cat6_instr: cat6_load 1138 | cat6_loadib 1139 | cat6_store 1140 | cat6_storeib 1141 | cat6_prefetch 1142 | cat6_atomic 1143 | cat6_ibo 1144 | cat6_id 1145 | cat6_bindless_ldc 1146 | cat6_bindless_ibo 1147 | cat6_todo 1148 1149 cat7_scope: '.' 'w' { instr->cat7.w = true; } 1150 | '.' 'r' { instr->cat7.r = true; } 1151 | '.' 'l' { instr->cat7.l = true; } 1152 | '.' 'g' { instr->cat7.g = true; } 1153 1154 cat7_scopes: 1155 | cat7_scope cat7_scopes 1156 1157 cat7_barrier: T_OP_BAR { new_instr(OPC_BAR); } cat7_scopes 1158 | T_OP_FENCE { new_instr(OPC_FENCE); } cat7_scopes 1159 1160 cat7_instr: cat7_barrier 1161 1162 src: T_REGISTER { $$ = new_src($1, 0); } 1163 | T_A0 { $$ = new_src((61 << 3), IR3_REG_HALF); } 1164 | T_A1 { $$ = new_src((61 << 3) + 1, IR3_REG_HALF); } 1165 | T_P0 { $$ = new_src((62 << 3) + $1, 0); } 1166 1167 dst: T_REGISTER { $$ = new_dst($1, 0); } 1168 | T_A0 { $$ = new_dst((61 << 3), IR3_REG_HALF); } 1169 | T_A1 { $$ = new_dst((61 << 3) + 1, IR3_REG_HALF); } 1170 | T_P0 { $$ = new_dst((62 << 3) + $1, 0); } 1171 1172 const: T_CONSTANT { $$ = new_src($1, IR3_REG_CONST); } 1173 1174 dst_reg_flag: T_EVEN { instr->cat1.round = ROUND_EVEN; } 1175 | T_POS_INFINITY { instr->cat1.round = ROUND_POS_INF; } 1176 | T_NEG_INFINITY { instr->cat1.round = ROUND_NEG_INF; } 1177 | T_EI { rflags.flags |= IR3_REG_EI; } 1178 | T_WRMASK { rflags.wrmask = $1; } 1179 1180 dst_reg_flags: dst_reg_flag 1181 | dst_reg_flag dst_reg_flags 1182 1183 /* note: destination registers are always incremented in repeat */ 1184 dst_reg: dst { $1->flags |= IR3_REG_R; } 1185 | dst_reg_flags dst { $2->flags |= IR3_REG_R; } 1186 1187 src_reg_flag: T_ABSNEG { rflags.flags |= IR3_REG_ABS|IR3_REG_NEGATE; } 1188 | T_NEG { rflags.flags |= IR3_REG_NEGATE; } 1189 | T_ABS { rflags.flags |= IR3_REG_ABS; } 1190 | T_R { rflags.flags |= IR3_REG_R; } 1191 1192 src_reg_flags: src_reg_flag 1193 | src_reg_flag src_reg_flags 1194 1195 src_reg: src 1196 | src_reg_flags src 1197 1198 src_const: const 1199 | src_reg_flags const 1200 1201 src_reg_or_const: src_reg 1202 | src_const 1203 1204 src_reg_or_const_or_rel: src_reg_or_const 1205 | relative 1206 | src_reg_flags relative 1207 1208 src_reg_or_const_or_rel_or_imm: src_reg_or_const_or_rel 1209 | src_reg_flags immediate 1210 | immediate 1211 1212 src_reg_or_rel_or_imm: src_reg 1213 | relative 1214 | immediate 1215 1216 offset: { $$ = 0; } 1217 | '+' integer { $$ = $2; } 1218 | '-' integer { $$ = -$2; } 1219 1220 relative_gpr_src: 'r' '<' T_A0 offset '>' { new_src(0, IR3_REG_RELATIV)->array.offset = $4; } 1221 | T_HR '<' T_A0 offset '>' { new_src(0, IR3_REG_RELATIV | IR3_REG_HALF)->array.offset = $4; } 1222 1223 relative_gpr_dst: 'r' '<' T_A0 offset '>' { new_dst(0, IR3_REG_RELATIV)->array.offset = $4; } 1224 | T_HR '<' T_A0 offset '>' { new_dst(0, IR3_REG_RELATIV | IR3_REG_HALF)->array.offset = $4; } 1225 1226 relative_const: 'c' '<' T_A0 offset '>' { new_src(0, IR3_REG_RELATIV | IR3_REG_CONST)->array.offset = $4; } 1227 | T_HC '<' T_A0 offset '>' { new_src(0, IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_HALF)->array.offset = $4; } 1228 1229 relative: relative_gpr_src 1230 | relative_const 1231 1232 /* cat1 immediates differ slighly in the floating point case from the cat2 1233 * case which can only encode certain predefined values (ie. and index into 1234 * the FLUT table) 1235 */ 1236 immediate_cat1: integer { new_src(0, IR3_REG_IMMED)->iim_val = type_size(instr->cat1.src_type) < 32 ? $1 & 0xffff : $1; } 1237 | '(' integer ')' { new_src(0, IR3_REG_IMMED)->fim_val = $2; } 1238 | '(' float ')' { new_src(0, IR3_REG_IMMED)->fim_val = $2; } 1239 | 'h' '(' integer ')' { new_src(0, IR3_REG_IMMED | IR3_REG_HALF)->iim_val = $3 & 0xffff; } 1240 | 'h' '(' float ')' { new_src(0, IR3_REG_IMMED | IR3_REG_HALF)->uim_val = _mesa_float_to_half($3); } 1241 | '(' T_NAN ')' { new_src(0, IR3_REG_IMMED)->fim_val = NAN; } 1242 | '(' T_INF ')' { new_src(0, IR3_REG_IMMED)->fim_val = INFINITY; } 1243 1244 immediate: integer { new_src(0, IR3_REG_IMMED)->iim_val = $1; } 1245 | '(' integer ')' { new_src(0, IR3_REG_IMMED)->fim_val = $2; } 1246 | flut_immed { new_src(0, IR3_REG_IMMED)->uim_val = $1; } 1247 | 'h' '(' integer ')' { new_src(0, IR3_REG_IMMED | IR3_REG_HALF)->iim_val = $3; } 1248 | 'h' flut_immed { new_src(0, IR3_REG_IMMED | IR3_REG_HALF)->uim_val = $2; } 1249 1250 /* Float LUT values accepted as immed: */ 1251 flut_immed: T_FLUT_0_0 1252 | T_FLUT_0_5 1253 | T_FLUT_1_0 1254 | T_FLUT_2_0 1255 | T_FLUT_E 1256 | T_FLUT_PI 1257 | T_FLUT_INV_PI 1258 | T_FLUT_INV_LOG2_E 1259 | T_FLUT_LOG2_E 1260 | T_FLUT_INV_LOG2_10 1261 | T_FLUT_LOG2_10 1262 | T_FLUT_4_0 1263 1264 integer: T_INT { $$ = $1; } 1265 | '-' T_INT { $$ = -$2; } 1266 | T_HEX { $$ = $1; } 1267 | '-' T_HEX { $$ = -$2; } 1268 1269 float: T_FLOAT { $$ = $1; } 1270 | '-' T_FLOAT { $$ = -$2; } 1271 1272 type: T_TYPE_F16 { $$ = TYPE_F16; } 1273 | T_TYPE_F32 { $$ = TYPE_F32; } 1274 | T_TYPE_U16 { $$ = TYPE_U16; } 1275 | T_TYPE_U32 { $$ = TYPE_U32; } 1276 | T_TYPE_S16 { $$ = TYPE_S16; } 1277 | T_TYPE_S32 { $$ = TYPE_S32; } 1278 | T_TYPE_U8 { $$ = TYPE_U8; } 1279 | T_TYPE_S8 { $$ = TYPE_S8; } 1280