📄 t_vb_arbprogram.c
字号:
}
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 + -