⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t_vb_arbprogram.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
}


static void do_XPD( struct arb_vp_machine *m, union instruction op ) 
{
   GLfloat *result = m->File[0][op.alu.dst];
   const GLfloat *arg0 = m->File[op.alu.file0][op.alu.idx0];
   const GLfloat *arg1 = m->File[op.alu.file1][op.alu.idx1];

   result[0] = arg0[1] * arg1[2] - arg0[2] * arg1[1];
   result[1] = arg0[2] * arg1[0] - arg0[0] * arg1[2];
   result[2] = arg0[0] * arg1[1] - arg0[1] * arg1[0];
}

static void do_NOP( struct arb_vp_machine *m, union instruction op ) 
{
}

/* Some useful debugging functions:
 */
static void print_mask( GLuint mask )
{
   _mesa_printf(".");
   if (mask&0x1) _mesa_printf("x");
   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, const struct opcode_info *info )
{
   GLuint swz = op.rsw.swz;
   GLuint neg = op.rsw.neg;
   GLuint i;

   _mesa_printf("%s ", info->string);
   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, const struct opcode_info *info )
{
   _mesa_printf("%s ", info->string);
   print_reg(0, op.alu.dst);
   _mesa_printf(", ");
   print_reg(op.alu.file0, op.alu.idx0);
   if (info->nr_args > 1) {
      _mesa_printf(", ");
      print_reg(op.alu.file1, op.alu.idx1);
   }
   _mesa_printf("\n");
}

static void print_MSK( union instruction op, const struct opcode_info *info )
{
   _mesa_printf("%s ", info->string);
   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, const struct opcode_info *info )
{
}

#define NOP 0
#define ALU 1
#define SWZ 2

static const struct opcode_info opcode_info[] = 
{
   { 1, "ABS", print_ALU },
   { 2, "ADD", print_ALU },
   { 1, "ARL", print_NOP },
   { 2, "DP3", print_ALU },
   { 2, "DP4", print_ALU },
   { 2, "DPH", print_ALU },
   { 2, "DST", print_ALU },
   { 0, "END", print_NOP },
   { 1, "EX2", print_ALU },
   { 1, "EXP", print_ALU },
   { 1, "FLR", print_ALU },
   { 1, "FRC", print_ALU },
   { 1, "LG2", print_ALU },
   { 1, "LIT", print_ALU },
   { 1, "LOG", print_ALU },
   { 3, "MAD", print_NOP },
   { 2, "MAX", print_ALU },
   { 2, "MIN", print_ALU },
   { 1, "MOV", print_ALU },
   { 2, "MUL", print_ALU },
   { 2, "POW", print_ALU },
   { 1, "PRT", print_ALU }, /* PRINT */
   { 1, "RCC", print_NOP },
   { 1, "RCP", print_ALU },
   { 1, "RSQ", print_ALU },
   { 2, "SGE", print_ALU },
   { 2, "SLT", print_ALU },
   { 2, "SUB", print_ALU },
   { 1, "SWZ", print_NOP },
   { 2, "XPD", print_ALU },
   { 1, "RSW", print_RSW },
   { 2, "MSK", print_MSK },
   { 1, "REL", print_ALU },
};

void _tnl_disassem_vba_insn( union instruction op )
{
   const struct opcode_info *info = &opcode_info[op.alu.opcode];
   info->print( op, info );
}


static void (* const opcode_func[])(struct arb_vp_machine *, union instruction) = 
{
   do_ABS,
   do_ADD,
   do_NOP,
   do_DP3,
   do_DP4,
   do_DPH,
   do_DST,
   do_NOP,
   do_EX2,
   do_EXP,
   do_FLR,
   do_FRC,
   do_LG2,
   do_LIT,
   do_LOG,
   do_NOP,
   do_MAX,
   do_MIN,
   do_MOV,
   do_MUL,
   do_POW,
   do_PRT,
   do_NOP,
   do_RCP,
   do_RSQ,
   do_SGE,
   do_SLT,
   do_SUB,
   do_RSW,
   do_XPD,
   do_RSW,
   do_MSK,
   do_REL,
};

static union instruction *cvp_next_instruction( struct compilation *cp )
{
   union instruction *op = cp->csr++;
   op->dword = 0;
   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:
      assert(0);
      return tmpreg;		/* can't happen */
   }
}

static struct reg cvp_emit_arg( struct compilation *cp,
				const struct vp_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.  
    */
   rsw.dword = 0;
   rsw.rsw.neg = src->Negate ? WRITEMASK_XYZW : 0;
   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));

   noop.dword = 0;
   noop.rsw.neg = 0;
   noop.rsw.swz = RSW_NOOP;

   if (rsw.dword != noop.dword) {
      union instruction *op = cvp_next_instruction(cp);
      struct reg rsw_reg = cvp_make_reg(FILE_REG, REG_ARG0 + arg);
      op->dword = rsw.dword;
      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 vp_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 {
      fixup->dword = 0;
      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 = VP_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 vp_instruction *inst )
{
   const struct opcode_info *info = &opcode_info[inst->Opcode];
   union instruction *op;
   union instruction fixup;
   struct reg reg[3];
   GLuint result, i;

   assert(sizeof(*op) == sizeof(GLuint));

   /* Need to handle SWZ, ARL specially.
    */
   switch (inst->Opcode) {
      /* Split into mul and add:
       */
   case VP_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 = VP_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 = VP_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->dword = fixup.dword;
      }
      break;

   case VP_OPCODE_ARL:
      reg[0] = cvp_emit_arg( cp, &inst->SrcReg[0], REG_ARG0 );

      op = cvp_next_instruction(cp);
      op->alu.opcode = VP_OPCODE_FLR;
      op->alu.dst = REG_ADDR;
      op->alu.file0 = reg[0].file;
      op->alu.idx0 = reg[0].idx;
      break;

   case VP_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].Negate & (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].Negate & (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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -