t_vb_arbprogram.c

来自「mesa-6.5-minigui源码」· C语言 代码 · 共 1,571 行 · 第 1/3 页

C
1,571
字号
   if (mask&0x2) _mesa_printf("y");   if (mask&0x4) _mesa_printf("z");   if (mask&0x8) _mesa_printf("w");}static void print_reg( GLuint file, GLuint reg ){   static const char *reg_file[] = {      "REG",      "LOCAL_PARAM",      "ENV_PARAM",      "STATE_VAR",   };   if (file == 0) {      if (reg == REG_RES) 	 _mesa_printf("RES");      else if (reg >= REG_ARG0 && reg <= REG_ARG1)	 _mesa_printf("ARG%d", reg - REG_ARG0);      else if (reg >= REG_TMP0 && reg <= REG_TMP11)	 _mesa_printf("TMP%d", reg - REG_TMP0);      else if (reg >= REG_IN0 && reg <= REG_IN31)	 _mesa_printf("IN%d", reg - REG_IN0);      else if (reg >= REG_OUT0 && reg <= REG_OUT14)	 _mesa_printf("OUT%d", reg - REG_OUT0);      else if (reg == REG_ADDR)	 _mesa_printf("ADDR");      else if (reg == REG_ID)	 _mesa_printf("ID");      else	 _mesa_printf("REG%d", reg);   }   else       _mesa_printf("%s:%d", reg_file[file], reg);}static void print_RSW( union instruction op ){   GLuint swz = op.rsw.swz;   GLuint neg = op.rsw.neg;   GLuint i;   _mesa_printf("RSW ");   print_reg(0, op.rsw.dst);   _mesa_printf(", ");   print_reg(op.rsw.file0, op.rsw.idx0);   _mesa_printf(".");   for (i = 0; i < 4; i++, swz >>= 2) {      const char *cswz = "xyzw";      if (neg & (1<<i))   	 _mesa_printf("-");      _mesa_printf("%c", cswz[swz&0x3]);   }   _mesa_printf("\n");}static void print_ALU( union instruction op ){   _mesa_printf("%s ", _mesa_opcode_string((enum prog_opcode) op.alu.opcode));   print_reg(0, op.alu.dst);   _mesa_printf(", ");   print_reg(op.alu.file0, op.alu.idx0);   if (_mesa_num_inst_src_regs((enum prog_opcode) op.alu.opcode) > 1) {      _mesa_printf(", ");      print_reg(op.alu.file1, op.alu.idx1);   }   _mesa_printf("\n");}static void print_MSK( union instruction op ){   _mesa_printf("MSK ");   print_reg(0, op.msk.dst);   print_mask(op.msk.mask);   _mesa_printf(", ");   print_reg(op.msk.file, op.msk.idx);   _mesa_printf("\n");}static void print_NOP( union instruction op ){}void_tnl_disassem_vba_insn( union instruction op ){   switch (op.alu.opcode) {   case OPCODE_ABS:   case OPCODE_ADD:   case OPCODE_DP3:   case OPCODE_DP4:   case OPCODE_DPH:   case OPCODE_DST:   case OPCODE_EX2:   case OPCODE_EXP:   case OPCODE_FLR:   case OPCODE_FRC:   case OPCODE_LG2:   case OPCODE_LIT:   case OPCODE_LOG:   case OPCODE_MAX:   case OPCODE_MIN:   case OPCODE_MOV:   case OPCODE_MUL:   case OPCODE_POW:   case OPCODE_PRINT:   case OPCODE_RCP:   case OPCODE_RSQ:   case OPCODE_SGE:   case OPCODE_SLT:   case OPCODE_SUB:   case OPCODE_XPD:      print_ALU(op);      break;   case OPCODE_ARA:   case OPCODE_ARL:   case OPCODE_ARL_NV:   case OPCODE_ARR:   case OPCODE_BRA:   case OPCODE_CAL:   case OPCODE_END:   case OPCODE_MAD:   case OPCODE_POPA:   case OPCODE_PUSHA:   case OPCODE_RCC:   case OPCODE_RET:   case OPCODE_SSG:   case OPCODE_SWZ:      print_NOP(op);      break;   case RSW:      print_RSW(op);      break;   case MSK:      print_MSK(op);      break;   case REL:      print_ALU(op);      break;   default:      _mesa_problem(NULL, "Bad opcode in _tnl_disassem_vba_insn()");   }}static void (* const opcode_func[MAX_OPCODE+3])(struct arb_vp_machine *, union instruction) = {   do_ABS,   do_ADD,   do_NOP,/*ARA*/   do_NOP,/*ARL*/   do_NOP,/*ARL_NV*/   do_NOP,/*ARR*/   do_NOP,/*BRA*/   do_NOP,/*CAL*/   do_NOP,/*CMP*/   do_NOP,/*COS*/   do_NOP,/*DDX*/   do_NOP,/*DDY*/   do_DP3,   do_DP4,   do_DPH,   do_DST,   do_NOP,   do_EX2,   do_EXP,   do_FLR,   do_FRC,   do_NOP,/*KIL*/   do_NOP,/*KIL_NV*/   do_LG2,   do_LIT,   do_LOG,   do_NOP,/*LRP*/   do_NOP,/*MAD*/   do_MAX,   do_MIN,   do_MOV,   do_MUL,   do_NOP,/*PK2H*/   do_NOP,/*PK2US*/   do_NOP,/*PK4B*/   do_NOP,/*PK4UB*/   do_POW,   do_NOP,/*POPA*/   do_PRT,   do_NOP,/*PUSHA*/   do_NOP,/*RCC*/   do_RCP,/*RCP*/   do_NOP,/*RET*/   do_NOP,/*RFL*/   do_RSQ,   do_NOP,/*SCS*/   do_NOP,/*SEQ*/   do_NOP,/*SFL*/   do_SGE,   do_NOP,/*SGT*/   do_NOP,/*SIN*/   do_NOP,/*SLE*/   do_SLT,   do_NOP,/*SNE*/   do_NOP,/*SSG*/   do_NOP,/*STR*/   do_SUB,   do_RSW,/*SWZ*/   do_NOP,/*TEX*/   do_NOP,/*TXB*/   do_NOP,/*TXD*/   do_NOP,/*TXL*/   do_NOP,/*TXP*/   do_NOP,/*TXP_NV*/   do_NOP,/*UP2H*/   do_NOP,/*UP2US*/   do_NOP,/*UP4B*/   do_NOP,/*UP4UB*/   do_NOP,/*X2D*/   do_XPD,   do_RSW,   do_MSK,   do_REL,};static union instruction *cvp_next_instruction( struct compilation *cp ){   union instruction *op = cp->csr++;   _mesa_bzero(op, sizeof(*op));   return op;}static struct reg cvp_make_reg( GLuint file, GLuint idx ){   struct reg reg;   reg.file = file;   reg.idx = idx;   return reg;}static struct reg cvp_emit_rel( struct compilation *cp,				struct reg reg,				struct reg tmpreg ){   union instruction *op = cvp_next_instruction(cp);   op->alu.opcode = REL;   op->alu.file0 = reg.file;   op->alu.idx0 = reg.idx;   op->alu.dst = tmpreg.idx;   return tmpreg;}static struct reg cvp_load_reg( struct compilation *cp,				GLuint file,				GLuint index,				GLuint rel,				GLuint tmpidx ){   struct reg tmpreg = cvp_make_reg(FILE_REG, tmpidx);   struct reg reg;   switch (file) {   case PROGRAM_TEMPORARY:      return cvp_make_reg(FILE_REG, REG_TMP0 + index);   case PROGRAM_INPUT:      return cvp_make_reg(FILE_REG, REG_IN0 + index);   case PROGRAM_OUTPUT:      return cvp_make_reg(FILE_REG, REG_OUT0 + index);      /* These two aren't populated by the parser?       */   case PROGRAM_LOCAL_PARAM:       reg = cvp_make_reg(FILE_LOCAL_PARAM, index);      if (rel) 	 return cvp_emit_rel(cp, reg, tmpreg);      else	 return reg;   case PROGRAM_ENV_PARAM:       reg = cvp_make_reg(FILE_ENV_PARAM, index);      if (rel) 	 return cvp_emit_rel(cp, reg, tmpreg);      else	 return reg;   case PROGRAM_STATE_VAR:      reg = cvp_make_reg(FILE_STATE_PARAM, index);      if (rel) 	 return cvp_emit_rel(cp, reg, tmpreg);      else	 return reg;      /* Invalid values:       */   case PROGRAM_WRITE_ONLY:   case PROGRAM_ADDRESS:   default:      _mesa_problem(NULL, "Invalid register file %d in cvp_load_reg()");      assert(0);      return tmpreg;		/* can't happen */   }}static struct reg cvp_emit_arg( struct compilation *cp,				const struct prog_src_register *src,				GLuint arg ){   struct reg reg = cvp_load_reg( cp, src->File, src->Index, src->RelAddr, arg );   union instruction rsw, noop;      /* Emit any necessary swizzling.      */   _mesa_bzero(&rsw, sizeof(rsw));   rsw.rsw.neg = src->NegateBase ? WRITEMASK_XYZW : 0;   /* we're expecting 2-bit swizzles below... */#if 1 /* XXX THESE ASSERTIONS CURRENTLY FAIL DURING GLEAN TESTS! */   ASSERT(GET_SWZ(src->Swizzle, 0) < 4);   ASSERT(GET_SWZ(src->Swizzle, 1) < 4);   ASSERT(GET_SWZ(src->Swizzle, 2) < 4);   ASSERT(GET_SWZ(src->Swizzle, 3) < 4);#endif   rsw.rsw.swz = ((GET_SWZ(src->Swizzle, 0) << 0) |		  (GET_SWZ(src->Swizzle, 1) << 2) |		  (GET_SWZ(src->Swizzle, 2) << 4) |		  (GET_SWZ(src->Swizzle, 3) << 6));   _mesa_bzero(&noop, sizeof(noop));   noop.rsw.neg = 0;   noop.rsw.swz = RSW_NOOP;   if (_mesa_memcmp(&rsw, &noop, sizeof(rsw)) !=0) {      union instruction *op = cvp_next_instruction(cp);      struct reg rsw_reg = cvp_make_reg(FILE_REG, REG_ARG0 + arg);      *op = rsw;      op->rsw.opcode = RSW;      op->rsw.file0 = reg.file;      op->rsw.idx0 = reg.idx;      op->rsw.dst = rsw_reg.idx;      return rsw_reg;   }   else      return reg;}static GLuint cvp_choose_result( struct compilation *cp,				 const struct prog_dst_register *dst,				 union instruction *fixup ){   GLuint mask = dst->WriteMask;   GLuint idx;   switch (dst->File) {   case PROGRAM_TEMPORARY:      idx = REG_TMP0 + dst->Index;      break;   case PROGRAM_OUTPUT:      idx = REG_OUT0 + dst->Index;      break;   default:      assert(0);      return REG_RES;		/* can't happen */   }   /* Optimization: When writing (with a writemask) to an undefined    * value for the first time, the writemask may be ignored.     */   if (mask != WRITEMASK_XYZW && (cp->reg_active & (1 << idx))) {      fixup->msk.opcode = MSK;      fixup->msk.dst = idx;      fixup->msk.file = FILE_REG;      fixup->msk.idx = REG_RES;      fixup->msk.mask = mask;      cp->reg_active |= 1 << idx;      return REG_RES;   }   else {      _mesa_bzero(fixup, sizeof(*fixup));      cp->reg_active |= 1 << idx;      return idx;   }}static struct reg cvp_emit_rsw( struct compilation *cp, 				GLuint dst,				struct reg src,				GLuint neg, 				GLuint swz,				GLboolean force){   struct reg retval;   if (swz != RSW_NOOP || neg != 0) {      union instruction *op = cvp_next_instruction(cp);      op->rsw.opcode = RSW;      op->rsw.dst = dst;      op->rsw.file0 = src.file;      op->rsw.idx0 = src.idx;      op->rsw.neg = neg;      op->rsw.swz = swz;	          retval.file = FILE_REG;      retval.idx = dst;      return retval;   }   else if (force) {      /* Oops.  Degenerate case:       */      union instruction *op = cvp_next_instruction(cp);      op->alu.opcode = OPCODE_MOV;      op->alu.dst = dst;      op->alu.file0 = src.file;      op->alu.idx0 = src.idx;            retval.file = FILE_REG;      retval.idx = dst;      return retval;   }   else {      return src;   }}static void cvp_emit_inst( struct compilation *cp,			   const struct prog_instruction *inst ){   union instruction *op;   union instruction fixup;   struct reg reg[3];   GLuint result, nr_args, i;   /* Need to handle SWZ, ARL specially.    */   switch (inst->Opcode) {      /* Split into mul and add:       */   case OPCODE_MAD:      result = cvp_choose_result( cp, &inst->DstReg, &fixup );      for (i = 0; i < 3; i++) 	 reg[i] = cvp_emit_arg( cp, &inst->SrcReg[i], REG_ARG0+i );      op = cvp_next_instruction(cp);      op->alu.opcode = OPCODE_MUL;      op->alu.file0 = reg[0].file;      op->alu.idx0 = reg[0].idx;      op->alu.file1 = reg[1].file;      op->alu.idx1 = reg[1].idx;      op->alu.dst = REG_ARG0;      op = cvp_next_instruction(cp);      op->alu.opcode = OPCODE_ADD;      op->alu.file0 = FILE_REG;      op->alu.idx0 = REG_ARG0;      op->alu.file1 = reg[2].file;      op->alu.idx1 = reg[2].idx;      op->alu.dst = result;      if (result == REG_RES) {	 op = cvp_next_instruction(cp);	 *op = fixup;      }      break;   case OPCODE_ARL:      reg[0] = cvp_emit_arg( cp, &inst->SrcReg[0], REG_ARG0 );      op = cvp_next_instruction(cp);      op->alu.opcode = OPCODE_FLR;      op->alu.dst = REG_ADDR;      op->alu.file0 = reg[0].file;      op->alu.idx0 = reg[0].idx;      break;   case OPCODE_SWZ: {      GLuint swz0 = 0, swz1 = 0;      GLuint neg0 = 0, neg1 = 0;      GLuint mask = 0;      /* Translate 3-bit-per-element swizzle into two 2-bit swizzles,       * one from the source register the other from a constant       * {0,0,0,1}.       */      for (i = 0; i < 4; i++) {	 GLuint swzelt = GET_SWZ(inst->SrcReg[0].Swizzle, i);	 if (swzelt >= SWIZZLE_ZERO) {	    neg0 |= inst->SrcReg[0].NegateBase & (1<<i);	    if (swzelt == SWIZZLE_ONE)	       swz0 |= SWIZZLE_W << (i*2);	    else if (i < SWIZZLE_W)	       swz0 |= i << (i*2);	 }	 else {	    mask |= 1<<i;	    neg1 |= inst->SrcReg[0].NegateBase & (1<<i);	    swz1 |= swzelt << (i*2);	 }      }      result = cvp_choose_result( cp, &inst->DstReg, &fixup );      reg[0].file = FILE_REG;      reg[0].idx = REG_ID;      reg[1] = cvp_emit_arg( cp, &inst->SrcReg[0], REG_ARG0 );      if (mask == WRITEMASK_XYZW) {	 cvp_emit_rsw(cp, result, reg[0], neg0, swz0, GL_TRUE);	       }      else if (mask == 0) {	 cvp_emit_rsw(cp, result, reg[1], neg1, swz1, GL_TRUE);      }      else {	 cvp_emit_rsw(cp, result, reg[0], neg0, swz0, GL_TRUE);	 reg[1] = cvp_emit_rsw(cp, REG_ARG0, reg[1], neg1, swz1, GL_FALSE);	 op = cvp_next_instruction(cp);	 op->msk.opcode = MSK;	 op->msk.dst = result;	 op->msk.file = reg[1].file;	 op->msk.idx = reg[1].idx;	 op->msk.mask = mask;      }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?