1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.3 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27 #include "main/glheader.h" 28 #include "main/imports.h" 29 #include "main/mtypes.h" 30 #include "prog_instruction.h" 31 32 33 /** 34 * Initialize program instruction fields to defaults. 35 * \param inst first instruction to initialize 36 * \param count number of instructions to initialize 37 */ 38 void 39 _mesa_init_instructions(struct prog_instruction *inst, GLuint count) 40 { 41 GLuint i; 42 43 memset(inst, 0, count * sizeof(struct prog_instruction)); 44 45 for (i = 0; i < count; i++) { 46 inst[i].SrcReg[0].File = PROGRAM_UNDEFINED; 47 inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; 48 inst[i].SrcReg[1].File = PROGRAM_UNDEFINED; 49 inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; 50 inst[i].SrcReg[2].File = PROGRAM_UNDEFINED; 51 inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP; 52 53 inst[i].DstReg.File = PROGRAM_UNDEFINED; 54 inst[i].DstReg.WriteMask = WRITEMASK_XYZW; 55 inst[i].DstReg.CondMask = COND_TR; 56 inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP; 57 58 inst[i].SaturateMode = SATURATE_OFF; 59 inst[i].Precision = FLOAT32; 60 } 61 } 62 63 64 /** 65 * Allocate an array of program instructions. 66 * \param numInst number of instructions 67 * \return pointer to instruction memory 68 */ 69 struct prog_instruction * 70 _mesa_alloc_instructions(GLuint numInst) 71 { 72 return (struct prog_instruction *) 73 calloc(1, numInst * sizeof(struct prog_instruction)); 74 } 75 76 77 /** 78 * Reallocate memory storing an array of program instructions. 79 * This is used when we need to append additional instructions onto an 80 * program. 81 * \param oldInst pointer to first of old/src instructions 82 * \param numOldInst number of instructions at <oldInst> 83 * \param numNewInst desired size of new instruction array. 84 * \return pointer to start of new instruction array. 85 */ 86 struct prog_instruction * 87 _mesa_realloc_instructions(struct prog_instruction *oldInst, 88 GLuint numOldInst, GLuint numNewInst) 89 { 90 struct prog_instruction *newInst; 91 92 newInst = (struct prog_instruction *) 93 _mesa_realloc(oldInst, 94 numOldInst * sizeof(struct prog_instruction), 95 numNewInst * sizeof(struct prog_instruction)); 96 97 return newInst; 98 } 99 100 101 /** 102 * Copy an array of program instructions. 103 * \param dest pointer to destination. 104 * \param src pointer to source. 105 * \param n number of instructions to copy. 106 * \return pointer to destination. 107 */ 108 struct prog_instruction * 109 _mesa_copy_instructions(struct prog_instruction *dest, 110 const struct prog_instruction *src, GLuint n) 111 { 112 GLuint i; 113 memcpy(dest, src, n * sizeof(struct prog_instruction)); 114 for (i = 0; i < n; i++) { 115 if (src[i].Comment) 116 dest[i].Comment = _mesa_strdup(src[i].Comment); 117 } 118 return dest; 119 } 120 121 122 /** 123 * Free an array of instructions 124 */ 125 void 126 _mesa_free_instructions(struct prog_instruction *inst, GLuint count) 127 { 128 GLuint i; 129 for (i = 0; i < count; i++) { 130 if (inst[i].Data) 131 free(inst[i].Data); 132 if (inst[i].Comment) 133 free((char *) inst[i].Comment); 134 } 135 free(inst); 136 } 137 138 139 /** 140 * Basic info about each instruction 141 */ 142 struct instruction_info 143 { 144 gl_inst_opcode Opcode; 145 const char *Name; 146 GLuint NumSrcRegs; 147 GLuint NumDstRegs; 148 }; 149 150 /** 151 * Instruction info 152 * \note Opcode should equal array index! 153 */ 154 static const struct instruction_info InstInfo[MAX_OPCODE] = { 155 { OPCODE_NOP, "NOP", 0, 0 }, 156 { OPCODE_ABS, "ABS", 1, 1 }, 157 { OPCODE_ADD, "ADD", 2, 1 }, 158 { OPCODE_AND, "AND", 2, 1 }, 159 { OPCODE_ARA, "ARA", 1, 1 }, 160 { OPCODE_ARL, "ARL", 1, 1 }, 161 { OPCODE_ARL_NV, "ARL_NV", 1, 1 }, 162 { OPCODE_ARR, "ARL", 1, 1 }, 163 { OPCODE_BGNLOOP,"BGNLOOP", 0, 0 }, 164 { OPCODE_BGNSUB, "BGNSUB", 0, 0 }, 165 { OPCODE_BRA, "BRA", 0, 0 }, 166 { OPCODE_BRK, "BRK", 0, 0 }, 167 { OPCODE_CAL, "CAL", 0, 0 }, 168 { OPCODE_CMP, "CMP", 3, 1 }, 169 { OPCODE_CONT, "CONT", 0, 0 }, 170 { OPCODE_COS, "COS", 1, 1 }, 171 { OPCODE_DDX, "DDX", 1, 1 }, 172 { OPCODE_DDY, "DDY", 1, 1 }, 173 { OPCODE_DP2, "DP2", 2, 1 }, 174 { OPCODE_DP2A, "DP2A", 3, 1 }, 175 { OPCODE_DP3, "DP3", 2, 1 }, 176 { OPCODE_DP4, "DP4", 2, 1 }, 177 { OPCODE_DPH, "DPH", 2, 1 }, 178 { OPCODE_DST, "DST", 2, 1 }, 179 { OPCODE_ELSE, "ELSE", 0, 0 }, 180 { OPCODE_EMIT_VERTEX, "EMIT_VERTEX", 0, 0 }, 181 { OPCODE_END, "END", 0, 0 }, 182 { OPCODE_END_PRIMITIVE, "END_PRIMITIVE", 0, 0 }, 183 { OPCODE_ENDIF, "ENDIF", 0, 0 }, 184 { OPCODE_ENDLOOP,"ENDLOOP", 0, 0 }, 185 { OPCODE_ENDSUB, "ENDSUB", 0, 0 }, 186 { OPCODE_EX2, "EX2", 1, 1 }, 187 { OPCODE_EXP, "EXP", 1, 1 }, 188 { OPCODE_FLR, "FLR", 1, 1 }, 189 { OPCODE_FRC, "FRC", 1, 1 }, 190 { OPCODE_IF, "IF", 1, 0 }, 191 { OPCODE_KIL, "KIL", 1, 0 }, 192 { OPCODE_KIL_NV, "KIL_NV", 0, 0 }, 193 { OPCODE_LG2, "LG2", 1, 1 }, 194 { OPCODE_LIT, "LIT", 1, 1 }, 195 { OPCODE_LOG, "LOG", 1, 1 }, 196 { OPCODE_LRP, "LRP", 3, 1 }, 197 { OPCODE_MAD, "MAD", 3, 1 }, 198 { OPCODE_MAX, "MAX", 2, 1 }, 199 { OPCODE_MIN, "MIN", 2, 1 }, 200 { OPCODE_MOV, "MOV", 1, 1 }, 201 { OPCODE_MUL, "MUL", 2, 1 }, 202 { OPCODE_NOISE1, "NOISE1", 1, 1 }, 203 { OPCODE_NOISE2, "NOISE2", 1, 1 }, 204 { OPCODE_NOISE3, "NOISE3", 1, 1 }, 205 { OPCODE_NOISE4, "NOISE4", 1, 1 }, 206 { OPCODE_NOT, "NOT", 1, 1 }, 207 { OPCODE_NRM3, "NRM3", 1, 1 }, 208 { OPCODE_NRM4, "NRM4", 1, 1 }, 209 { OPCODE_OR, "OR", 2, 1 }, 210 { OPCODE_PK2H, "PK2H", 1, 1 }, 211 { OPCODE_PK2US, "PK2US", 1, 1 }, 212 { OPCODE_PK4B, "PK4B", 1, 1 }, 213 { OPCODE_PK4UB, "PK4UB", 1, 1 }, 214 { OPCODE_POW, "POW", 2, 1 }, 215 { OPCODE_POPA, "POPA", 0, 0 }, 216 { OPCODE_PRINT, "PRINT", 1, 0 }, 217 { OPCODE_PUSHA, "PUSHA", 0, 0 }, 218 { OPCODE_RCC, "RCC", 1, 1 }, 219 { OPCODE_RCP, "RCP", 1, 1 }, 220 { OPCODE_RET, "RET", 0, 0 }, 221 { OPCODE_RFL, "RFL", 1, 1 }, 222 { OPCODE_RSQ, "RSQ", 1, 1 }, 223 { OPCODE_SCS, "SCS", 1, 1 }, 224 { OPCODE_SEQ, "SEQ", 2, 1 }, 225 { OPCODE_SFL, "SFL", 0, 1 }, 226 { OPCODE_SGE, "SGE", 2, 1 }, 227 { OPCODE_SGT, "SGT", 2, 1 }, 228 { OPCODE_SIN, "SIN", 1, 1 }, 229 { OPCODE_SLE, "SLE", 2, 1 }, 230 { OPCODE_SLT, "SLT", 2, 1 }, 231 { OPCODE_SNE, "SNE", 2, 1 }, 232 { OPCODE_SSG, "SSG", 1, 1 }, 233 { OPCODE_STR, "STR", 0, 1 }, 234 { OPCODE_SUB, "SUB", 2, 1 }, 235 { OPCODE_SWZ, "SWZ", 1, 1 }, 236 { OPCODE_TEX, "TEX", 1, 1 }, 237 { OPCODE_TXB, "TXB", 1, 1 }, 238 { OPCODE_TXD, "TXD", 3, 1 }, 239 { OPCODE_TXL, "TXL", 1, 1 }, 240 { OPCODE_TXP, "TXP", 1, 1 }, 241 { OPCODE_TXP_NV, "TXP_NV", 1, 1 }, 242 { OPCODE_TRUNC, "TRUNC", 1, 1 }, 243 { OPCODE_UP2H, "UP2H", 1, 1 }, 244 { OPCODE_UP2US, "UP2US", 1, 1 }, 245 { OPCODE_UP4B, "UP4B", 1, 1 }, 246 { OPCODE_UP4UB, "UP4UB", 1, 1 }, 247 { OPCODE_X2D, "X2D", 3, 1 }, 248 { OPCODE_XOR, "XOR", 2, 1 }, 249 { OPCODE_XPD, "XPD", 2, 1 } 250 }; 251 252 253 /** 254 * Return the number of src registers for the given instruction/opcode. 255 */ 256 GLuint 257 _mesa_num_inst_src_regs(gl_inst_opcode opcode) 258 { 259 ASSERT(opcode < MAX_OPCODE); 260 ASSERT(opcode == InstInfo[opcode].Opcode); 261 ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode); 262 return InstInfo[opcode].NumSrcRegs; 263 } 264 265 266 /** 267 * Return the number of dst registers for the given instruction/opcode. 268 */ 269 GLuint 270 _mesa_num_inst_dst_regs(gl_inst_opcode opcode) 271 { 272 ASSERT(opcode < MAX_OPCODE); 273 ASSERT(opcode == InstInfo[opcode].Opcode); 274 ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode); 275 return InstInfo[opcode].NumDstRegs; 276 } 277 278 279 GLboolean 280 _mesa_is_tex_instruction(gl_inst_opcode opcode) 281 { 282 return (opcode == OPCODE_TEX || 283 opcode == OPCODE_TXB || 284 opcode == OPCODE_TXD || 285 opcode == OPCODE_TXL || 286 opcode == OPCODE_TXP); 287 } 288 289 290 /** 291 * Check if there's a potential src/dst register data dependency when 292 * using SOA execution. 293 * Example: 294 * MOV T, T.yxwz; 295 * This would expand into: 296 * MOV t0, t1; 297 * MOV t1, t0; 298 * MOV t2, t3; 299 * MOV t3, t2; 300 * The second instruction will have the wrong value for t0 if executed as-is. 301 */ 302 GLboolean 303 _mesa_check_soa_dependencies(const struct prog_instruction *inst) 304 { 305 GLuint i, chan; 306 307 if (inst->DstReg.WriteMask == WRITEMASK_X || 308 inst->DstReg.WriteMask == WRITEMASK_Y || 309 inst->DstReg.WriteMask == WRITEMASK_Z || 310 inst->DstReg.WriteMask == WRITEMASK_W || 311 inst->DstReg.WriteMask == 0x0) { 312 /* no chance of data dependency */ 313 return GL_FALSE; 314 } 315 316 /* loop over src regs */ 317 for (i = 0; i < 3; i++) { 318 if (inst->SrcReg[i].File == inst->DstReg.File && 319 inst->SrcReg[i].Index == inst->DstReg.Index) { 320 /* loop over dest channels */ 321 GLuint channelsWritten = 0x0; 322 for (chan = 0; chan < 4; chan++) { 323 if (inst->DstReg.WriteMask & (1 << chan)) { 324 /* check if we're reading a channel that's been written */ 325 GLuint swizzle = GET_SWZ(inst->SrcReg[i].Swizzle, chan); 326 if (swizzle <= SWIZZLE_W && 327 (channelsWritten & (1 << swizzle))) { 328 return GL_TRUE; 329 } 330 331 channelsWritten |= (1 << chan); 332 } 333 } 334 } 335 } 336 return GL_FALSE; 337 } 338 339 340 /** 341 * Return string name for given program opcode. 342 */ 343 const char * 344 _mesa_opcode_string(gl_inst_opcode opcode) 345 { 346 if (opcode < MAX_OPCODE) 347 return InstInfo[opcode].Name; 348 else { 349 static char s[20]; 350 _mesa_snprintf(s, sizeof(s), "OP%u", opcode); 351 return s; 352 } 353 } 354 355