Home | History | Annotate | Download | only in program
      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