1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2012-2013 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv (at) lunarg.com> 26 */ 27 28 #ifndef TOY_COMPILER_H 29 #define TOY_COMPILER_H 30 31 #include "genhw/genhw.h" 32 #include "util/slab.h" 33 34 #include "ilo_common.h" 35 #include "toy_compiler_reg.h" 36 37 /** 38 * Toy opcodes. 39 */ 40 enum toy_opcode { 41 /* 0..127 are reserved for GEN6_OPCODE_x */ 42 TOY_OPCODE_LAST_HW = 127, 43 44 TOY_OPCODE_DO, 45 46 /* TGSI register functions */ 47 TOY_OPCODE_TGSI_IN, 48 TOY_OPCODE_TGSI_CONST, 49 TOY_OPCODE_TGSI_SV, 50 TOY_OPCODE_TGSI_IMM, 51 TOY_OPCODE_TGSI_INDIRECT_FETCH, 52 TOY_OPCODE_TGSI_INDIRECT_STORE, 53 54 /* TGSI sampling functions */ 55 TOY_OPCODE_TGSI_TEX, 56 TOY_OPCODE_TGSI_TXB, 57 TOY_OPCODE_TGSI_TXD, 58 TOY_OPCODE_TGSI_TXL, 59 TOY_OPCODE_TGSI_TXP, 60 TOY_OPCODE_TGSI_TXF, 61 TOY_OPCODE_TGSI_TXQ, 62 TOY_OPCODE_TGSI_TXQ_LZ, 63 TOY_OPCODE_TGSI_TEX2, 64 TOY_OPCODE_TGSI_TXB2, 65 TOY_OPCODE_TGSI_TXL2, 66 TOY_OPCODE_TGSI_SAMPLE, 67 TOY_OPCODE_TGSI_SAMPLE_I, 68 TOY_OPCODE_TGSI_SAMPLE_I_MS, 69 TOY_OPCODE_TGSI_SAMPLE_B, 70 TOY_OPCODE_TGSI_SAMPLE_C, 71 TOY_OPCODE_TGSI_SAMPLE_C_LZ, 72 TOY_OPCODE_TGSI_SAMPLE_D, 73 TOY_OPCODE_TGSI_SAMPLE_L, 74 TOY_OPCODE_TGSI_GATHER4, 75 TOY_OPCODE_TGSI_SVIEWINFO, 76 TOY_OPCODE_TGSI_SAMPLE_POS, 77 TOY_OPCODE_TGSI_SAMPLE_INFO, 78 79 /* math functions */ 80 TOY_OPCODE_INV, 81 TOY_OPCODE_LOG, 82 TOY_OPCODE_EXP, 83 TOY_OPCODE_SQRT, 84 TOY_OPCODE_RSQ, 85 TOY_OPCODE_SIN, 86 TOY_OPCODE_COS, 87 TOY_OPCODE_FDIV, 88 TOY_OPCODE_POW, 89 TOY_OPCODE_INT_DIV_QUOTIENT, 90 TOY_OPCODE_INT_DIV_REMAINDER, 91 92 /* URB functions */ 93 TOY_OPCODE_URB_WRITE, 94 95 /* GS-specific functions */ 96 TOY_OPCODE_EMIT, 97 TOY_OPCODE_ENDPRIM, 98 99 /* FS-specific functions */ 100 TOY_OPCODE_DDX, 101 TOY_OPCODE_DDY, 102 TOY_OPCODE_FB_WRITE, 103 TOY_OPCODE_KIL, 104 }; 105 106 /** 107 * Toy instruction. 108 */ 109 struct toy_inst { 110 unsigned opcode:8; /* enum toy_opcode */ 111 unsigned access_mode:1; /* GEN6_ALIGN_x */ 112 unsigned mask_ctrl:1; /* GEN6_MASKCTRL_x */ 113 unsigned dep_ctrl:2; /* GEN6_DEPCTRL_x */ 114 unsigned qtr_ctrl:2; /* GEN6_QTRCTRL_x */ 115 unsigned thread_ctrl:2; /* GEN6_THREADCTRL_x */ 116 unsigned pred_ctrl:4; /* GEN6_PREDCTRL_x */ 117 unsigned pred_inv:1; /* true or false */ 118 unsigned exec_size:3; /* GEN6_EXECSIZE_x */ 119 unsigned cond_modifier:4; /* GEN6_COND_x */ 120 unsigned acc_wr_ctrl:1; /* true or false */ 121 unsigned saturate:1; /* true or false */ 122 123 /* true if the instruction should be ignored for instruction iteration */ 124 unsigned marker:1; 125 126 unsigned pad:1; 127 128 struct toy_dst dst; 129 struct toy_src src[5]; /* match TGSI_FULL_MAX_SRC_REGISTERS */ 130 131 struct { 132 int target; /* TGSI_TEXTURE_x */ 133 struct toy_src offsets[1]; /* need to be 4 when GATHER4 is supported */ 134 } tex; 135 136 struct list_head list; 137 }; 138 139 struct toy_compaction_table { 140 uint32_t control[32]; 141 uint32_t datatype[32]; 142 uint32_t subreg[32]; 143 uint32_t src[32]; 144 145 uint32_t control_3src[4]; 146 uint64_t source_3src[4]; 147 }; 148 149 /** 150 * Toy compiler. 151 */ 152 struct toy_compiler { 153 const struct ilo_dev *dev; 154 155 struct toy_inst templ; 156 struct slab_mempool mempool; 157 struct list_head instructions; 158 struct list_head *iter, *iter_next; 159 160 /* this is not set until toy_compiler_legalize_for_asm() */ 161 int num_instructions; 162 163 int rect_linear_width; 164 int next_vrf; 165 166 bool fail; 167 const char *reason; 168 }; 169 170 /** 171 * Allocate the given number of VRF registers. 172 */ 173 static inline int 174 tc_alloc_vrf(struct toy_compiler *tc, int count) 175 { 176 const int vrf = tc->next_vrf; 177 178 tc->next_vrf += count; 179 180 return vrf; 181 } 182 183 /** 184 * Allocate a temporary register. 185 */ 186 static inline struct toy_dst 187 tc_alloc_tmp(struct toy_compiler *tc) 188 { 189 return tdst(TOY_FILE_VRF, tc_alloc_vrf(tc, 1), 0); 190 } 191 192 /** 193 * Allocate four temporary registers. 194 */ 195 static inline void 196 tc_alloc_tmp4(struct toy_compiler *tc, struct toy_dst *tmp) 197 { 198 tmp[0] = tc_alloc_tmp(tc); 199 tmp[1] = tc_alloc_tmp(tc); 200 tmp[2] = tc_alloc_tmp(tc); 201 tmp[3] = tc_alloc_tmp(tc); 202 } 203 204 /** 205 * Duplicate an instruction at the current location. 206 */ 207 static inline struct toy_inst * 208 tc_duplicate_inst(struct toy_compiler *tc, const struct toy_inst *inst) 209 { 210 struct toy_inst *new_inst; 211 212 new_inst = slab_alloc_st(&tc->mempool); 213 if (!new_inst) 214 return NULL; 215 216 *new_inst = *inst; 217 list_addtail(&new_inst->list, tc->iter_next); 218 219 return new_inst; 220 } 221 222 /** 223 * Move an instruction to the current location. 224 */ 225 static inline void 226 tc_move_inst(struct toy_compiler *tc, struct toy_inst *inst) 227 { 228 list_del(&inst->list); 229 list_addtail(&inst->list, tc->iter_next); 230 } 231 232 /** 233 * Discard an instruction. 234 */ 235 static inline void 236 tc_discard_inst(struct toy_compiler *tc, struct toy_inst *inst) 237 { 238 list_del(&inst->list); 239 slab_free_st(&tc->mempool, inst); 240 } 241 242 /** 243 * Add a new instruction at the current location, using tc->templ as the 244 * template. 245 */ 246 static inline struct toy_inst * 247 tc_add(struct toy_compiler *tc) 248 { 249 return tc_duplicate_inst(tc, &tc->templ); 250 } 251 252 /** 253 * A convenient version of tc_add() for instructions with 3 source operands. 254 */ 255 static inline struct toy_inst * 256 tc_add3(struct toy_compiler *tc, unsigned opcode, 257 struct toy_dst dst, 258 struct toy_src src0, 259 struct toy_src src1, 260 struct toy_src src2) 261 { 262 struct toy_inst *inst; 263 264 inst = tc_add(tc); 265 if (!inst) 266 return NULL; 267 268 inst->opcode = opcode; 269 inst->dst = dst; 270 inst->src[0] = src0; 271 inst->src[1] = src1; 272 inst->src[2] = src2; 273 274 return inst; 275 } 276 277 /** 278 * A convenient version of tc_add() for instructions with 2 source operands. 279 */ 280 static inline struct toy_inst * 281 tc_add2(struct toy_compiler *tc, int opcode, 282 struct toy_dst dst, 283 struct toy_src src0, 284 struct toy_src src1) 285 { 286 return tc_add3(tc, opcode, dst, src0, src1, tsrc_null()); 287 } 288 289 /** 290 * A convenient version of tc_add() for instructions with 1 source operand. 291 */ 292 static inline struct toy_inst * 293 tc_add1(struct toy_compiler *tc, unsigned opcode, 294 struct toy_dst dst, 295 struct toy_src src0) 296 { 297 return tc_add2(tc, opcode, dst, src0, tsrc_null()); 298 } 299 300 /** 301 * A convenient version of tc_add() for instructions without source or 302 * destination operands. 303 */ 304 static inline struct toy_inst * 305 tc_add0(struct toy_compiler *tc, unsigned opcode) 306 { 307 return tc_add1(tc, opcode, tdst_null(), tsrc_null()); 308 } 309 310 #define TC_ALU0(func, opcode) \ 311 static inline struct toy_inst * \ 312 func(struct toy_compiler *tc) \ 313 { \ 314 return tc_add0(tc, opcode); \ 315 } 316 317 #define TC_ALU1(func, opcode) \ 318 static inline struct toy_inst * \ 319 func(struct toy_compiler *tc, \ 320 struct toy_dst dst, \ 321 struct toy_src src) \ 322 { \ 323 return tc_add1(tc, opcode, dst, src); \ 324 } 325 326 #define TC_ALU2(func, opcode) \ 327 static inline struct toy_inst * \ 328 func(struct toy_compiler *tc, \ 329 struct toy_dst dst, \ 330 struct toy_src src0, \ 331 struct toy_src src1) \ 332 { \ 333 return tc_add2(tc, opcode, \ 334 dst, src0, src1); \ 335 } 336 337 #define TC_ALU3(func, opcode) \ 338 static inline struct toy_inst * \ 339 func(struct toy_compiler *tc, \ 340 struct toy_dst dst, \ 341 struct toy_src src0, \ 342 struct toy_src src1, \ 343 struct toy_src src2) \ 344 { \ 345 return tc_add3(tc, opcode, \ 346 dst, src0, src1, src2); \ 347 } 348 349 #define TC_CND2(func, opcode) \ 350 static inline struct toy_inst * \ 351 func(struct toy_compiler *tc, \ 352 struct toy_dst dst, \ 353 struct toy_src src0, \ 354 struct toy_src src1, \ 355 unsigned cond_modifier) \ 356 { \ 357 struct toy_inst *inst; \ 358 inst = tc_add2(tc, opcode, \ 359 dst, src0, src1); \ 360 inst->cond_modifier = cond_modifier; \ 361 return inst; \ 362 } 363 364 TC_ALU0(tc_NOP, GEN6_OPCODE_NOP) 365 TC_ALU0(tc_ELSE, GEN6_OPCODE_ELSE) 366 TC_ALU0(tc_ENDIF, GEN6_OPCODE_ENDIF) 367 TC_ALU1(tc_MOV, GEN6_OPCODE_MOV) 368 TC_ALU1(tc_RNDD, GEN6_OPCODE_RNDD) 369 TC_ALU1(tc_INV, TOY_OPCODE_INV) 370 TC_ALU1(tc_FRC, GEN6_OPCODE_FRC) 371 TC_ALU1(tc_EXP, TOY_OPCODE_EXP) 372 TC_ALU1(tc_LOG, TOY_OPCODE_LOG) 373 TC_ALU2(tc_ADD, GEN6_OPCODE_ADD) 374 TC_ALU2(tc_MUL, GEN6_OPCODE_MUL) 375 TC_ALU2(tc_AND, GEN6_OPCODE_AND) 376 TC_ALU2(tc_OR, GEN6_OPCODE_OR) 377 TC_ALU2(tc_DP2, GEN6_OPCODE_DP2) 378 TC_ALU2(tc_DP3, GEN6_OPCODE_DP3) 379 TC_ALU2(tc_DP4, GEN6_OPCODE_DP4) 380 TC_ALU2(tc_SHL, GEN6_OPCODE_SHL) 381 TC_ALU2(tc_SHR, GEN6_OPCODE_SHR) 382 TC_ALU2(tc_POW, TOY_OPCODE_POW) 383 TC_ALU3(tc_MAC, GEN6_OPCODE_MAC) 384 TC_CND2(tc_SEL, GEN6_OPCODE_SEL) 385 TC_CND2(tc_CMP, GEN6_OPCODE_CMP) 386 TC_CND2(tc_IF, GEN6_OPCODE_IF) 387 TC_CND2(tc_SEND, GEN6_OPCODE_SEND) 388 389 /** 390 * Upcast a list_head to an instruction. 391 */ 392 static inline struct toy_inst * 393 tc_list_to_inst(struct toy_compiler *tc, struct list_head *item) 394 { 395 return container_of(item, (struct toy_inst *) NULL, list); 396 } 397 398 /** 399 * Return the instruction at the current location. 400 */ 401 static inline struct toy_inst * 402 tc_current(struct toy_compiler *tc) 403 { 404 return (tc->iter != &tc->instructions) ? 405 tc_list_to_inst(tc, tc->iter) : NULL; 406 } 407 408 /** 409 * Set the current location to the head. 410 */ 411 static inline void 412 tc_head(struct toy_compiler *tc) 413 { 414 tc->iter = &tc->instructions; 415 tc->iter_next = tc->iter->next; 416 } 417 418 /** 419 * Set the current location to the tail. 420 */ 421 static inline void 422 tc_tail(struct toy_compiler *tc) 423 { 424 tc->iter = &tc->instructions; 425 tc->iter_next = tc->iter; 426 } 427 428 /** 429 * Advance the current location. 430 */ 431 static inline struct toy_inst * 432 tc_next_no_skip(struct toy_compiler *tc) 433 { 434 /* stay at the tail so that new instructions are added there */ 435 if (tc->iter_next == &tc->instructions) { 436 tc_tail(tc); 437 return NULL; 438 } 439 440 tc->iter = tc->iter_next; 441 tc->iter_next = tc->iter_next->next; 442 443 return tc_list_to_inst(tc, tc->iter); 444 } 445 446 /** 447 * Advance the current location, skipping markers. 448 */ 449 static inline struct toy_inst * 450 tc_next(struct toy_compiler *tc) 451 { 452 struct toy_inst *inst; 453 454 do { 455 inst = tc_next_no_skip(tc); 456 } while (inst && inst->marker); 457 458 return inst; 459 } 460 461 static inline void 462 tc_fail(struct toy_compiler *tc, const char *reason) 463 { 464 if (!tc->fail) { 465 tc->fail = true; 466 tc->reason = reason; 467 } 468 } 469 470 void 471 toy_compiler_init(struct toy_compiler *tc, const struct ilo_dev *dev); 472 473 void 474 toy_compiler_cleanup(struct toy_compiler *tc); 475 476 void 477 toy_compiler_dump(struct toy_compiler *tc); 478 479 void * 480 toy_compiler_assemble(struct toy_compiler *tc, int *size); 481 482 const struct toy_compaction_table * 483 toy_compiler_get_compaction_table(const struct ilo_dev *dev); 484 485 void 486 toy_compiler_disassemble(const struct ilo_dev *dev, 487 const void *kernel, int size, 488 bool dump_hex); 489 490 #endif /* TOY_COMPILER_H */ 491