static void c_node_dump(struct c_node *node, unsigned indent)
{
struct c_instruction *i;
- unsigned j;
+ unsigned j, k;
pindent(indent); fprintf(stderr, "# node %s\n", c_get_name(c_opcode_str, node->opcode));
c_list_for_each(i, &node->insts) {
- pindent(indent); fprintf(stderr, "%s", c_get_name(c_opcode_str, i->opcode));
- fprintf(stderr, " %s[%d][%s%s%s%s]",
- c_get_name(c_file_str, i->output.vector->file),
- i->output.vector->id,
- c_get_name(c_file_swz, i->output.swizzle[0]),
- c_get_name(c_file_swz, i->output.swizzle[1]),
- c_get_name(c_file_swz, i->output.swizzle[2]),
- c_get_name(c_file_swz, i->output.swizzle[3]));
- for (j = 0; j < i->ninput; j++) {
- fprintf(stderr, " %s[%d][%s%s%s%s]",
- c_get_name(c_file_str, i->input[j].vector->file),
- i->input[j].vector->id,
- c_get_name(c_file_swz, i->input[j].swizzle[0]),
- c_get_name(c_file_swz, i->input[j].swizzle[1]),
- c_get_name(c_file_swz, i->input[j].swizzle[2]),
- c_get_name(c_file_swz, i->input[j].swizzle[3]));
+ for (k = 0; k < i->nop; k++) {
+ pindent(indent);
+ fprintf(stderr, "%s", c_get_name(c_opcode_str, i->op[k].opcode));
+ fprintf(stderr, " %s[%d][%s]",
+ c_get_name(c_file_str, i->op[k].output.vector->file),
+ i->op[k].output.vector->id,
+ c_get_name(c_file_swz, i->op[k].output.swizzle));
+ for (j = 0; j < i->op[k].ninput; j++) {
+ fprintf(stderr, " %s[%d][%s]",
+ c_get_name(c_file_str, i->op[k].input[j].vector->file),
+ i->op[k].input[j].vector->id,
+ c_get_name(c_file_swz, i->op[k].input[j].swizzle));
+ }
+ fprintf(stderr, ";\n");
}
- fprintf(stderr, ";\n");
}
}
if (vr == NULL)
return -ENOMEM;
memset(&instruction, 0, sizeof(struct c_instruction));
- instruction.opcode = C_OPCODE_VFETCH;
- instruction.write_mask = 0xF;
- instruction.ninput = 2;
- instruction.output.vector = v;
- instruction.input[0].vector = vi;
- instruction.input[1].vector = vr;
- instruction.output.swizzle[0] = C_SWIZZLE_X;
- instruction.output.swizzle[1] = C_SWIZZLE_Y;
- instruction.output.swizzle[2] = C_SWIZZLE_Z;
- instruction.output.swizzle[3] = C_SWIZZLE_W;
+ instruction.nop = 4;
+ instruction.op[0].opcode = C_OPCODE_VFETCH;
+ instruction.op[1].opcode = C_OPCODE_VFETCH;
+ instruction.op[2].opcode = C_OPCODE_VFETCH;
+ instruction.op[3].opcode = C_OPCODE_VFETCH;
+ instruction.op[0].ninput = 2;
+ instruction.op[1].ninput = 2;
+ instruction.op[2].ninput = 2;
+ instruction.op[3].ninput = 2;
+ instruction.op[0].output.vector = v;
+ instruction.op[1].output.vector = v;
+ instruction.op[2].output.vector = v;
+ instruction.op[3].output.vector = v;
+ instruction.op[0].input[0].vector = vi;
+ instruction.op[0].input[1].vector = vr;
+ instruction.op[1].input[0].vector = vi;
+ instruction.op[1].input[1].vector = vr;
+ instruction.op[2].input[0].vector = vi;
+ instruction.op[2].input[1].vector = vr;
+ instruction.op[3].input[0].vector = vi;
+ instruction.op[3].input[1].vector = vr;
+ instruction.op[0].output.swizzle = C_SWIZZLE_X;
+ instruction.op[1].output.swizzle = C_SWIZZLE_Y;
+ instruction.op[2].output.swizzle = C_SWIZZLE_Z;
+ instruction.op[3].output.swizzle = C_SWIZZLE_W;
r = c_node_add_new_instruction_head(&shader->entry, &instruction);
if (r)
return r;
if (instruction == NULL)
return 0;
- if (instruction->opcode != C_OPCODE_VFETCH)
+ if (instruction->op[0].opcode != C_OPCODE_VFETCH)
return 0;
if (!c_list_empty(&node->alu)) {
rnode = r600_shader_new_node(rshader, node->node);
vfetch = calloc(1, sizeof(struct r600_shader_vfetch));
if (vfetch == NULL)
return -ENOMEM;
- r = r600_shader_find_gpr(rshader, instruction->output.vector, 0, &vfetch->dst[0]);
+ r = r600_shader_find_gpr(rshader, instruction->op[0].output.vector, 0, &vfetch->dst[0]);
if (r)
return r;
- r = r600_shader_find_gpr(rshader, instruction->input[0].vector, 0, &vfetch->src[0]);
+ r = r600_shader_find_gpr(rshader, instruction->op[0].input[0].vector, 0, &vfetch->src[0]);
if (r)
return r;
- r = r600_shader_find_gpr(rshader, instruction->input[1].vector, 0, &vfetch->src[1]);
+ r = r600_shader_find_gpr(rshader, instruction->op[0].input[1].vector, 0, &vfetch->src[1]);
if (r)
return r;
vfetch->dst[0].chan = C_SWIZZLE_X;
if (rnode == NULL)
return -ENOMEM;
c_list_for_each(instruction, &node->insts) {
- switch (instruction->opcode) {
+ switch (instruction->op[0].opcode) {
case C_OPCODE_VFETCH:
r = r600_shader_add_vfetch(rshader, rnode, instruction);
if (r) {
return alu;
}
-static int r600_shader_node_add_alu(struct r600_shader *rshader,
- struct r600_shader_node *node,
- struct r600_shader_alu *alu,
- unsigned instruction,
- unsigned ninput,
- struct r600_shader_operand *dst,
- struct r600_shader_operand src[3])
-{
- struct r600_shader_alu *nalu;
- unsigned nconstant = 0, nliteral = 0, slot, i;
-
- /* count number of constant & literal */
- for (i = 0; i < ninput; i++) {
- if (src[i].vector->file == C_FILE_IMMEDIATE) {
- nliteral++;
- nconstant++;
- }
- }
-
- slot = dst->chan;
- if (r600_instruction_info[instruction].is_trans) {
- slot = 4;
- }
-
- /* allocate new alu group if necessary */
- nalu = alu;
- if (alu == NULL) {
- nalu = r600_shader_insert_alu(rshader, node);
- if (nalu == NULL)
- return -ENOMEM;
- alu = nalu;
- }
- if ((alu->alu[slot].inst != INST_NOP &&
- alu->alu[4].inst != INST_NOP) ||
- (alu->nconstant + nconstant) > 4 ||
- (alu->nliteral + nliteral) > 4) {
- /* neither trans neither dst slot are free need new alu */
- nalu = r600_shader_insert_alu(rshader, node);
- if (nalu == NULL)
- return -ENOMEM;
- alu = nalu;
- }
- if (alu->alu[slot].inst != INST_NOP) {
- slot = 4;
- }
-
- alu->alu[slot].dst = *dst;
- alu->alu[slot].inst = instruction;
- alu->alu[slot].opcode = r600_instruction_info[instruction].opcode;
- alu->alu[slot].is_op3 = r600_instruction_info[instruction].is_op3;
- for (i = 0; i < ninput; i++) {
- alu->alu[slot].src[i] = src[i];
- if (src[i].vector->file == C_FILE_IMMEDIATE) {
- alu->literal[alu->nliteral++] = src[i].vector->channel[0]->value;
- alu->literal[alu->nliteral++] = src[i].vector->channel[1]->value;
- alu->literal[alu->nliteral++] = src[i].vector->channel[2]->value;
- alu->literal[alu->nliteral++] = src[i].vector->channel[3]->value;
- }
- }
- return 0;
-}
-
static int r600_shader_alu_translate(struct r600_shader *rshader,
struct r600_shader_node *node,
struct c_instruction *instruction)
{
- struct r600_alu_instruction *ainfo = &r600_alu_instruction[instruction->opcode];
- struct r600_instruction_info *info;
- struct r600_shader_alu *alu;
struct r600_shader_node *rnode;
- int r, i, j;
- struct r600_shader_operand dst;
- struct r600_shader_operand src[3];
+ struct r600_shader_alu *alu;
+ int i, j, r, comp;
if (!c_list_empty(&node->vfetch)) {
rnode = r600_shader_new_node(rshader, node->node);
}
node = rnode;
}
+
+ /* initialize alu */
alu = r600_shader_insert_alu(rshader, node);
- if (alu == NULL) {
- fprintf(stderr, "%s %d instert alu node failed\n", __func__, __LINE__);
- return -ENOMEM;
- }
- for (i = 0; i < 4; i++) {
- if (!(instruction->write_mask) || instruction->output.swizzle[i] == C_SWIZZLE_D)
- continue;
- if (ainfo->instruction == INST_NOP) {
- fprintf(stderr, "%s:%d unsupported instruction %d\n", __FILE__, __LINE__, instruction->opcode);
- continue;
- }
- info = &r600_instruction_info[ainfo->instruction];
- r = r600_shader_find_gpr(rshader, instruction->output.vector,
- instruction->output.swizzle[i], &dst);
- if (r) {
- fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
- return r;
+
+ /* check special operation like lit */
+
+ /* go through operation */
+ for (i = 0; i < instruction->nop; i++) {
+ struct r600_alu_instruction *ainfo = &r600_alu_instruction[instruction->op[i].opcode];
+ struct r600_instruction_info *iinfo = &r600_instruction_info[ainfo->instruction];
+ unsigned comp;
+
+ /* check that output is a valid component */
+ comp = instruction->op[i].output.swizzle;
+ switch (comp) {
+ case C_SWIZZLE_X:
+ case C_SWIZZLE_Y:
+ case C_SWIZZLE_Z:
+ case C_SWIZZLE_W:
+ break;
+ case C_SWIZZLE_0:
+ case C_SWIZZLE_1:
+ default:
+ fprintf(stderr, "%s %d invalid output\n", __func__, __LINE__);
+ return -EINVAL;
}
- for (j = 0; j < instruction->ninput; j++) {
- r = r600_shader_find_gpr(rshader, instruction->input[j].vector,
- instruction->input[j].swizzle[i], &src[j]);
+ alu->alu[comp].inst = ainfo->instruction;
+ alu->alu[comp].opcode = iinfo->opcode;
+ alu->alu[comp].is_op3 = iinfo->is_op3;
+ for (j = 0; j < instruction->op[i].ninput; j++) {
+ r = r600_shader_find_gpr(rshader, instruction->op[i].input[j].vector,
+ instruction->op[i].input[j].swizzle, &alu->alu[comp].src[j]);
if (r) {
fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
return r;
}
}
- r = r600_shader_node_add_alu(rshader, node, alu, ainfo->instruction,
- instruction->ninput, &dst, src);
+ r = r600_shader_find_gpr(rshader, instruction->op[i].output.vector,
+ instruction->op[i].output.swizzle, &alu->alu[comp].dst);
if (r) {
- fprintf(stderr, "%s %d failed\n", __FILE__, __LINE__);
+ fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
return r;
}
}
+ for (i = instruction->nop; i >= 0; i--) {
+ if (alu->alu[i].inst != INST_NOP) {
+ alu->alu[i].last = 1;
+ alu->nalu = i + 1;
+ break;
+ }
+ }
return 0;
}
struct r600_shader_node *node, *nnode;
struct r600_shader_alu *alu, *nalu;
+#if 0
c_list_for_each_safe(node, nnode, &rshader->nodes) {
c_list_for_each_safe(alu, nalu, &node->alu) {
alu->nalu = 5;
alu->alu[4].last = 1;
}
}
+#endif
return 0;
}
struct c_shader *shader = ts->shader;
struct c_instruction instruction;
unsigned opcode;
- int i, r;
+ int i, j, r;
if (fi->Instruction.NumDstRegs > 1) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
}
/* FIXME add flow instruction handling */
memset(&instruction, 0, sizeof(struct c_instruction));
- instruction.opcode = opcode;
- instruction.ninput = fi->Instruction.NumSrcRegs;
- instruction.write_mask = fi->Dst[0].Register.WriteMask;
- for (i = 0; i < fi->Instruction.NumSrcRegs; i++) {
- instruction.input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index];
- instruction.input[i].swizzle[0] = fi->Src[i].Register.SwizzleX;
- instruction.input[i].swizzle[1] = fi->Src[i].Register.SwizzleY;
- instruction.input[i].swizzle[2] = fi->Src[i].Register.SwizzleZ;
- instruction.input[i].swizzle[3] = fi->Src[i].Register.SwizzleW;
+ instruction.nop = 0;
+ for (j = 0; j < 4; j++) {
+ instruction.op[instruction.nop].opcode = opcode;
+ instruction.op[instruction.nop].ninput = fi->Instruction.NumSrcRegs;
+ for (i = 0; i < fi->Instruction.NumSrcRegs; i++) {
+ instruction.op[instruction.nop].input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index];
+ switch (j) {
+ case 0:
+ instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleX;
+ break;
+ case 1:
+ instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleY;
+ break;
+ case 2:
+ instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleZ;
+ break;
+ case 3:
+ instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleW;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ instruction.op[instruction.nop].output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index];
+ switch (j) {
+ case 0:
+ instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D;
+ break;
+ case 1:
+ instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Y : C_SWIZZLE_D;
+ break;
+ case 2:
+ instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Z : C_SWIZZLE_D;
+ break;
+ case 3:
+ instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_W : C_SWIZZLE_D;
+ break;
+ default:
+ return -EINVAL;
+ }
+ instruction.nop++;
}
- instruction.output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index];
- instruction.output.swizzle[0] = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D;
- instruction.output.swizzle[1] = (fi->Dst[0].Register.WriteMask & 0x2) ? C_SWIZZLE_Y : C_SWIZZLE_D;
- instruction.output.swizzle[2] = (fi->Dst[0].Register.WriteMask & 0x4) ? C_SWIZZLE_Z : C_SWIZZLE_D;
- instruction.output.swizzle[3] = (fi->Dst[0].Register.WriteMask & 0x8) ? C_SWIZZLE_W : C_SWIZZLE_D;
return c_node_add_new_instruction(ts->node, &instruction);
}