r600g: drop compiler stuff and switch over dumb tgsi assembler

Writing a compiler is time consuming and error prone in
order to allow r600g to further progress in the meantime
i wrote a simple tgsi assembler, it does stupid thing but
i would rather keep the code simple than having people
trying to optimize code it does.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
This commit is contained in:
Jerome Glisse 2010-07-23 17:32:32 -04:00
parent 9a12a3925a
commit de553d906b
16 changed files with 1286 additions and 3332 deletions

View File

@ -18,10 +18,7 @@ C_SOURCES = \
r600_state.c \
r600_texture.c \
r600_shader.c \
r600_compiler.c \
r600_compiler_tgsi.c \
r600_compiler_dump.c \
r600_compiler_r600.c \
r600_compiler_r700.c
r600_asm.c \
r700_asm.c
include ../../Makefile.template

View File

@ -0,0 +1,385 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "r600_asm.h"
#include "r600_context.h"
#include "util/u_memory.h"
#include "r600_sq.h"
#include <stdio.h>
#include <errno.h>
int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id);
static struct r600_bc_cf *r600_bc_cf(void)
{
struct r600_bc_cf *cf = CALLOC_STRUCT(r600_bc_cf);
if (cf == NULL)
return NULL;
LIST_INITHEAD(&cf->list);
LIST_INITHEAD(&cf->alu);
LIST_INITHEAD(&cf->vtx);
return cf;
}
static struct r600_bc_alu *r600_bc_alu(void)
{
struct r600_bc_alu *alu = CALLOC_STRUCT(r600_bc_alu);
if (alu == NULL)
return NULL;
LIST_INITHEAD(&alu->list);
return alu;
}
static struct r600_bc_vtx *r600_bc_vtx(void)
{
struct r600_bc_vtx *vtx = CALLOC_STRUCT(r600_bc_vtx);
if (vtx == NULL)
return NULL;
LIST_INITHEAD(&vtx->list);
return vtx;
}
int r600_bc_init(struct r600_bc *bc, enum radeon_family family)
{
LIST_INITHEAD(&bc->cf);
bc->family = family;
return 0;
}
static int r600_bc_add_cf(struct r600_bc *bc)
{
struct r600_bc_cf *cf = r600_bc_cf();
if (cf == NULL)
return -ENOMEM;
LIST_ADDTAIL(&cf->list, &bc->cf);
if (bc->cf_last)
cf->id = bc->cf_last->id + 2;
bc->cf_last = cf;
bc->ncf++;
bc->ndw += 2;
return 0;
}
int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output)
{
int r;
r = r600_bc_add_cf(bc);
if (r)
return r;
bc->cf_last->inst = output->inst;
memcpy(&bc->cf_last->output, output, sizeof(struct r600_bc_output));
return 0;
}
int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu)
{
struct r600_bc_alu *nalu = r600_bc_alu();
struct r600_bc_alu *lalu;
int i, r;
if (nalu == NULL)
return -ENOMEM;
memcpy(nalu, alu, sizeof(struct r600_bc_alu));
nalu->nliteral = 0;
/* cf can contains only alu or only vtx or only tex */
if (bc->cf_last == NULL || bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3)) {
r = r600_bc_add_cf(bc);
if (r) {
free(nalu);
return r;
}
bc->cf_last->inst = V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3;
}
/* number of gpr == the last gpr used in any alu */
for (i = 0; i < 3; i++) {
if (alu->src[i].sel >= bc->ngpr && alu->src[i].sel < 128) {
bc->ngpr = alu->src[i].sel + 1;
}
/* compute how many literal are needed
* either 2 or 4 literals
*/
if (alu->src[i].sel == 253) {
if (((alu->src[i].chan + 2) & 0x6) > nalu->nliteral) {
nalu->nliteral = (alu->src[i].chan + 2) & 0x6;
}
}
}
if (!LIST_IS_EMPTY(&bc->cf_last->alu)) {
lalu = LIST_ENTRY(struct r600_bc_alu, bc->cf_last->alu.prev, list);
if (!lalu->last && lalu->nliteral > nalu->nliteral) {
nalu->nliteral = lalu->nliteral;
}
}
if (alu->dst.sel >= bc->ngpr) {
bc->ngpr = alu->dst.sel + 1;
}
LIST_ADDTAIL(&nalu->list, &bc->cf_last->alu);
/* each alu use 2 dwords */
bc->cf_last->ndw += 2;
bc->ndw += 2;
return 0;
}
int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
{
struct r600_bc_alu *alu;
if (bc->cf_last == NULL ||
bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3) ||
LIST_IS_EMPTY(&bc->cf_last->alu)) {
R600_ERR("last CF is not ALU (%p)\n", bc->cf_last);
return -EINVAL;
}
alu = LIST_ENTRY(struct r600_bc_alu, bc->cf_last->alu.prev, list);
if (!alu->last || !alu->nliteral) {
return 0;
}
memcpy(alu->value, value, 4 * 4);
bc->cf_last->ndw += alu->nliteral;
bc->ndw += alu->nliteral;
return 0;
}
int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx)
{
struct r600_bc_vtx *nvtx = r600_bc_vtx();
int r;
if (nvtx == NULL)
return -ENOMEM;
memcpy(nvtx, vtx, sizeof(struct r600_bc_vtx));
/* cf can contains only alu or only vtx or only tex */
if (bc->cf_last == NULL ||
(bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_VTX &&
bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC)) {
r = r600_bc_add_cf(bc);
if (r) {
free(nvtx);
return r;
}
bc->cf_last->inst = V_SQ_CF_WORD1_SQ_CF_INST_VTX;
}
LIST_ADDTAIL(&nvtx->list, &bc->cf_last->vtx);
/* each fetch use 6 dwords */
bc->cf_last->ndw += 4;
bc->ndw += 4;
return 0;
}
int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsigned id)
{
bc->bytecode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vtx->buffer_id) |
S_SQ_VTX_WORD0_SRC_GPR(vtx->src_gpr) |
S_SQ_VTX_WORD0_SRC_SEL_X(vtx->src_sel_x) |
S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(vtx->mega_fetch_count);
bc->bytecode[id++] = S_SQ_VTX_WORD1_DST_SEL_X(vtx->dst_sel_x) |
S_SQ_VTX_WORD1_DST_SEL_Y(vtx->dst_sel_y) |
S_SQ_VTX_WORD1_DST_SEL_Z(vtx->dst_sel_z) |
S_SQ_VTX_WORD1_DST_SEL_W(vtx->dst_sel_w) |
S_SQ_VTX_WORD1_USE_CONST_FIELDS(1) |
S_SQ_VTX_WORD1_GPR_DST_GPR(vtx->dst_gpr);
bc->bytecode[id++] = S_SQ_VTX_WORD2_MEGA_FETCH(1);
bc->bytecode[id++] = 0;
return 0;
}
int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id)
{
unsigned i;
/* don't replace gpr by pv or ps for destination register */
if (alu->is_op3) {
bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_LAST(alu->last);
bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
S_SQ_ALU_WORD1_OP3_ALU_INST(alu->inst) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
} else {
bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
S_SQ_ALU_WORD0_LAST(alu->last);
bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) |
S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
}
if (alu->last) {
for (i = 0; i < alu->nliteral; i++) {
bc->bytecode[id++] = alu->value[i];
}
}
return 0;
}
int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
{
unsigned id = cf->id;
switch (cf->inst) {
case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
bc->bytecode[id++] = S_SQ_CF_ALU_WORD0_ADDR(cf->addr >> 1);
bc->bytecode[id++] = S_SQ_CF_ALU_WORD1_CF_INST(cf->inst >> 3) |
S_SQ_CF_ALU_WORD1_BARRIER(1) |
S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1);
break;
case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->addr >> 1);
bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) |
S_SQ_CF_WORD1_BARRIER(1) |
S_SQ_CF_WORD1_COUNT((cf->ndw / 4) - 1);
break;
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR(cf->output.gpr) |
S_SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE(cf->output.elem_size) |
S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(cf->output.array_base) |
S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(cf->output.type);
bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(cf->output.swizzle_x) |
S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y(cf->output.swizzle_y) |
S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z(cf->output.swizzle_z) |
S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W(cf->output.swizzle_w) |
S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(cf->output.barrier) |
S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(cf->output.inst) |
S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(cf->output.end_of_program);
break;
default:
R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
return -EINVAL;
}
return 0;
}
int r600_bc_build(struct r600_bc *bc)
{
struct r600_bc_cf *cf;
struct r600_bc_alu *alu;
struct r600_bc_vtx *vtx;
unsigned addr;
int r;
/* first path compute addr of each CF block */
/* addr start after all the CF instructions */
addr = bc->cf_last->id + 2;
LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
switch (cf->inst) {
case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
break;
case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
/* fetch node need to be 16 bytes aligned*/
addr += 3;
addr &= 0xFFFFFFFCUL;
break;
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
break;
default:
R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
return -EINVAL;
}
cf->addr = addr;
addr += cf->ndw;
bc->ndw = cf->addr + cf->ndw;
}
free(bc->bytecode);
bc->bytecode = calloc(1, bc->ndw * 4);
if (bc->bytecode == NULL)
return -ENOMEM;
LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
addr = cf->addr;
r = r600_bc_cf_build(bc, cf);
if (r)
return r;
switch (cf->inst) {
case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) {
switch (bc->family) {
case CHIP_R600:
case CHIP_RV610:
case CHIP_RV630:
case CHIP_RV670:
case CHIP_RV620:
case CHIP_RV635:
case CHIP_RS780:
case CHIP_RS880:
r = r600_bc_alu_build(bc, alu, addr);
break;
case CHIP_RV770:
case CHIP_RV730:
case CHIP_RV710:
case CHIP_RV740:
r = r700_bc_alu_build(bc, alu, addr);
break;
default:
R600_ERR("unknown family %d\n", bc->family);
return -EINVAL;
}
if (r)
return r;
addr += 2;
if (alu->last) {
addr += alu->nliteral;
}
}
break;
case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) {
r = r600_bc_vtx_build(bc, vtx, addr);
if (r)
return r;
addr += 4;
}
break;
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
break;
default:
R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
return -EINVAL;
}
}
return 0;
}

View File

@ -0,0 +1,112 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef R600_ASM_H
#define R600_ASM_H
#include "radeon.h"
#include "util/u_double_list.h"
struct r600_bc_alu_src {
unsigned sel;
unsigned chan;
unsigned neg;
unsigned abs;
};
struct r600_bc_alu_dst {
unsigned sel;
unsigned chan;
unsigned clamp;
unsigned write;
};
struct r600_bc_alu {
struct list_head list;
struct r600_bc_alu_src src[3];
struct r600_bc_alu_dst dst;
unsigned inst;
unsigned last;
unsigned is_op3;
unsigned nliteral;
u32 value[4];
};
struct r600_bc_vtx {
struct list_head list;
unsigned inst;
unsigned fetch_type;
unsigned buffer_id;
unsigned src_gpr;
unsigned src_sel_x;
unsigned mega_fetch_count;
unsigned dst_gpr;
unsigned dst_sel_x;
unsigned dst_sel_y;
unsigned dst_sel_z;
unsigned dst_sel_w;
};
struct r600_bc_output {
unsigned array_base;
unsigned type;
unsigned end_of_program;
unsigned inst;
unsigned elem_size;
unsigned gpr;
unsigned swizzle_x;
unsigned swizzle_y;
unsigned swizzle_z;
unsigned swizzle_w;
unsigned barrier;
};
struct r600_bc_cf {
struct list_head list;
unsigned inst;
unsigned addr;
unsigned ndw;
unsigned id;
struct list_head alu;
struct list_head vtx;
struct r600_bc_output output;
};
struct r600_bc {
enum radeon_family family;
struct list_head cf;
struct r600_bc_cf *cf_last;
unsigned ndw;
unsigned ncf;
unsigned ngpr;
unsigned nresource;
u32 *bytecode;
};
int r600_bc_init(struct r600_bc *bc, enum radeon_family family);
int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu);
int r600_bc_add_literal(struct r600_bc *bc, const u32 *value);
int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx);
int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output);
int r600_bc_build(struct r600_bc *bc);
#endif

View File

@ -1,447 +0,0 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include "r600_compiler.h"
struct c_vector *c_vector_new(void)
{
struct c_vector *v = calloc(1, sizeof(struct c_vector));
if (v == NULL) {
return NULL;
}
LIST_INITHEAD(&v->head);
return v;
}
static unsigned c_opcode_is_alu(unsigned opcode)
{
switch (opcode) {
case C_OPCODE_MOV:
case C_OPCODE_MUL:
case C_OPCODE_MAD:
case C_OPCODE_ARL:
case C_OPCODE_LIT:
case C_OPCODE_RCP:
case C_OPCODE_RSQ:
case C_OPCODE_EXP:
case C_OPCODE_LOG:
case C_OPCODE_ADD:
case C_OPCODE_DP3:
case C_OPCODE_DP4:
case C_OPCODE_DST:
case C_OPCODE_MIN:
case C_OPCODE_MAX:
case C_OPCODE_SLT:
case C_OPCODE_SGE:
case C_OPCODE_SUB:
case C_OPCODE_LRP:
case C_OPCODE_CND:
case C_OPCODE_DP2A:
case C_OPCODE_FRC:
case C_OPCODE_CLAMP:
case C_OPCODE_FLR:
case C_OPCODE_ROUND:
case C_OPCODE_EX2:
case C_OPCODE_LG2:
case C_OPCODE_POW:
case C_OPCODE_XPD:
case C_OPCODE_ABS:
case C_OPCODE_RCC:
case C_OPCODE_DPH:
case C_OPCODE_COS:
case C_OPCODE_DDX:
case C_OPCODE_DDY:
case C_OPCODE_PK2H:
case C_OPCODE_PK2US:
case C_OPCODE_PK4B:
case C_OPCODE_PK4UB:
case C_OPCODE_RFL:
case C_OPCODE_SEQ:
case C_OPCODE_SFL:
case C_OPCODE_SGT:
case C_OPCODE_SIN:
case C_OPCODE_SLE:
case C_OPCODE_SNE:
case C_OPCODE_STR:
case C_OPCODE_UP2H:
case C_OPCODE_UP2US:
case C_OPCODE_UP4B:
case C_OPCODE_UP4UB:
case C_OPCODE_X2D:
case C_OPCODE_ARA:
case C_OPCODE_ARR:
case C_OPCODE_BRA:
case C_OPCODE_SSG:
case C_OPCODE_CMP:
case C_OPCODE_SCS:
case C_OPCODE_NRM:
case C_OPCODE_DIV:
case C_OPCODE_DP2:
case C_OPCODE_CEIL:
case C_OPCODE_I2F:
case C_OPCODE_NOT:
case C_OPCODE_TRUNC:
case C_OPCODE_SHL:
case C_OPCODE_AND:
case C_OPCODE_OR:
case C_OPCODE_MOD:
case C_OPCODE_XOR:
case C_OPCODE_SAD:
case C_OPCODE_NRM4:
case C_OPCODE_F2I:
case C_OPCODE_IDIV:
case C_OPCODE_IMAX:
case C_OPCODE_IMIN:
case C_OPCODE_INEG:
case C_OPCODE_ISGE:
case C_OPCODE_ISHR:
case C_OPCODE_ISLT:
case C_OPCODE_F2U:
case C_OPCODE_U2F:
case C_OPCODE_UADD:
case C_OPCODE_UDIV:
case C_OPCODE_UMAD:
case C_OPCODE_UMAX:
case C_OPCODE_UMIN:
case C_OPCODE_UMOD:
case C_OPCODE_UMUL:
case C_OPCODE_USEQ:
case C_OPCODE_USGE:
case C_OPCODE_USHR:
case C_OPCODE_USLT:
case C_OPCODE_USNE:
return 1;
case C_OPCODE_END:
case C_OPCODE_VFETCH:
case C_OPCODE_KILP:
case C_OPCODE_CAL:
case C_OPCODE_RET:
case C_OPCODE_TXB:
case C_OPCODE_TXL:
case C_OPCODE_BRK:
case C_OPCODE_IF:
case C_OPCODE_BGNFOR:
case C_OPCODE_REP:
case C_OPCODE_ELSE:
case C_OPCODE_ENDIF:
case C_OPCODE_ENDFOR:
case C_OPCODE_ENDREP:
case C_OPCODE_PUSHA:
case C_OPCODE_POPA:
case C_OPCODE_TXF:
case C_OPCODE_TXQ:
case C_OPCODE_CONT:
case C_OPCODE_EMIT:
case C_OPCODE_ENDPRIM:
case C_OPCODE_BGNLOOP:
case C_OPCODE_BGNSUB:
case C_OPCODE_ENDLOOP:
case C_OPCODE_ENDSUB:
case C_OPCODE_NOP:
case C_OPCODE_CALLNZ:
case C_OPCODE_IFC:
case C_OPCODE_BREAKC:
case C_OPCODE_KIL:
case C_OPCODE_TEX:
case C_OPCODE_TXD:
case C_OPCODE_TXP:
case C_OPCODE_SWITCH:
case C_OPCODE_CASE:
case C_OPCODE_DEFAULT:
case C_OPCODE_ENDSWITCH:
default:
return 0;
}
}
/* NEW */
void c_node_init(struct c_node *node)
{
memset(node, 0, sizeof(struct c_node));
LIST_INITHEAD(&node->predecessors);
LIST_INITHEAD(&node->successors);
LIST_INITHEAD(&node->childs);
LIST_INITHEAD(&node->insts);
node->parent = NULL;
}
static struct c_node_link *c_node_link_new(struct c_node *node)
{
struct c_node_link *link;
link = calloc(1, sizeof(struct c_node_link));
if (link == NULL)
return NULL;
LIST_INITHEAD(&link->head);
link->node = node;
return link;
}
int c_node_cfg_link(struct c_node *predecessor, struct c_node *successor)
{
struct c_node_link *pedge, *sedge;
pedge = c_node_link_new(successor);
sedge = c_node_link_new(predecessor);
if (sedge == NULL || pedge == NULL) {
free(sedge);
free(pedge);
return -ENOMEM;
}
LIST_ADDTAIL(&pedge->head, &predecessor->successors);
LIST_ADDTAIL(&sedge->head, &successor->predecessors);
return 0;
}
int c_node_add_new_instruction_head(struct c_node *node, struct c_instruction *instruction)
{
struct c_instruction *inst = malloc(sizeof(struct c_instruction));
if (inst == NULL)
return -ENOMEM;
memcpy(inst, instruction, sizeof(struct c_instruction));
LIST_ADD(&inst->head, &node->insts);
return 0;
}
int c_node_add_new_instruction(struct c_node *node, struct c_instruction *instruction)
{
struct c_instruction *inst = malloc(sizeof(struct c_instruction));
if (inst == NULL)
return -ENOMEM;
memcpy(inst, instruction, sizeof(struct c_instruction));
LIST_ADDTAIL(&inst->head, &node->insts);
return 0;
}
struct c_node *c_shader_cfg_new_node_after(struct c_shader *shader, struct c_node *predecessor)
{
struct c_node *node = calloc(1, sizeof(struct c_node));
if (node == NULL)
return NULL;
c_node_init(node);
if (c_node_cfg_link(predecessor, node)) {
free(node);
return NULL;
}
LIST_ADDTAIL(&node->head, &shader->nodes);
return node;
}
int c_shader_init(struct c_shader *shader, unsigned type)
{
unsigned i;
int r;
shader->type = type;
for (i = 0; i < C_FILE_COUNT; i++) {
shader->files[i].nvectors = 0;
LIST_INITHEAD(&shader->files[i].vectors);
}
LIST_INITHEAD(&shader->nodes);
c_node_init(&shader->entry);
c_node_init(&shader->end);
shader->entry.opcode = C_OPCODE_ENTRY;
shader->end.opcode = C_OPCODE_END;
r = c_node_cfg_link(&shader->entry, &shader->end);
if (r)
return r;
return 0;
}
struct c_vector *c_shader_vector_new(struct c_shader *shader, unsigned file, unsigned name, int sid)
{
struct c_vector *v = calloc(1, sizeof(struct c_vector));
int i;
if (v == NULL) {
return NULL;
}
for (i = 0; i < 4; i++) {
v->channel[i] = calloc(1, sizeof(struct c_channel));
if (v->channel[i] == NULL)
goto out_err;
v->channel[i]->vindex = i;
v->channel[i]->vector = v;
}
v->file = file;
v->name = name;
v->sid = sid;
shader->files[v->file].nvectors++;
v->id = shader->nvectors++;
LIST_ADDTAIL(&v->head, &shader->files[v->file].vectors);
return v;
out_err:
for (i = 0; i < 4; i++) {
free(v->channel[i]);
}
free(v);
return NULL;
}
static void c_node_remove_link(struct list_head *head, struct c_node *node)
{
struct c_node_link *link, *tmp;
LIST_FOR_EACH_ENTRY_SAFE(link, tmp, head, head) {
if (link->node == node) {
LIST_DEL(&link->head);
free(link);
}
}
}
static void c_node_destroy(struct c_node *node)
{
struct c_instruction *i, *ni;
struct c_node_link *link, *tmp;
LIST_FOR_EACH_ENTRY_SAFE(i, ni, &node->insts, head) {
LIST_DEL(&i->head);
free(i);
}
if (node->parent)
c_node_remove_link(&node->parent->childs, node);
node->parent = NULL;
LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->predecessors, head) {
c_node_remove_link(&link->node->successors, node);
LIST_DEL(&link->head);
free(link);
}
LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->successors, head) {
c_node_remove_link(&link->node->predecessors, node);
LIST_DEL(&link->head);
free(link);
}
LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->childs, head) {
link->node->parent = NULL;
LIST_DEL(&link->head);
free(link);
}
}
void c_shader_destroy(struct c_shader *shader)
{
struct c_node *n, *nn;
struct c_vector *v, *nv;
unsigned i;
for (i = 0; i < C_FILE_COUNT; i++) {
shader->files[i].nvectors = 0;
LIST_FOR_EACH_ENTRY_SAFE(v, nv, &shader->files[i].vectors, head) {
LIST_DEL(&v->head);
free(v->channel[0]);
free(v->channel[1]);
free(v->channel[2]);
free(v->channel[3]);
free(v);
}
}
LIST_FOR_EACH_ENTRY_SAFE(n, nn, &shader->nodes, head) {
LIST_DEL(&n->head);
c_node_destroy(n);
}
memset(shader, 0, sizeof(struct c_shader));
}
static void c_shader_dfs_without_rec(struct c_node *entry, struct c_node *node)
{
struct c_node_link *link;
if (entry == node || entry->visited)
return;
entry->visited = 1;
LIST_FOR_EACH_ENTRY(link, &entry->successors, head) {
c_shader_dfs_without_rec(link->node, node);
}
}
static void c_shader_dfs_without(struct c_shader *shader, struct c_node *node)
{
struct c_node *n;
shader->entry.visited = 0;
shader->end.visited = 0;
LIST_FOR_EACH_ENTRY(n, &shader->nodes, head) {
n->visited = 0;
}
c_shader_dfs_without_rec(&shader->entry, node);
}
static int c_shader_build_dominator_tree_rec(struct c_shader *shader, struct c_node *node)
{
struct c_node_link *link, *nlink;
unsigned found = 0;
int r;
if (node->done)
return 0;
node->done = 1;
LIST_FOR_EACH_ENTRY(link, &node->predecessors, head) {
/* if we remove this predecessor can we reach the current node ? */
c_shader_dfs_without(shader, link->node);
if (node->visited == 0) {
/* we were unable to visit current node thus current
* predecessor is the immediate dominator of node, as
* their can be only one immediate dominator we break
*/
node->parent = link->node;
nlink = c_node_link_new(node);
if (nlink == NULL)
return -ENOMEM;
LIST_ADDTAIL(&nlink->head, &link->node->childs);
found = 1;
break;
}
}
/* this shouldn't happen there should at least be 1 denominator for each node */
if (!found && node->opcode != C_OPCODE_ENTRY) {
fprintf(stderr, "invalid flow control graph node %p (%d) has no immediate dominator\n",
node, node->opcode);
return -EINVAL;
}
LIST_FOR_EACH_ENTRY(link, &node->predecessors, head) {
r = c_shader_build_dominator_tree_rec(shader, link->node);
if (r)
return r;
}
return 0;
}
int c_shader_build_dominator_tree(struct c_shader *shader)
{
struct c_node *node;
LIST_FOR_EACH_ENTRY(node, &shader->nodes, head) {
node->done = 0;
}
return c_shader_build_dominator_tree_rec(shader, &shader->end);
}

View File

@ -1,320 +0,0 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef R600_COMPILER_H
#define R600_COMPILER_H
#include "util/u_double_list.h"
struct c_vector;
/* operand are the basic source/destination of each operation */
struct c_channel {
struct list_head head;
unsigned vindex; /**< index in vector X,Y,Z,W (0,1,2,3) */
unsigned value; /**< immediate value 32bits */
struct c_vector *vector; /**< vector to which it belongs */
};
/* in GPU world most of the time operand are grouped into vector
* of 4 component this structure is mostly and handler to group
* operand into a same vector
*/
struct c_vector {
struct list_head head;
unsigned id; /**< vector uniq id */
unsigned name; /**< semantic name */
unsigned file; /**< operand file C_FILE_* */
int sid; /**< semantic id */
struct c_channel *channel[4]; /**< operands */
};
#define C_PROGRAM_TYPE_VS 0
#define C_PROGRAM_TYPE_FS 1
#define C_PROGRAM_TYPE_COUNT 2
#define C_NODE_FLAG_ALU 1
#define C_NODE_FLAG_FETCH 2
#define C_SWIZZLE_X 0
#define C_SWIZZLE_Y 1
#define C_SWIZZLE_Z 2
#define C_SWIZZLE_W 3
#define C_SWIZZLE_0 4
#define C_SWIZZLE_1 5
#define C_SWIZZLE_D 6
#define C_FILE_NULL 0
#define C_FILE_CONSTANT 1
#define C_FILE_INPUT 2
#define C_FILE_OUTPUT 3
#define C_FILE_TEMPORARY 4
#define C_FILE_SAMPLER 5
#define C_FILE_ADDRESS 6
#define C_FILE_IMMEDIATE 7
#define C_FILE_LOOP 8
#define C_FILE_PREDICATE 9
#define C_FILE_SYSTEM_VALUE 10
#define C_FILE_RESOURCE 11
#define C_FILE_COUNT 12
#define C_SEMANTIC_POSITION 0
#define C_SEMANTIC_COLOR 1
#define C_SEMANTIC_BCOLOR 2 /**< back-face color */
#define C_SEMANTIC_FOG 3
#define C_SEMANTIC_PSIZE 4
#define C_SEMANTIC_GENERIC 5
#define C_SEMANTIC_NORMAL 6
#define C_SEMANTIC_FACE 7
#define C_SEMANTIC_EDGEFLAG 8
#define C_SEMANTIC_PRIMID 9
#define C_SEMANTIC_INSTANCEID 10
#define C_SEMANTIC_VERTEXID 11
#define C_SEMANTIC_COUNT 12 /**< number of semantic values */
#define C_OPCODE_NOP 0
#define C_OPCODE_MOV 1
#define C_OPCODE_LIT 2
#define C_OPCODE_RCP 3
#define C_OPCODE_RSQ 4
#define C_OPCODE_EXP 5
#define C_OPCODE_LOG 6
#define C_OPCODE_MUL 7
#define C_OPCODE_ADD 8
#define C_OPCODE_DP3 9
#define C_OPCODE_DP4 10
#define C_OPCODE_DST 11
#define C_OPCODE_MIN 12
#define C_OPCODE_MAX 13
#define C_OPCODE_SLT 14
#define C_OPCODE_SGE 15
#define C_OPCODE_MAD 16
#define C_OPCODE_SUB 17
#define C_OPCODE_LRP 18
#define C_OPCODE_CND 19
/* gap */
#define C_OPCODE_DP2A 21
/* gap */
#define C_OPCODE_FRC 24
#define C_OPCODE_CLAMP 25
#define C_OPCODE_FLR 26
#define C_OPCODE_ROUND 27
#define C_OPCODE_EX2 28
#define C_OPCODE_LG2 29
#define C_OPCODE_POW 30
#define C_OPCODE_XPD 31
/* gap */
#define C_OPCODE_ABS 33
#define C_OPCODE_RCC 34
#define C_OPCODE_DPH 35
#define C_OPCODE_COS 36
#define C_OPCODE_DDX 37
#define C_OPCODE_DDY 38
#define C_OPCODE_KILP 39 /* predicated kill */
#define C_OPCODE_PK2H 40
#define C_OPCODE_PK2US 41
#define C_OPCODE_PK4B 42
#define C_OPCODE_PK4UB 43
#define C_OPCODE_RFL 44
#define C_OPCODE_SEQ 45
#define C_OPCODE_SFL 46
#define C_OPCODE_SGT 47
#define C_OPCODE_SIN 48
#define C_OPCODE_SLE 49
#define C_OPCODE_SNE 50
#define C_OPCODE_STR 51
#define C_OPCODE_TEX 52
#define C_OPCODE_TXD 53
#define C_OPCODE_TXP 54
#define C_OPCODE_UP2H 55
#define C_OPCODE_UP2US 56
#define C_OPCODE_UP4B 57
#define C_OPCODE_UP4UB 58
#define C_OPCODE_X2D 59
#define C_OPCODE_ARA 60
#define C_OPCODE_ARR 61
#define C_OPCODE_BRA 62
#define C_OPCODE_CAL 63
#define C_OPCODE_RET 64
#define C_OPCODE_SSG 65 /* SGN */
#define C_OPCODE_CMP 66
#define C_OPCODE_SCS 67
#define C_OPCODE_TXB 68
#define C_OPCODE_NRM 69
#define C_OPCODE_DIV 70
#define C_OPCODE_DP2 71
#define C_OPCODE_TXL 72
#define C_OPCODE_BRK 73
#define C_OPCODE_IF 74
#define C_OPCODE_BGNFOR 75
#define C_OPCODE_REP 76
#define C_OPCODE_ELSE 77
#define C_OPCODE_ENDIF 78
#define C_OPCODE_ENDFOR 79
#define C_OPCODE_ENDREP 80
#define C_OPCODE_PUSHA 81
#define C_OPCODE_POPA 82
#define C_OPCODE_CEIL 83
#define C_OPCODE_I2F 84
#define C_OPCODE_NOT 85
#define C_OPCODE_TRUNC 86
#define C_OPCODE_SHL 87
/* gap */
#define C_OPCODE_AND 89
#define C_OPCODE_OR 90
#define C_OPCODE_MOD 91
#define C_OPCODE_XOR 92
#define C_OPCODE_SAD 93
#define C_OPCODE_TXF 94
#define C_OPCODE_TXQ 95
#define C_OPCODE_CONT 96
#define C_OPCODE_EMIT 97
#define C_OPCODE_ENDPRIM 98
#define C_OPCODE_BGNLOOP 99
#define C_OPCODE_BGNSUB 100
#define C_OPCODE_ENDLOOP 101
#define C_OPCODE_ENDSUB 102
/* gap */
#define C_OPCODE_NRM4 112
#define C_OPCODE_CALLNZ 113
#define C_OPCODE_IFC 114
#define C_OPCODE_BREAKC 115
#define C_OPCODE_KIL 116 /* conditional kill */
#define C_OPCODE_END 117 /* aka HALT */
/* gap */
#define C_OPCODE_F2I 119
#define C_OPCODE_IDIV 120
#define C_OPCODE_IMAX 121
#define C_OPCODE_IMIN 122
#define C_OPCODE_INEG 123
#define C_OPCODE_ISGE 124
#define C_OPCODE_ISHR 125
#define C_OPCODE_ISLT 126
#define C_OPCODE_F2U 127
#define C_OPCODE_U2F 128
#define C_OPCODE_UADD 129
#define C_OPCODE_UDIV 130
#define C_OPCODE_UMAD 131
#define C_OPCODE_UMAX 132
#define C_OPCODE_UMIN 133
#define C_OPCODE_UMOD 134
#define C_OPCODE_UMUL 135
#define C_OPCODE_USEQ 136
#define C_OPCODE_USGE 137
#define C_OPCODE_USHR 138
#define C_OPCODE_USLT 139
#define C_OPCODE_USNE 140
#define C_OPCODE_SWITCH 141
#define C_OPCODE_CASE 142
#define C_OPCODE_DEFAULT 143
#define C_OPCODE_ENDSWITCH 144
#define C_OPCODE_VFETCH 145
#define C_OPCODE_ENTRY 146
#define C_OPCODE_ARL 147
#define C_OPCODE_LAST 148
#define C_OPERAND_FLAG_ABS (1 << 0)
#define C_OPERAND_FLAG_NEG (1 << 1)
struct c_operand {
struct c_vector *vector;
unsigned swizzle;
unsigned flag;
};
struct c_op {
unsigned ninput;
struct c_operand input[3];
struct c_operand output;
unsigned opcode;
};
struct c_instruction {
struct list_head head;
unsigned nop;
struct c_op op[5];
};
struct c_node;
struct c_node_link {
struct list_head head;
struct c_node *node;
};
/**
* struct c_node
*
* @next: all node are in a double linked list, this point to
* next node
* @next: all node are in a double linked list, this point to
* previous node
* @predecessors: list of all predecessor nodes in the flow graph
* @successors: list of all sucessor nodes in the flow graph
* @parent: parent node in the depth first walk tree
* @childs: child nodes in the depth first walk tree
*/
struct c_node {
struct list_head head;
struct list_head predecessors;
struct list_head successors;
struct list_head childs;
struct c_node *parent;
struct list_head insts;
unsigned opcode;
unsigned visited;
unsigned done;
void *backend;
};
struct c_file {
unsigned nvectors;
struct list_head vectors;
};
struct c_shader {
unsigned nvectors;
struct c_file files[C_FILE_COUNT];
struct list_head nodes;
struct c_node entry;
struct c_node end;
unsigned type;
};
int c_shader_init(struct c_shader *shader, unsigned type);
void c_shader_destroy(struct c_shader *shader);
struct c_vector *c_shader_vector_new(struct c_shader *shader, unsigned file, unsigned name, int sid);
int c_shader_build_dominator_tree(struct c_shader *shader);
void c_shader_dump(struct c_shader *shader);
void c_node_init(struct c_node *node);
int c_node_add_new_instruction(struct c_node *node, struct c_instruction *instruction);
int c_node_add_new_instruction_head(struct c_node *node, struct c_instruction *instruction);
/* control flow graph functions */
int c_node_cfg_link(struct c_node *predecessor, struct c_node *successor);
struct c_node *c_node_cfg_new_after(struct c_node *predecessor);
struct c_node *c_shader_cfg_new_node_after(struct c_shader *shader, struct c_node *predecessor);
struct c_vector *c_vector_new(void);
#endif

View File

@ -1,267 +0,0 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "r600_compiler.h"
static const char *c_file_swz[] = {
"x",
"y",
"z",
"w",
"0",
"1",
".",
};
static const char *c_file_str[] = {
"NULL",
"CONSTANT",
"INPUT",
"OUTPUT",
"TEMPORARY",
"SAMPLER",
"ADDRESS",
"IMMEDIATE",
"LOOP",
"PREDICATE",
"SYSTEM_VALUE",
};
static const char *c_semantic_str[] = {
"POSITION",
"COLOR",
"BCOLOR",
"FOG",
"PSIZE",
"GENERIC",
"NORMAL",
"FACE",
"EDGEFLAG",
"PRIMID",
"INSTANCEID",
};
static const char *c_opcode_str[] = {
"ARL",
"MOV",
"LIT",
"RCP",
"RSQ",
"EXP",
"LOG",
"MUL",
"ADD",
"DP3",
"DP4",
"DST",
"MIN",
"MAX",
"SLT",
"SGE",
"MAD",
"SUB",
"LRP",
"CND",
"(INVALID)",
"DP2A",
"(INVALID)",
"(INVALID)",
"FRC",
"CLAMP",
"FLR",
"ROUND",
"EX2",
"LG2",
"POW",
"XPD",
"(INVALID)",
"ABS",
"RCC",
"DPH",
"COS",
"DDX",
"DDY",
"KILP",
"PK2H",
"PK2US",
"PK4B",
"PK4UB",
"RFL",
"SEQ",
"SFL",
"SGT",
"SIN",
"SLE",
"SNE",
"STR",
"TEX",
"TXD",
"TXP",
"UP2H",
"UP2US",
"UP4B",
"UP4UB",
"X2D",
"ARA",
"ARR",
"BRA",
"CAL",
"RET",
"SSG",
"CMP",
"SCS",
"TXB",
"NRM",
"DIV",
"DP2",
"TXL",
"BRK",
"IF",
"BGNFOR",
"REP",
"ELSE",
"ENDIF",
"ENDFOR",
"ENDREP",
"PUSHA",
"POPA",
"CEIL",
"I2F",
"NOT",
"TRUNC",
"SHL",
"(INVALID)",
"AND",
"OR",
"MOD",
"XOR",
"SAD",
"TXF",
"TXQ",
"CONT",
"EMIT",
"ENDPRIM",
"BGNLOOP",
"BGNSUB",
"ENDLOOP",
"ENDSUB",
"(INVALID)",
"(INVALID)",
"(INVALID)",
"(INVALID)",
"NOP",
"(INVALID)",
"(INVALID)",
"(INVALID)",
"(INVALID)",
"NRM4",
"CALLNZ",
"IFC",
"BREAKC",
"KIL",
"END",
"(INVALID)",
"F2I",
"IDIV",
"IMAX",
"IMIN",
"INEG",
"ISGE",
"ISHR",
"ISLT",
"F2U",
"U2F",
"UADD",
"UDIV",
"UMAD",
"UMAX",
"UMIN",
"UMOD",
"UMUL",
"USEQ",
"USGE",
"USHR",
"USLT",
"USNE",
"SWITCH",
"CASE",
"DEFAULT",
"ENDSWITCH",
"VFETCH",
"ENTRY",
};
static inline const char *c_get_name(const char *name[], unsigned i)
{
return name[i];
}
static void pindent(unsigned indent)
{
unsigned i;
for (i = 0; i < indent; i++)
fprintf(stderr, " ");
}
static void c_node_dump(struct c_node *node, unsigned indent)
{
struct c_instruction *i;
unsigned j, k;
pindent(indent); fprintf(stderr, "# node %s\n", c_get_name(c_opcode_str, node->opcode));
LIST_FOR_EACH_ENTRY(i, &node->insts, head) {
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");
}
}
}
static void c_shader_dump_rec(struct c_shader *shader, struct c_node *node, unsigned indent)
{
struct c_node_link *link;
c_node_dump(node, indent);
LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
c_shader_dump_rec(shader, link->node, indent + 1);
}
}
void c_shader_dump(struct c_shader *shader)
{
c_shader_dump_rec(shader, &shader->entry, 0);
}

View File

@ -1,972 +0,0 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <util/u_format.h>
#include "r600_screen.h"
#include "r600_context.h"
#include "r600_sq.h"
struct r600_alu_instruction {
unsigned copcode;
enum r600_instruction instruction;
};
static int r600_shader_alu_translate(struct r600_shader *rshader,
struct r600_shader_node *node,
struct c_instruction *instruction);
struct r600_alu_instruction r600_alu_instruction[C_OPCODE_LAST];
struct r600_instruction_info r600_instruction_info[];
int r600_shader_insert_fetch(struct c_shader *shader)
{
struct c_vector *vi, *vr, *v, *nv;
struct c_instruction instruction;
int r;
if (shader->type != C_PROGRAM_TYPE_VS)
return 0;
vi = c_shader_vector_new(shader, C_FILE_INPUT, C_SEMANTIC_VERTEXID, -1);
if (vi == NULL)
return -ENOMEM;
LIST_FOR_EACH_ENTRY_SAFE(v, nv, &shader->files[C_FILE_INPUT].vectors, head) {
if (v == vi)
continue;
vr = c_shader_vector_new(shader, C_FILE_RESOURCE, C_SEMANTIC_GENERIC, -1);
if (vr == NULL)
return -ENOMEM;
memset(&instruction, 0, sizeof(struct c_instruction));
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;
LIST_DEL(&v->head);
shader->files[C_FILE_INPUT].nvectors--;
LIST_ADDTAIL(&v->head, &shader->files[C_FILE_TEMPORARY].vectors);
shader->files[C_FILE_TEMPORARY].nvectors++;
v->file = C_FILE_TEMPORARY;
}
return 0;
}
void r600_shader_cleanup(struct r600_shader *rshader)
{
struct r600_shader_node *n, *nn;
struct r600_shader_vfetch *vf, *nvf;
struct r600_shader_alu *alu, *nalu;
int i;
if (rshader == NULL)
return;
if (rshader->gpr) {
for (i = 0; i < rshader->nvector; i++) {
free(rshader->gpr[i]);
}
free(rshader->gpr);
rshader->gpr = NULL;
}
LIST_FOR_EACH_ENTRY_SAFE(n, nn, &rshader->nodes, head) {
LIST_DEL(&n->head);
LIST_FOR_EACH_ENTRY_SAFE(vf, nvf, &n->vfetch, head) {
LIST_DEL(&vf->head);
free(vf);
}
LIST_FOR_EACH_ENTRY_SAFE(alu, nalu, &n->alu, head) {
LIST_DEL(&alu->head);
free(alu);
}
free(n);
}
free(rshader->bcode);
return;
}
int r600_shader_vfetch_bytecode(struct r600_shader *rshader,
struct r600_shader_node *rnode,
struct r600_shader_vfetch *vfetch,
unsigned *cid)
{
unsigned id = *cid;
vfetch->cf_addr = id;
rshader->bcode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vfetch->src[1].sel) |
S_SQ_VTX_WORD0_SRC_GPR(vfetch->src[0].sel) |
S_SQ_VTX_WORD0_SRC_SEL_X(vfetch->src[0].sel) |
S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(0x1F);
rshader->bcode[id++] = S_SQ_VTX_WORD1_DST_SEL_X(vfetch->dst[0].chan) |
S_SQ_VTX_WORD1_DST_SEL_Y(vfetch->dst[1].chan) |
S_SQ_VTX_WORD1_DST_SEL_Z(vfetch->dst[2].chan) |
S_SQ_VTX_WORD1_DST_SEL_W(vfetch->dst[3].chan) |
S_SQ_VTX_WORD1_USE_CONST_FIELDS(1) |
S_SQ_VTX_WORD1_GPR_DST_GPR(vfetch->dst[0].sel);
rshader->bcode[id++] = S_SQ_VTX_WORD2_MEGA_FETCH(1);
rshader->bcode[id++] = 0;
*cid = id;
return 0;
}
int r600_shader_update(struct r600_shader *rshader, enum pipe_format *resource_format)
{
struct r600_shader_node *rnode;
struct r600_shader_vfetch *vfetch;
unsigned i;
memcpy(rshader->resource_format, resource_format,
rshader->nresource * sizeof(enum pipe_format));
LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
LIST_FOR_EACH_ENTRY(vfetch, &rnode->vfetch, head) {
const struct util_format_description *desc;
i = vfetch->cf_addr + 1;
rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_X;
rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_Y;
rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_Z;
rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_W;
desc = util_format_description(resource_format[vfetch->src[1].sel]);
if (desc == NULL) {
fprintf(stderr, "%s unknown format %d\n", __func__, resource_format[vfetch->src[1].sel]);
continue;
}
/* WARNING so far TGSI swizzle match R600 ones */
rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_X(desc->swizzle[0]);
rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_Y(desc->swizzle[1]);
rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_Z(desc->swizzle[2]);
rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_W(desc->swizzle[3]);
}
}
return 0;
}
int r600_shader_register(struct r600_shader *rshader)
{
struct c_vector *v, *nv;
unsigned tid, cid, rid, i;
rshader->nvector = rshader->cshader.nvectors;
rshader->gpr = calloc(rshader->nvector, sizeof(void*));
if (rshader->gpr == NULL)
return -ENOMEM;
tid = 0;
cid = 0;
rid = 0;
/* alloc input first */
LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_INPUT].vectors, head) {
nv = c_vector_new();
if (nv == NULL) {
return -ENOMEM;
}
memcpy(nv, v, sizeof(struct c_vector));
nv->id = tid++;
rshader->gpr[v->id] = nv;
}
for (i = 0; i < C_FILE_COUNT; i++) {
if (i == C_FILE_INPUT || i == C_FILE_IMMEDIATE)
continue;
LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[i].vectors, head) {
switch (v->file) {
case C_FILE_OUTPUT:
case C_FILE_TEMPORARY:
nv = c_vector_new();
if (nv == NULL) {
return -ENOMEM;
}
memcpy(nv, v, sizeof(struct c_vector));
nv->id = tid++;
rshader->gpr[v->id] = nv;
break;
case C_FILE_CONSTANT:
nv = c_vector_new();
if (nv == NULL) {
return -ENOMEM;
}
memcpy(nv, v, sizeof(struct c_vector));
nv->id = (cid++) + 256;
rshader->gpr[v->id] = nv;
break;
case C_FILE_RESOURCE:
nv = c_vector_new();
if (nv == NULL) {
return -ENOMEM;
}
memcpy(nv, v, sizeof(struct c_vector));
nv->id = (rid++);
rshader->gpr[v->id] = nv;
break;
default:
fprintf(stderr, "%s:%d unsupported file %d\n", __func__, __LINE__, v->file);
return -EINVAL;
}
}
}
rshader->ngpr = tid;
rshader->nconstant = cid;
rshader->nresource = rid;
return 0;
}
int r600_shader_find_gpr(struct r600_shader *rshader, struct c_vector *v, unsigned swizzle,
struct r600_shader_operand *operand)
{
struct c_vector *tmp;
/* Values [0,127] correspond to GPR[0..127].
* Values [256,511] correspond to cfile constants c[0..255].
* Other special values are shown in the list below.
* 248 SQ_ALU_SRC_0: special constant 0.0.
* 249 SQ_ALU_SRC_1: special constant 1.0 float.
* 250 SQ_ALU_SRC_1_INT: special constant 1 integer.
* 251 SQ_ALU_SRC_M_1_INT: special constant -1 integer.
* 252 SQ_ALU_SRC_0_5: special constant 0.5 float.
* 253 SQ_ALU_SRC_LITERAL: literal constant.
* 254 SQ_ALU_SRC_PV: previous vector result.
* 255 SQ_ALU_SRC_PS: previous scalar result.
*/
operand->vector = v;
operand->sel = 248;
operand->chan = 0;
operand->neg = 0;
operand->abs = 0;
if (v == NULL)
return 0;
if (v->file == C_FILE_IMMEDIATE) {
operand->sel = 253;
} else {
tmp = rshader->gpr[v->id];
if (tmp == NULL) {
fprintf(stderr, "%s %d unknown register\n", __FILE__, __LINE__);
return -EINVAL;
}
operand->sel = tmp->id;
}
operand->chan = swizzle;
switch (swizzle) {
case C_SWIZZLE_X:
case C_SWIZZLE_Y:
case C_SWIZZLE_Z:
case C_SWIZZLE_W:
break;
case C_SWIZZLE_0:
operand->sel = 248;
operand->chan = 0;
break;
case C_SWIZZLE_1:
operand->sel = 249;
operand->chan = 0;
break;
default:
fprintf(stderr, "%s %d invalid swizzle %d\n", __FILE__, __LINE__, swizzle);
return -EINVAL;
}
return 0;
}
static struct r600_shader_node *r600_shader_new_node(struct r600_shader *rshader, struct c_node *node)
{
struct r600_shader_node *rnode;
rnode = CALLOC_STRUCT(r600_shader_node);
if (rnode == NULL)
return NULL;
rnode->node = node;
LIST_INITHEAD(&rnode->vfetch);
fprintf(stderr, "------------------------ new node (%p %p)\n", &rnode->vfetch, rnode->vfetch.next);
LIST_INITHEAD(&rnode->alu);
LIST_ADDTAIL(&rnode->head, &rshader->nodes);
return rnode;
}
static int r600_shader_add_vfetch(struct r600_shader *rshader,
struct r600_shader_node *node,
struct c_instruction *instruction)
{
struct r600_shader_vfetch *vfetch;
struct r600_shader_node *rnode;
int r;
if (instruction == NULL)
return 0;
if (instruction->op[0].opcode != C_OPCODE_VFETCH)
return 0;
if (!LIST_IS_EMPTY(&node->alu)) {
rnode = r600_shader_new_node(rshader, node->node);
if (rnode == NULL)
return -ENOMEM;
node = rnode;
}
vfetch = calloc(1, sizeof(struct r600_shader_vfetch));
if (vfetch == NULL)
return -ENOMEM;
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->op[0].input[0].vector, 0, &vfetch->src[0]);
if (r)
return r;
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;
vfetch->dst[1].chan = C_SWIZZLE_Y;
vfetch->dst[2].chan = C_SWIZZLE_Z;
vfetch->dst[3].chan = C_SWIZZLE_W;
LIST_ADDTAIL(&vfetch->head, &node->vfetch);
node->nslot += 2;
return 0;
}
static int r600_node_translate(struct r600_shader *rshader, struct c_node *node)
{
struct c_instruction *instruction;
struct r600_shader_node *rnode;
int r;
rnode = r600_shader_new_node(rshader, node);
if (rnode == NULL)
return -ENOMEM;
LIST_FOR_EACH_ENTRY(instruction, &node->insts, head) {
switch (instruction->op[0].opcode) {
case C_OPCODE_VFETCH:
r = r600_shader_add_vfetch(rshader, rnode, instruction);
if (r) {
fprintf(stderr, "%s %d vfetch failed\n", __func__, __LINE__);
return r;
}
break;
default:
r = r600_shader_alu_translate(rshader, rnode, instruction);
if (r) {
fprintf(stderr, "%s %d alu failed\n", __func__, __LINE__);
return r;
}
break;
}
}
return 0;
}
int r600_shader_translate_rec(struct r600_shader *rshader, struct c_node *node)
{
struct c_node_link *link;
int r;
if (node->opcode == C_OPCODE_END)
return 0;
r = r600_node_translate(rshader, node);
if (r)
return r;
LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
r = r600_shader_translate_rec(rshader, link->node);
if (r)
return r;
}
return 0;
}
static struct r600_shader_alu *r600_shader_insert_alu(struct r600_shader *rshader, struct r600_shader_node *node)
{
struct r600_shader_alu *alu;
alu = CALLOC_STRUCT(r600_shader_alu);
if (alu == NULL)
return NULL;
alu->alu[0].inst = INST_NOP;
alu->alu[1].inst = INST_NOP;
alu->alu[2].inst = INST_NOP;
alu->alu[3].inst = INST_NOP;
alu->alu[4].inst = INST_NOP;
alu->alu[0].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
alu->alu[1].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
alu->alu[2].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
alu->alu[3].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
alu->alu[4].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
alu->alu[1].dst.chan = 1;
alu->alu[2].dst.chan = 2;
alu->alu[3].dst.chan = 3;
LIST_ADDTAIL(&alu->head, &node->alu);
return alu;
}
static int r600_shader_alu_translate(struct r600_shader *rshader,
struct r600_shader_node *node,
struct c_instruction *instruction)
{
struct r600_shader_node *rnode;
struct r600_shader_alu *alu;
int i, j, r, litteral_lastcomp = -1;
if (!LIST_IS_EMPTY(&node->vfetch)) {
fprintf(stderr, "------------------------ add node (%p %p)\n", &node->vfetch, node->vfetch.next);
rnode = r600_shader_new_node(rshader, node->node);
if (rnode == NULL) {
fprintf(stderr, "%s %d new node failed\n", __func__, __LINE__);
return -ENOMEM;
}
node = rnode;
}
/* initialize alu */
alu = r600_shader_insert_alu(rshader, node);
/* 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 %d\n", __func__, __LINE__, comp);
return -EINVAL;
}
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;
}
if (instruction->op[i].input[j].vector->file == C_FILE_IMMEDIATE) {
r = instruction->op[i].input[j].swizzle;
switch (r) {
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 input\n", __func__, __LINE__);
return -EINVAL;
}
alu->literal[r] = instruction->op[i].input[j].vector->channel[r]->value;
if (r > litteral_lastcomp) {
litteral_lastcomp = r;
}
}
}
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 register failed\n", __FILE__, __LINE__);
return r;
}
}
switch (litteral_lastcomp) {
case 0:
case 1:
alu->nliteral = 2;
break;
case 2:
case 3:
alu->nliteral = 4;
break;
case -1:
default:
break;
}
for (i = 4; i >= 0; i--) {
if (alu->alu[i].inst != INST_NOP) {
alu->alu[i].last = 1;
alu->nalu = i + 1;
break;
}
}
return 0;
}
void r600_shader_node_place(struct r600_shader *rshader)
{
struct r600_shader_node *node, *nnode;
struct r600_shader_alu *alu, *nalu;
struct r600_shader_vfetch *vfetch, *nvfetch;
unsigned cf_id = 0, cf_addr = 0;
rshader->ncf = 0;
rshader->nslot = 0;
LIST_FOR_EACH_ENTRY_SAFE(node, nnode, &rshader->nodes, head) {
LIST_FOR_EACH_ENTRY_SAFE(alu, nalu, &node->alu, head) {
node->nslot += alu->nalu;
node->nslot += alu->nliteral >> 1;
}
node->nfetch = 0;
LIST_FOR_EACH_ENTRY_SAFE(vfetch, nvfetch, &node->vfetch, head) {
node->nslot += 2;
node->nfetch += 1;
}
if (!LIST_IS_EMPTY(&node->vfetch)) {
/* fetch node need to be 16 bytes aligned*/
cf_addr += 1;
cf_addr &= 0xFFFFFFFEUL;
}
node->cf_id = cf_id;
node->cf_addr = cf_addr;
cf_id += 2;
cf_addr += node->nslot * 2;
rshader->ncf++;
}
rshader->nslot = cf_addr;
LIST_FOR_EACH_ENTRY_SAFE(node, nnode, &rshader->nodes, head) {
node->cf_addr += cf_id * 2;
}
rshader->ncf += rshader->cshader.files[C_FILE_OUTPUT].nvectors;
rshader->ndw = rshader->ncf * 2 + rshader->nslot * 2;
}
int r600_shader_legalize(struct r600_shader *rshader)
{
return 0;
}
static int r600_cshader_legalize_rec(struct c_shader *shader, struct c_node *node)
{
struct c_node_link *link;
struct c_instruction *i, *n;
struct c_operand operand;
unsigned k, inst;
int r;
LIST_FOR_EACH_ENTRY(i, &node->insts, head) {
for (k = 0; k < i->nop; k++) {
switch (i->op[k].opcode) {
case C_OPCODE_SLT:
i->op[k].opcode = C_OPCODE_SGT;
memcpy(&operand, &i->op[k].input[0], sizeof(struct c_operand));
memcpy(&i->op[k].input[0], &i->op[k].input[1], sizeof(struct c_operand));
memcpy(&i->op[k].input[1], &operand, sizeof(struct c_operand));
break;
default:
break;
}
inst = r600_alu_instruction[i->op[k].opcode].instruction;
if (r600_instruction_info[inst].is_trans && k < (i->nop -1)) {
/* split trans opcode */
n = CALLOC_STRUCT(c_instruction);
if (n == NULL)
return -ENOMEM;
for (n->nop = 0, k = k + 1; k < i->nop; k++, n->nop++) {
memcpy(&n->op[n->nop - 0], &i->op[k], sizeof(struct c_op));
}
i->nop -= n->nop;
LIST_ADD(&n->head, &i->head);
}
}
}
LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
r = r600_cshader_legalize_rec(shader, link->node);
if (r) {
return r;
}
}
return 0;
}
int r600_cshader_legalize(struct c_shader *shader)
{
return r600_cshader_legalize_rec(shader, &shader->entry);
}
struct r600_instruction_info r600_instruction_info[] = {
{INST_ADD, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, 0, 0},
{INST_MUL, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL, 0, 0},
{INST_MUL_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL_IEEE, 0, 0},
{INST_MAX, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX, 0, 0},
{INST_MIN, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN, 0, 0},
{INST_MAX_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX_DX10, 0, 0},
{INST_MIN_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN_DX10, 0, 0},
{INST_SETE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE, 0, 0},
{INST_SETGT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT, 0, 0},
{INST_SETGE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE, 0, 0},
{INST_SETNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE, 0, 0},
{INST_SETE_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE_DX10, 0, 0},
{INST_SETGT_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT_DX10, 0, 0},
{INST_SETGE_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE_DX10, 0, 0},
{INST_SETNE_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE_DX10, 0, 0},
{INST_FRACT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT, 0, 0},
{INST_TRUNC, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_TRUNC, 0, 0},
{INST_CEIL, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CEIL, 0, 0},
{INST_RNDNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RNDNE, 0, 0},
{INST_FLOOR, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR, 0, 0},
{INST_MOVA, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA, 0, 0},
{INST_MOVA_FLOOR, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR, 0, 0},
{INST_MOVA_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_INT, 0, 0},
{INST_MOV, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV, 0, 0},
{INST_NOP, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, 0, 0},
{INST_PRED_SETGT_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_UINT, 0, 0},
{INST_PRED_SETGE_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_UINT, 0, 0},
{INST_PRED_SETE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE, 0, 0},
{INST_PRED_SETGT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT, 0, 0},
{INST_PRED_SETGE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE, 0, 0},
{INST_PRED_SETNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE, 0, 0},
{INST_PRED_SET_INV, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_INV, 0, 0},
{INST_PRED_SET_POP, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_POP, 0, 0},
{INST_PRED_SET_CLR, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_CLR, 0, 0},
{INST_PRED_SET_RESTORE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_RESTORE, 0, 0},
{INST_PRED_SETE_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_PUSH, 0, 0},
{INST_PRED_SETGT_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_PUSH, 0, 0},
{INST_PRED_SETGE_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_PUSH, 0, 0},
{INST_PRED_SETNE_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_PUSH, 0, 0},
{INST_KILLE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE, 0, 0},
{INST_KILLGT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT, 0, 0},
{INST_KILLGE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE, 0, 0},
{INST_KILLNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE, 0, 0},
{INST_AND_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_AND_INT, 0, 0},
{INST_OR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_OR_INT, 0, 0},
{INST_XOR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_XOR_INT, 0, 0},
{INST_NOT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOT_INT, 0, 0},
{INST_ADD_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT, 0, 0},
{INST_SUB_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SUB_INT, 0, 0},
{INST_MAX_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX_INT, 0, 0},
{INST_MIN_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN_INT, 0, 0},
{INST_MAX_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX_UINT, 0, 0},
{INST_MIN_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN_UINT, 0, 0},
{INST_SETE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE_INT, 0, 0},
{INST_SETGT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT_INT, 0, 0},
{INST_SETGE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE_INT, 0, 0},
{INST_SETNE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE_INT, 0, 0},
{INST_SETGT_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT_UINT, 0, 0},
{INST_SETGE_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE_UINT, 0, 0},
{INST_KILLGT_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT_UINT, 0, 0},
{INST_KILLGE_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE_UINT, 0, 0},
{INST_PRED_SETE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_INT, 0, 0},
{INST_PRED_SETGT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_INT, 0, 0},
{INST_PRED_SETGE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_INT, 0, 0},
{INST_PRED_SETNE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_INT, 0, 0},
{INST_KILLE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE_INT, 0, 0},
{INST_KILLGT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT_INT, 0, 0},
{INST_KILLGE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE_INT, 0, 0},
{INST_KILLNE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE_INT, 0, 0},
{INST_PRED_SETE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_PUSH_INT, 0, 0},
{INST_PRED_SETGT_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_PUSH_INT, 0, 0},
{INST_PRED_SETGE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_PUSH_INT, 0, 0},
{INST_PRED_SETNE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_PUSH_INT, 0, 0},
{INST_PRED_SETLT_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETLT_PUSH_INT, 0, 0},
{INST_PRED_SETLE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETLE_PUSH_INT, 0, 0},
{INST_DOT4, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, 0, 0},
{INST_DOT4_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4_IEEE, 0, 0},
{INST_CUBE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE, 0, 0},
{INST_MAX4, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX4, 0, 0},
{INST_MOVA_GPR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_GPR_INT, 0, 0},
{INST_EXP_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE, 1, 0},
{INST_LOG_CLAMPED, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED, 1, 0},
{INST_LOG_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE, 1, 0},
{INST_RECIP_CLAMPED, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_CLAMPED, 1, 0},
{INST_RECIP_FF, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_FF, 1, 0},
{INST_RECIP_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE, 1, 0},
{INST_RECIPSQRT_CLAMPED, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_CLAMPED, 1, 0},
{INST_RECIPSQRT_FF, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_FF, 1, 0},
{INST_RECIPSQRT_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_IEEE, 1, 0},
{INST_SQRT_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SQRT_IEEE, 1, 0},
{INST_FLT_TO_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT, 1, 0},
{INST_INT_TO_FLT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INT_TO_FLT, 1, 0},
{INST_UINT_TO_FLT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_UINT_TO_FLT, 1, 0},
{INST_SIN, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN, 1, 0},
{INST_COS, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS, 1, 0},
{INST_ASHR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ASHR_INT, 1, 0},
{INST_LSHR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHR_INT, 1, 0},
{INST_LSHL_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHL_INT, 1, 0},
{INST_MULLO_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULLO_INT, 1, 0},
{INST_MULHI_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULHI_INT, 1, 0},
{INST_MULLO_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULLO_UINT, 1, 0},
{INST_MULHI_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULHI_UINT, 1, 0},
{INST_RECIP_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_INT, 1, 0},
{INST_RECIP_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_UINT, 1, 0},
{INST_FLT_TO_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_UINT, 1, 0},
{INST_MUL_LIT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT, 1, 1},
{INST_MUL_LIT_M2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_M2, 1, 1},
{INST_MUL_LIT_M4, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_M4, 1, 1},
{INST_MUL_LIT_D2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_D2, 1, 1},
{INST_MULADD, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD, 0, 1},
{INST_MULADD_M2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_M2, 0, 1},
{INST_MULADD_M4, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_M4, 0, 1},
{INST_MULADD_D2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_D2, 0, 1},
{INST_MULADD_IEEE, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE, 0, 1},
{INST_MULADD_IEEE_M2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE_M2, 0, 1},
{INST_MULADD_IEEE_M4, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE_M4, 0, 1},
{INST_MULADD_IEEE_D2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE_D2, 0, 1},
{INST_CNDE, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDE, 0, 1},
{INST_CNDGT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT, 0, 1},
{INST_CNDGE, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGE, 0, 1},
{INST_CNDE_INT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDE_INT, 0, 1},
{INST_CNDGT_INT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT_INT, 0, 1},
{INST_CNDGE_INT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGE_INT, 0, 1},
};
struct r600_alu_instruction r600_alu_instruction[C_OPCODE_LAST] = {
{C_OPCODE_NOP, INST_NOP},
{C_OPCODE_MOV, INST_MOV},
{C_OPCODE_LIT, INST_NOP},
{C_OPCODE_RCP, INST_RECIP_IEEE},
{C_OPCODE_RSQ, INST_RECIPSQRT_IEEE},
{C_OPCODE_EXP, INST_EXP_IEEE},
{C_OPCODE_LOG, INST_LOG_IEEE},
{C_OPCODE_MUL, INST_MUL},
{C_OPCODE_ADD, INST_ADD},
{C_OPCODE_DP3, INST_DOT4},
{C_OPCODE_DP4, INST_DOT4},
{C_OPCODE_DST, INST_NOP},
{C_OPCODE_MIN, INST_MIN},
{C_OPCODE_MAX, INST_MAX},
{C_OPCODE_SLT, INST_NOP},
{C_OPCODE_SGE, INST_NOP},
{C_OPCODE_MAD, INST_MULADD},
{C_OPCODE_SUB, INST_COUNT},
{C_OPCODE_LRP, INST_NOP},
{C_OPCODE_CND, INST_NOP},
{20, INST_NOP},
{C_OPCODE_DP2A, INST_NOP},
{22, INST_NOP},
{23, INST_NOP},
{C_OPCODE_FRC, INST_NOP},
{C_OPCODE_CLAMP, INST_NOP},
{C_OPCODE_FLR, INST_NOP},
{C_OPCODE_ROUND, INST_NOP},
{C_OPCODE_EX2, INST_NOP},
{C_OPCODE_LG2, INST_NOP},
{C_OPCODE_POW, INST_NOP},
{C_OPCODE_XPD, INST_NOP},
{32, INST_NOP},
{C_OPCODE_ABS, INST_COUNT},
{C_OPCODE_RCC, INST_NOP},
{C_OPCODE_DPH, INST_NOP},
{C_OPCODE_COS, INST_COS},
{C_OPCODE_DDX, INST_NOP},
{C_OPCODE_DDY, INST_NOP},
{C_OPCODE_KILP, INST_NOP},
{C_OPCODE_PK2H, INST_NOP},
{C_OPCODE_PK2US, INST_NOP},
{C_OPCODE_PK4B, INST_NOP},
{C_OPCODE_PK4UB, INST_NOP},
{C_OPCODE_RFL, INST_NOP},
{C_OPCODE_SEQ, INST_NOP},
{C_OPCODE_SFL, INST_NOP},
{C_OPCODE_SGT, INST_SETGT},
{C_OPCODE_SIN, INST_SIN},
{C_OPCODE_SLE, INST_NOP},
{C_OPCODE_SNE, INST_NOP},
{C_OPCODE_STR, INST_NOP},
{C_OPCODE_TEX, INST_NOP},
{C_OPCODE_TXD, INST_NOP},
{C_OPCODE_TXP, INST_NOP},
{C_OPCODE_UP2H, INST_NOP},
{C_OPCODE_UP2US, INST_NOP},
{C_OPCODE_UP4B, INST_NOP},
{C_OPCODE_UP4UB, INST_NOP},
{C_OPCODE_X2D, INST_NOP},
{C_OPCODE_ARA, INST_NOP},
{C_OPCODE_ARR, INST_NOP},
{C_OPCODE_BRA, INST_NOP},
{C_OPCODE_CAL, INST_NOP},
{C_OPCODE_RET, INST_NOP},
{C_OPCODE_SSG, INST_NOP},
{C_OPCODE_CMP, INST_NOP},
{C_OPCODE_SCS, INST_NOP},
{C_OPCODE_TXB, INST_NOP},
{C_OPCODE_NRM, INST_NOP},
{C_OPCODE_DIV, INST_NOP},
{C_OPCODE_DP2, INST_NOP},
{C_OPCODE_TXL, INST_NOP},
{C_OPCODE_BRK, INST_NOP},
{C_OPCODE_IF, INST_NOP},
{C_OPCODE_BGNFOR, INST_NOP},
{C_OPCODE_REP, INST_NOP},
{C_OPCODE_ELSE, INST_NOP},
{C_OPCODE_ENDIF, INST_NOP},
{C_OPCODE_ENDFOR, INST_NOP},
{C_OPCODE_ENDREP, INST_NOP},
{C_OPCODE_PUSHA, INST_NOP},
{C_OPCODE_POPA, INST_NOP},
{C_OPCODE_CEIL, INST_NOP},
{C_OPCODE_I2F, INST_NOP},
{C_OPCODE_NOT, INST_NOP},
{C_OPCODE_TRUNC, INST_NOP},
{C_OPCODE_SHL, INST_NOP},
{88, INST_NOP},
{C_OPCODE_AND, INST_NOP},
{C_OPCODE_OR, INST_NOP},
{C_OPCODE_MOD, INST_NOP},
{C_OPCODE_XOR, INST_NOP},
{C_OPCODE_SAD, INST_NOP},
{C_OPCODE_TXF, INST_NOP},
{C_OPCODE_TXQ, INST_NOP},
{C_OPCODE_CONT, INST_NOP},
{C_OPCODE_EMIT, INST_NOP},
{C_OPCODE_ENDPRIM, INST_NOP},
{C_OPCODE_BGNLOOP, INST_NOP},
{C_OPCODE_BGNSUB, INST_NOP},
{C_OPCODE_ENDLOOP, INST_NOP},
{C_OPCODE_ENDSUB, INST_NOP},
{103, INST_NOP},
{104, INST_NOP},
{105, INST_NOP},
{106, INST_NOP},
{107, INST_NOP},
{108, INST_NOP},
{109, INST_NOP},
{110, INST_NOP},
{111, INST_NOP},
{C_OPCODE_NRM4, INST_NOP},
{C_OPCODE_CALLNZ, INST_NOP},
{C_OPCODE_IFC, INST_NOP},
{C_OPCODE_BREAKC, INST_NOP},
{C_OPCODE_KIL, INST_NOP},
{C_OPCODE_END, INST_NOP},
{118, INST_NOP},
{C_OPCODE_F2I, INST_NOP},
{C_OPCODE_IDIV, INST_NOP},
{C_OPCODE_IMAX, INST_NOP},
{C_OPCODE_IMIN, INST_NOP},
{C_OPCODE_INEG, INST_NOP},
{C_OPCODE_ISGE, INST_NOP},
{C_OPCODE_ISHR, INST_NOP},
{C_OPCODE_ISLT, INST_NOP},
{C_OPCODE_F2U, INST_NOP},
{C_OPCODE_U2F, INST_NOP},
{C_OPCODE_UADD, INST_NOP},
{C_OPCODE_UDIV, INST_NOP},
{C_OPCODE_UMAD, INST_NOP},
{C_OPCODE_UMAX, INST_NOP},
{C_OPCODE_UMIN, INST_NOP},
{C_OPCODE_UMOD, INST_NOP},
{C_OPCODE_UMUL, INST_NOP},
{C_OPCODE_USEQ, INST_NOP},
{C_OPCODE_USGE, INST_NOP},
{C_OPCODE_USHR, INST_NOP},
{C_OPCODE_USLT, INST_NOP},
{C_OPCODE_USNE, INST_NOP},
{C_OPCODE_SWITCH, INST_NOP},
{C_OPCODE_CASE, INST_NOP},
{C_OPCODE_DEFAULT, INST_NOP},
{C_OPCODE_ENDSWITCH, INST_NOP},
{C_OPCODE_VFETCH, INST_NOP},
{C_OPCODE_ENTRY, INST_NOP},
{C_OPCODE_ARL, INST_NOP},
};
static int r600_shader_alu_bytecode(struct r600_shader *rshader,
struct r600_shader_node *rnode,
struct r600_shader_inst *alu,
unsigned *cid)
{
unsigned id = *cid;
/* don't replace gpr by pv or ps for destination register */
if (alu->is_op3) {
rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_LAST(alu->last);
rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
S_SQ_ALU_WORD1_OP3_ALU_INST(alu->opcode) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
} else {
rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
S_SQ_ALU_WORD0_LAST(alu->last);
rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
S_SQ_ALU_WORD1_OP2_WRITE_MASK(1) |
S_SQ_ALU_WORD1_OP2_ALU_INST(alu->opcode) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
}
*cid = id;
return 0;
}
int r6xx_shader_alu_translate(struct r600_shader *rshader,
struct r600_shader_node *rnode,
unsigned *cid)
{
struct r600_shader_alu *alu;
unsigned id = *cid;
int i;
int r = 0;
LIST_FOR_EACH_ENTRY(alu, &rnode->alu, head) {
for (i = 0; i < alu->nalu; i++) {
r = r600_shader_alu_bytecode(rshader, rnode, &alu->alu[i], &id);
if (r)
goto out;
}
for (i = 0; i < alu->nliteral; i++) {
rshader->bcode[id++] = alu->literal[i];
}
}
out:
*cid = id;
return r;
}

View File

@ -1,233 +0,0 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include "r600_context.h"
#include "r700_sq.h"
static int r700_shader_cf_node_bytecode(struct r600_shader *rshader,
struct r600_shader_node *rnode,
unsigned *cid)
{
unsigned id = *cid;
if (rnode->nfetch) {
rshader->bcode[id++] = S_SQ_CF_WORD0_ADDR(rnode->cf_addr >> 1);
rshader->bcode[id++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) |
S_SQ_CF_WORD1_BARRIER(1) |
S_SQ_CF_WORD1_COUNT(rnode->nfetch - 1);
} else {
rshader->bcode[id++] = S_SQ_CF_ALU_WORD0_ADDR(rnode->cf_addr >> 1);
rshader->bcode[id++] = S_SQ_CF_ALU_WORD1_CF_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU) |
S_SQ_CF_ALU_WORD1_BARRIER(1) |
S_SQ_CF_ALU_WORD1_COUNT(rnode->nslot - 1);
}
*cid = id;
return 0;
}
static int r700_shader_cf_output_bytecode(struct r600_shader *rshader,
struct c_vector *v,
unsigned *cid,
unsigned end)
{
struct r600_shader_operand out;
unsigned id = *cid;
int r;
r = r600_shader_find_gpr(rshader, v, 0, &out);
if (r)
return r;
rshader->bcode[id + 0] = S_SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR(out.sel) |
S_SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE(3);
rshader->bcode[id + 1] = S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(0) |
S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y(1) |
S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z(2) |
S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W(3) |
S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(1) |
S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE) |
S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(end);
switch (v->name) {
case C_SEMANTIC_POSITION:
rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(60) |
S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS);
break;
case C_SEMANTIC_COLOR:
if (rshader->cshader.type == C_PROGRAM_TYPE_VS) {
rshader->output[rshader->noutput].gpr = out.sel;
rshader->output[rshader->noutput].sid = v->sid;
rshader->output[rshader->noutput].name = v->name;
rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(rshader->noutput++) |
S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM);
} else {
rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(0) |
S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL);
}
break;
case C_SEMANTIC_GENERIC:
rshader->output[rshader->noutput].gpr = out.sel;
rshader->output[rshader->noutput].sid = v->sid;
rshader->output[rshader->noutput].name = v->name;
rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(rshader->noutput++) |
S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM);
break;
default:
fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
*cid = id + 2;
return 0;
}
static int r700_shader_alu_bytecode(struct r600_shader *rshader,
struct r600_shader_node *rnode,
struct r600_shader_inst *alu,
unsigned *cid)
{
unsigned id = *cid;
/* don't replace gpr by pv or ps for destination register */
if (alu->is_op3) {
rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_LAST(alu->last);
rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
S_SQ_ALU_WORD1_OP3_ALU_INST(alu->opcode) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
} else {
rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
S_SQ_ALU_WORD0_LAST(alu->last);
rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
S_SQ_ALU_WORD1_OP2_WRITE_MASK(1) |
S_SQ_ALU_WORD1_OP2_ALU_INST(alu->opcode) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
}
*cid = id;
return 0;
}
static int r700_shader_alu_translate(struct r600_shader *rshader,
struct r600_shader_node *rnode,
unsigned *cid)
{
struct r600_shader_alu *alu;
unsigned id = *cid;
int i;
int r = 0;
LIST_FOR_EACH_ENTRY(alu, &rnode->alu, head) {
for (i = 0; i < alu->nalu; i++) {
r = r700_shader_alu_bytecode(rshader, rnode, &alu->alu[i], &id);
if (r)
goto out;
}
for (i = 0; i < alu->nliteral; i++) {
rshader->bcode[id++] = alu->literal[i];
}
}
out:
*cid = id;
return r;
}
int r700_shader_translate(struct r600_shader *rshader)
{
struct c_shader *shader = &rshader->cshader;
struct r600_shader_node *rnode;
struct r600_shader_vfetch *vfetch;
struct c_vector *v;
unsigned id, end;
int r;
r = r600_shader_register(rshader);
if (r) {
fprintf(stderr, "%s %d register allocation failed\n", __FILE__, __LINE__);
return r;
}
r = r600_shader_translate_rec(rshader, &shader->entry);
if (r) {
fprintf(stderr, "%s %d translation failed\n", __FILE__, __LINE__);
return r;
}
r = r600_shader_legalize(rshader);
if (r) {
fprintf(stderr, "%s %d legalize failed\n", __FILE__, __LINE__);
return r;
}
r600_shader_node_place(rshader);
rshader->bcode = malloc(rshader->ndw * 4);
if (rshader->bcode == NULL)
return -ENOMEM;
LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
id = rnode->cf_addr;
LIST_FOR_EACH_ENTRY(vfetch, &rnode->vfetch, head) {
r = r600_shader_vfetch_bytecode(rshader, rnode, vfetch, &id);
if (r)
return r;
}
if (rshader->r6xx_compile)
r = r6xx_shader_alu_translate(rshader, rnode, &id);
else
r = r700_shader_alu_translate(rshader, rnode, &id);
if (r)
return r;
}
id = 0;
LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
r = r700_shader_cf_node_bytecode(rshader, rnode, &id);
if (r)
return r;
}
LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_OUTPUT].vectors, head) {
end = 0;
if (v->head.next == &rshader->cshader.files[C_FILE_OUTPUT].vectors)
end = 1;
r = r700_shader_cf_output_bytecode(rshader, v, &id, end);
if (r)
return r;
}
LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_INPUT].vectors, head) {
rshader->input[rshader->ninput].gpr = rshader->ninput;
rshader->input[rshader->ninput].sid = v->sid;
rshader->input[rshader->ninput].name = v->name;
rshader->ninput++;
}
return 0;
}

View File

@ -1,730 +0,0 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <tgsi/tgsi_parse.h>
#include <tgsi/tgsi_scan.h>
#include "r600_shader.h"
#include "r600_context.h"
struct tgsi_shader {
struct c_vector **v[TGSI_FILE_COUNT];
struct tgsi_shader_info info;
struct tgsi_parse_context parser;
const struct tgsi_token *tokens;
struct c_shader *shader;
struct c_node *node;
};
static unsigned tgsi_file_to_c_file(unsigned file);
static unsigned tgsi_sname_to_c_sname(unsigned sname);
static int tgsi_opcode_to_c_opcode(unsigned opcode, unsigned *copcode);
static int tgsi_shader_init(struct tgsi_shader *ts,
const struct tgsi_token *tokens,
struct c_shader *shader)
{
int i;
ts->shader = shader;
ts->tokens = tokens;
tgsi_scan_shader(ts->tokens, &ts->info);
tgsi_parse_init(&ts->parser, ts->tokens);
/* initialize to NULL in case of error */
for (i = 0; i < C_FILE_COUNT; i++) {
ts->v[i] = NULL;
}
for (i = 0; i < TGSI_FILE_COUNT; i++) {
if (ts->info.file_count[i] > 0) {
ts->v[i] = calloc(ts->info.file_count[i], sizeof(void*));
if (ts->v[i] == NULL) {
fprintf(stderr, "%s:%d unsupported %d %d\n", __func__, __LINE__, i, ts->info.file_count[i]);
return -ENOMEM;
}
}
}
return 0;
}
static void tgsi_shader_destroy(struct tgsi_shader *ts)
{
int i;
for (i = 0; i < TGSI_FILE_COUNT; i++) {
free(ts->v[i]);
}
tgsi_parse_free(&ts->parser);
}
static int ntransform_declaration(struct tgsi_shader *ts)
{
struct tgsi_full_declaration *fd = &ts->parser.FullToken.FullDeclaration;
struct c_vector *v;
unsigned file;
unsigned name;
int sid;
int i;
if (fd->Declaration.Dimension) {
fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
for (i = fd->Range.First ; i <= fd->Range.Last; i++) {
sid = i;
name = C_SEMANTIC_GENERIC;
file = tgsi_file_to_c_file(fd->Declaration.File);
if (file == TGSI_FILE_NULL) {
fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
if (fd->Declaration.Semantic) {
name = tgsi_sname_to_c_sname(fd->Semantic.Name);
sid = fd->Semantic.Index;
}
v = c_shader_vector_new(ts->shader, file, name, sid);
if (v == NULL) {
fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
return -ENOMEM;
}
ts->v[fd->Declaration.File][i] = v;
}
return 0;
}
static int ntransform_immediate(struct tgsi_shader *ts)
{
struct tgsi_full_immediate *fd = &ts->parser.FullToken.FullImmediate;
struct c_vector *v;
unsigned file;
unsigned name;
if (fd->Immediate.DataType != TGSI_IMM_FLOAT32) {
fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
name = C_SEMANTIC_GENERIC;
file = C_FILE_IMMEDIATE;
v = c_shader_vector_new(ts->shader, file, name, 0);
if (v == NULL) {
fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
return -ENOMEM;
}
v->channel[0]->value = fd->u[0].Uint;
v->channel[1]->value = fd->u[1].Uint;
v->channel[2]->value = fd->u[2].Uint;
v->channel[3]->value = fd->u[3].Uint;
ts->v[TGSI_FILE_IMMEDIATE][0] = v;
return 0;
}
static int ntransform_instruction(struct tgsi_shader *ts)
{
struct tgsi_full_instruction *fi = &ts->parser.FullToken.FullInstruction;
struct c_shader *shader = ts->shader;
struct c_instruction instruction;
unsigned opcode;
int i, j, r;
if (fi->Instruction.NumDstRegs > 1) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
if (fi->Instruction.Saturate) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
if (fi->Instruction.Predicate) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
if (fi->Instruction.Label) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
if (fi->Instruction.Texture) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
for (i = 0; i < fi->Instruction.NumSrcRegs; i++) {
if (fi->Src[i].Register.Indirect ||
fi->Src[i].Register.Dimension ||
fi->Src[i].Register.Absolute) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
}
for (i = 0; i < fi->Instruction.NumDstRegs; i++) {
if (fi->Dst[i].Register.Indirect || fi->Dst[i].Register.Dimension) {
fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
return -EINVAL;
}
}
r = tgsi_opcode_to_c_opcode(fi->Instruction.Opcode, &opcode);
if (r) {
fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
return r;
}
if (opcode == C_OPCODE_END) {
return c_node_cfg_link(ts->node, &shader->end);
}
/* FIXME add flow instruction handling */
memset(&instruction, 0, sizeof(struct c_instruction));
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++;
}
return c_node_add_new_instruction(ts->node, &instruction);
}
int c_shader_from_tgsi(struct c_shader *shader, unsigned type,
const struct tgsi_token *tokens)
{
struct tgsi_shader ts;
int r = 0;
c_shader_init(shader, type);
r = tgsi_shader_init(&ts, tokens, shader);
if (r)
goto out_err;
ts.shader = shader;
ts.node = &shader->entry;
while (!tgsi_parse_end_of_tokens(&ts.parser)) {
tgsi_parse_token(&ts.parser);
switch (ts.parser.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_IMMEDIATE:
r = ntransform_immediate(&ts);
if (r)
goto out_err;
break;
case TGSI_TOKEN_TYPE_DECLARATION:
r = ntransform_declaration(&ts);
if (r)
goto out_err;
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
r = ntransform_instruction(&ts);
if (r)
goto out_err;
break;
default:
r = -EINVAL;
goto out_err;
}
}
tgsi_shader_destroy(&ts);
return 0;
out_err:
c_shader_destroy(shader);
tgsi_shader_destroy(&ts);
return r;
}
static unsigned tgsi_file_to_c_file(unsigned file)
{
switch (file) {
case TGSI_FILE_CONSTANT:
return C_FILE_CONSTANT;
case TGSI_FILE_INPUT:
return C_FILE_INPUT;
case TGSI_FILE_OUTPUT:
return C_FILE_OUTPUT;
case TGSI_FILE_TEMPORARY:
return C_FILE_TEMPORARY;
case TGSI_FILE_SAMPLER:
return C_FILE_SAMPLER;
case TGSI_FILE_ADDRESS:
return C_FILE_ADDRESS;
case TGSI_FILE_IMMEDIATE:
return C_FILE_IMMEDIATE;
case TGSI_FILE_PREDICATE:
return C_FILE_PREDICATE;
case TGSI_FILE_SYSTEM_VALUE:
return C_FILE_SYSTEM_VALUE;
case TGSI_FILE_NULL:
return C_FILE_NULL;
default:
fprintf(stderr, "%s:%d unsupported file %d\n", __func__, __LINE__, file);
return C_FILE_NULL;
}
}
static unsigned tgsi_sname_to_c_sname(unsigned sname)
{
switch (sname) {
case TGSI_SEMANTIC_POSITION:
return C_SEMANTIC_POSITION;
case TGSI_SEMANTIC_COLOR:
return C_SEMANTIC_COLOR;
case TGSI_SEMANTIC_BCOLOR:
return C_SEMANTIC_BCOLOR;
case TGSI_SEMANTIC_FOG:
return C_SEMANTIC_FOG;
case TGSI_SEMANTIC_PSIZE:
return C_SEMANTIC_PSIZE;
case TGSI_SEMANTIC_GENERIC:
return C_SEMANTIC_GENERIC;
case TGSI_SEMANTIC_NORMAL:
return C_SEMANTIC_NORMAL;
case TGSI_SEMANTIC_FACE:
return C_SEMANTIC_FACE;
case TGSI_SEMANTIC_EDGEFLAG:
return C_SEMANTIC_EDGEFLAG;
case TGSI_SEMANTIC_PRIMID:
return C_SEMANTIC_PRIMID;
case TGSI_SEMANTIC_INSTANCEID:
return C_SEMANTIC_INSTANCEID;
default:
return C_SEMANTIC_GENERIC;
}
}
static int tgsi_opcode_to_c_opcode(unsigned opcode, unsigned *copcode)
{
switch (opcode) {
case TGSI_OPCODE_MOV:
*copcode = C_OPCODE_MOV;
return 0;
case TGSI_OPCODE_MUL:
*copcode = C_OPCODE_MUL;
return 0;
case TGSI_OPCODE_MAD:
*copcode = C_OPCODE_MAD;
return 0;
case TGSI_OPCODE_END:
*copcode = C_OPCODE_END;
return 0;
case TGSI_OPCODE_ARL:
*copcode = C_OPCODE_ARL;
return 0;
case TGSI_OPCODE_LIT:
*copcode = C_OPCODE_LIT;
return 0;
case TGSI_OPCODE_RCP:
*copcode = C_OPCODE_RCP;
return 0;
case TGSI_OPCODE_RSQ:
*copcode = C_OPCODE_RSQ;
return 0;
case TGSI_OPCODE_EXP:
*copcode = C_OPCODE_EXP;
return 0;
case TGSI_OPCODE_LOG:
*copcode = C_OPCODE_LOG;
return 0;
case TGSI_OPCODE_ADD:
*copcode = C_OPCODE_ADD;
return 0;
case TGSI_OPCODE_DP3:
*copcode = C_OPCODE_DP3;
return 0;
case TGSI_OPCODE_DP4:
*copcode = C_OPCODE_DP4;
return 0;
case TGSI_OPCODE_DST:
*copcode = C_OPCODE_DST;
return 0;
case TGSI_OPCODE_MIN:
*copcode = C_OPCODE_MIN;
return 0;
case TGSI_OPCODE_MAX:
*copcode = C_OPCODE_MAX;
return 0;
case TGSI_OPCODE_SLT:
*copcode = C_OPCODE_SLT;
return 0;
case TGSI_OPCODE_SGE:
*copcode = C_OPCODE_SGE;
return 0;
case TGSI_OPCODE_SUB:
*copcode = C_OPCODE_SUB;
return 0;
case TGSI_OPCODE_LRP:
*copcode = C_OPCODE_LRP;
return 0;
case TGSI_OPCODE_CND:
*copcode = C_OPCODE_CND;
return 0;
case TGSI_OPCODE_DP2A:
*copcode = C_OPCODE_DP2A;
return 0;
case TGSI_OPCODE_FRC:
*copcode = C_OPCODE_FRC;
return 0;
case TGSI_OPCODE_CLAMP:
*copcode = C_OPCODE_CLAMP;
return 0;
case TGSI_OPCODE_FLR:
*copcode = C_OPCODE_FLR;
return 0;
case TGSI_OPCODE_ROUND:
*copcode = C_OPCODE_ROUND;
return 0;
case TGSI_OPCODE_EX2:
*copcode = C_OPCODE_EX2;
return 0;
case TGSI_OPCODE_LG2:
*copcode = C_OPCODE_LG2;
return 0;
case TGSI_OPCODE_POW:
*copcode = C_OPCODE_POW;
return 0;
case TGSI_OPCODE_XPD:
*copcode = C_OPCODE_XPD;
return 0;
case TGSI_OPCODE_ABS:
*copcode = C_OPCODE_ABS;
return 0;
case TGSI_OPCODE_RCC:
*copcode = C_OPCODE_RCC;
return 0;
case TGSI_OPCODE_DPH:
*copcode = C_OPCODE_DPH;
return 0;
case TGSI_OPCODE_COS:
*copcode = C_OPCODE_COS;
return 0;
case TGSI_OPCODE_DDX:
*copcode = C_OPCODE_DDX;
return 0;
case TGSI_OPCODE_DDY:
*copcode = C_OPCODE_DDY;
return 0;
case TGSI_OPCODE_KILP:
*copcode = C_OPCODE_KILP;
return 0;
case TGSI_OPCODE_PK2H:
*copcode = C_OPCODE_PK2H;
return 0;
case TGSI_OPCODE_PK2US:
*copcode = C_OPCODE_PK2US;
return 0;
case TGSI_OPCODE_PK4B:
*copcode = C_OPCODE_PK4B;
return 0;
case TGSI_OPCODE_PK4UB:
*copcode = C_OPCODE_PK4UB;
return 0;
case TGSI_OPCODE_RFL:
*copcode = C_OPCODE_RFL;
return 0;
case TGSI_OPCODE_SEQ:
*copcode = C_OPCODE_SEQ;
return 0;
case TGSI_OPCODE_SFL:
*copcode = C_OPCODE_SFL;
return 0;
case TGSI_OPCODE_SGT:
*copcode = C_OPCODE_SGT;
return 0;
case TGSI_OPCODE_SIN:
*copcode = C_OPCODE_SIN;
return 0;
case TGSI_OPCODE_SLE:
*copcode = C_OPCODE_SLE;
return 0;
case TGSI_OPCODE_SNE:
*copcode = C_OPCODE_SNE;
return 0;
case TGSI_OPCODE_STR:
*copcode = C_OPCODE_STR;
return 0;
case TGSI_OPCODE_TEX:
*copcode = C_OPCODE_TEX;
return 0;
case TGSI_OPCODE_TXD:
*copcode = C_OPCODE_TXD;
return 0;
case TGSI_OPCODE_TXP:
*copcode = C_OPCODE_TXP;
return 0;
case TGSI_OPCODE_UP2H:
*copcode = C_OPCODE_UP2H;
return 0;
case TGSI_OPCODE_UP2US:
*copcode = C_OPCODE_UP2US;
return 0;
case TGSI_OPCODE_UP4B:
*copcode = C_OPCODE_UP4B;
return 0;
case TGSI_OPCODE_UP4UB:
*copcode = C_OPCODE_UP4UB;
return 0;
case TGSI_OPCODE_X2D:
*copcode = C_OPCODE_X2D;
return 0;
case TGSI_OPCODE_ARA:
*copcode = C_OPCODE_ARA;
return 0;
case TGSI_OPCODE_ARR:
*copcode = C_OPCODE_ARR;
return 0;
case TGSI_OPCODE_BRA:
*copcode = C_OPCODE_BRA;
return 0;
case TGSI_OPCODE_CAL:
*copcode = C_OPCODE_CAL;
return 0;
case TGSI_OPCODE_RET:
*copcode = C_OPCODE_RET;
return 0;
case TGSI_OPCODE_SSG:
*copcode = C_OPCODE_SSG;
return 0;
case TGSI_OPCODE_CMP:
*copcode = C_OPCODE_CMP;
return 0;
case TGSI_OPCODE_SCS:
*copcode = C_OPCODE_SCS;
return 0;
case TGSI_OPCODE_TXB:
*copcode = C_OPCODE_TXB;
return 0;
case TGSI_OPCODE_NRM:
*copcode = C_OPCODE_NRM;
return 0;
case TGSI_OPCODE_DIV:
*copcode = C_OPCODE_DIV;
return 0;
case TGSI_OPCODE_DP2:
*copcode = C_OPCODE_DP2;
return 0;
case TGSI_OPCODE_TXL:
*copcode = C_OPCODE_TXL;
return 0;
case TGSI_OPCODE_BRK:
*copcode = C_OPCODE_BRK;
return 0;
case TGSI_OPCODE_IF:
*copcode = C_OPCODE_IF;
return 0;
case TGSI_OPCODE_ELSE:
*copcode = C_OPCODE_ELSE;
return 0;
case TGSI_OPCODE_ENDIF:
*copcode = C_OPCODE_ENDIF;
return 0;
case TGSI_OPCODE_PUSHA:
*copcode = C_OPCODE_PUSHA;
return 0;
case TGSI_OPCODE_POPA:
*copcode = C_OPCODE_POPA;
return 0;
case TGSI_OPCODE_CEIL:
*copcode = C_OPCODE_CEIL;
return 0;
case TGSI_OPCODE_I2F:
*copcode = C_OPCODE_I2F;
return 0;
case TGSI_OPCODE_NOT:
*copcode = C_OPCODE_NOT;
return 0;
case TGSI_OPCODE_TRUNC:
*copcode = C_OPCODE_TRUNC;
return 0;
case TGSI_OPCODE_SHL:
*copcode = C_OPCODE_SHL;
return 0;
case TGSI_OPCODE_AND:
*copcode = C_OPCODE_AND;
return 0;
case TGSI_OPCODE_OR:
*copcode = C_OPCODE_OR;
return 0;
case TGSI_OPCODE_MOD:
*copcode = C_OPCODE_MOD;
return 0;
case TGSI_OPCODE_XOR:
*copcode = C_OPCODE_XOR;
return 0;
case TGSI_OPCODE_SAD:
*copcode = C_OPCODE_SAD;
return 0;
case TGSI_OPCODE_TXF:
*copcode = C_OPCODE_TXF;
return 0;
case TGSI_OPCODE_TXQ:
*copcode = C_OPCODE_TXQ;
return 0;
case TGSI_OPCODE_CONT:
*copcode = C_OPCODE_CONT;
return 0;
case TGSI_OPCODE_EMIT:
*copcode = C_OPCODE_EMIT;
return 0;
case TGSI_OPCODE_ENDPRIM:
*copcode = C_OPCODE_ENDPRIM;
return 0;
case TGSI_OPCODE_BGNLOOP:
*copcode = C_OPCODE_BGNLOOP;
return 0;
case TGSI_OPCODE_BGNSUB:
*copcode = C_OPCODE_BGNSUB;
return 0;
case TGSI_OPCODE_ENDLOOP:
*copcode = C_OPCODE_ENDLOOP;
return 0;
case TGSI_OPCODE_ENDSUB:
*copcode = C_OPCODE_ENDSUB;
return 0;
case TGSI_OPCODE_NOP:
*copcode = C_OPCODE_NOP;
return 0;
case TGSI_OPCODE_NRM4:
*copcode = C_OPCODE_NRM4;
return 0;
case TGSI_OPCODE_CALLNZ:
*copcode = C_OPCODE_CALLNZ;
return 0;
case TGSI_OPCODE_IFC:
*copcode = C_OPCODE_IFC;
return 0;
case TGSI_OPCODE_BREAKC:
*copcode = C_OPCODE_BREAKC;
return 0;
case TGSI_OPCODE_KIL:
*copcode = C_OPCODE_KIL;
return 0;
case TGSI_OPCODE_F2I:
*copcode = C_OPCODE_F2I;
return 0;
case TGSI_OPCODE_IDIV:
*copcode = C_OPCODE_IDIV;
return 0;
case TGSI_OPCODE_IMAX:
*copcode = C_OPCODE_IMAX;
return 0;
case TGSI_OPCODE_IMIN:
*copcode = C_OPCODE_IMIN;
return 0;
case TGSI_OPCODE_INEG:
*copcode = C_OPCODE_INEG;
return 0;
case TGSI_OPCODE_ISGE:
*copcode = C_OPCODE_ISGE;
return 0;
case TGSI_OPCODE_ISHR:
*copcode = C_OPCODE_ISHR;
return 0;
case TGSI_OPCODE_ISLT:
*copcode = C_OPCODE_ISLT;
return 0;
case TGSI_OPCODE_F2U:
*copcode = C_OPCODE_F2U;
return 0;
case TGSI_OPCODE_U2F:
*copcode = C_OPCODE_U2F;
return 0;
case TGSI_OPCODE_UADD:
*copcode = C_OPCODE_UADD;
return 0;
case TGSI_OPCODE_UDIV:
*copcode = C_OPCODE_UDIV;
return 0;
case TGSI_OPCODE_UMAD:
*copcode = C_OPCODE_UMAD;
return 0;
case TGSI_OPCODE_UMAX:
*copcode = C_OPCODE_UMAX;
return 0;
case TGSI_OPCODE_UMIN:
*copcode = C_OPCODE_UMIN;
return 0;
case TGSI_OPCODE_UMOD:
*copcode = C_OPCODE_UMOD;
return 0;
case TGSI_OPCODE_UMUL:
*copcode = C_OPCODE_UMUL;
return 0;
case TGSI_OPCODE_USEQ:
*copcode = C_OPCODE_USEQ;
return 0;
case TGSI_OPCODE_USGE:
*copcode = C_OPCODE_USGE;
return 0;
case TGSI_OPCODE_USHR:
*copcode = C_OPCODE_USHR;
return 0;
case TGSI_OPCODE_USLT:
*copcode = C_OPCODE_USLT;
return 0;
case TGSI_OPCODE_USNE:
*copcode = C_OPCODE_USNE;
return 0;
case TGSI_OPCODE_SWITCH:
*copcode = C_OPCODE_SWITCH;
return 0;
case TGSI_OPCODE_CASE:
*copcode = C_OPCODE_CASE;
return 0;
case TGSI_OPCODE_DEFAULT:
*copcode = C_OPCODE_DEFAULT;
return 0;
case TGSI_OPCODE_ENDSWITCH:
*copcode = C_OPCODE_ENDSWITCH;
return 0;
default:
fprintf(stderr, "%s:%d unsupported opcode %d\n", __func__, __LINE__, opcode);
return -EINVAL;
}
}

View File

@ -55,7 +55,7 @@ static void r600_flush(struct pipe_context *ctx, unsigned flags,
*/
if (!dc)
radeon_ctx_dump_bof(rctx->ctx, "gallium.bof");
#if 0
#if 1
radeon_ctx_submit(rctx->ctx);
#endif
rctx->ctx = radeon_ctx_decref(rctx->ctx);

View File

@ -40,7 +40,6 @@ struct r600_vertex_elements_state
};
struct r600_pipe_shader {
unsigned type;
struct r600_shader shader;
struct radeon_bo *bo;
struct radeon_state *state;
@ -92,8 +91,10 @@ struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *rpshader);
struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx,
unsigned type,
const struct tgsi_token *tokens);
int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rpshader);
#define R600_ERR(fmt, args...) \
fprintf(stderr, "EE %s/%s:%d - "fmt, __FILE__, __func__, __LINE__, ##args)
#endif

View File

@ -19,40 +19,112 @@
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Jerome Glisse
*/
#include <stdio.h>
#include <errno.h>
#include <util/u_inlines.h>
#include <util/u_format.h>
#include <util/u_memory.h>
#include <tgsi/tgsi_dump.h>
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_scan.h"
#include "util/u_format.h"
#include "r600_screen.h"
#include "r600_context.h"
#include "r600_shader.h"
#include "r600_asm.h"
#include "r600_sq.h"
#include "r600d.h"
#include <stdio.h>
#include <errno.h>
static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader);
static int r600_shader_update(struct pipe_context *ctx, struct r600_shader *shader)
{
struct r600_context *rctx = r600_context(ctx);
const struct util_format_description *desc;
enum pipe_format resource_format[160];
unsigned i, nresources = 0;
struct r600_bc *bc = &shader->bc;
struct r600_bc_cf *cf;
struct r600_bc_vtx *vtx;
if (shader->processor_type != TGSI_PROCESSOR_VERTEX)
return 0;
for (i = 0; i < rctx->vertex_elements->count; i++) {
resource_format[nresources++] = rctx->vertex_elements->elements[i].src_format;
}
LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
switch (cf->inst) {
case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) {
desc = util_format_description(resource_format[vtx->buffer_id]);
if (desc == NULL) {
R600_ERR("unknown format %d\n", resource_format[vtx->buffer_id]);
return -EINVAL;
}
vtx->dst_sel_x = desc->swizzle[0];
vtx->dst_sel_y = desc->swizzle[1];
vtx->dst_sel_z = desc->swizzle[2];
vtx->dst_sel_w = desc->swizzle[3];
}
break;
default:
break;
}
}
return r600_bc_build(&shader->bc);
}
struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx,
const struct tgsi_token *tokens)
{
struct r600_screen *rscreen = r600_screen(ctx->screen);
struct r600_pipe_shader *rpshader = CALLOC_STRUCT(r600_pipe_shader);
int r;
fprintf(stderr, "--------------------------------------------------------------\n");
tgsi_dump(tokens, 0);
if (rpshader == NULL)
return NULL;
rpshader->shader.family = radeon_get_family(rscreen->rw);
r = r600_shader_from_tgsi(tokens, &rpshader->shader);
if (r) {
R600_ERR("translation from TGSI failed !\n");
goto out_err;
}
r = r600_bc_build(&rpshader->shader.bc);
if (r) {
R600_ERR("building bytecode failed !\n");
goto out_err;
}
fprintf(stderr, "______________________________________________________________\n");
return rpshader;
out_err:
free(rpshader);
return NULL;
}
static int r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
{
struct r600_screen *rscreen = r600_screen(ctx->screen);
struct r600_shader *rshader = &rpshader->shader;
struct radeon_state *state;
unsigned i, tmp;
unsigned i, j, tmp;
rpshader->state = radeon_state_decref(rpshader->state);
state = radeon_state(rscreen->rw, R600_VS_SHADER_TYPE, R600_VS_SHADER);
if (state == NULL)
return -ENOMEM;
for (i = 0; i < rshader->noutput; i += 4) {
tmp = rshader->output[i].sid;
tmp |= rshader->output[i + 1].sid << 8;
tmp |= rshader->output[i + 2].sid << 16;
tmp |= rshader->output[i + 3].sid << 24;
state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i / 4] = tmp;
for (i = 0; i < 10; i++) {
state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i] = 0;
}
state->states[R600_VS_SHADER__SPI_VS_OUT_CONFIG] = S_0286C4_VS_EXPORT_COUNT(rshader->noutput - 1);
state->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = S_028868_NUM_GPRS(rshader->ngpr);
for (i = 0, j = 0; i < rshader->noutput; i++) {
if (rshader->output[i].name != TGSI_SEMANTIC_POSITION) {
tmp = rshader->output[i].sid << ((j & 3) * 8);
state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + j / 4] |= tmp;
j++;
}
}
state->states[R600_VS_SHADER__SPI_VS_OUT_CONFIG] = S_0286C4_VS_EXPORT_COUNT(rshader->noutput - 2);
state->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = S_028868_NUM_GPRS(rshader->bc.ngpr);
rpshader->state = state;
rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
rpshader->state->bo[1] = radeon_bo_incref(rscreen->rw, rpshader->bo);
@ -81,7 +153,7 @@ static int r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_0] = S_0286CC_NUM_INTERP(rshader->ninput) |
S_0286CC_PERSP_GRADIENT_ENA(1);
state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_1] = 0x00000000;
state->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = S_028868_NUM_GPRS(rshader->ngpr);
state->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = S_028868_NUM_GPRS(rshader->bc.ngpr);
state->states[R600_PS_SHADER__SQ_PGM_EXPORTS_PS] = 0x00000002;
rpshader->state = state;
rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
@ -100,21 +172,21 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *r
/* copy new shader */
radeon_bo_decref(rscreen->rw, rpshader->bo);
rpshader->bo = NULL;
rpshader->bo = radeon_bo(rscreen->rw, 0, rshader->ndw * 4,
rpshader->bo = radeon_bo(rscreen->rw, 0, rshader->bc.ndw * 4,
4096, NULL);
if (rpshader->bo == NULL) {
return -ENOMEM;
}
radeon_bo_map(rscreen->rw, rpshader->bo);
memcpy(rpshader->bo->data, rshader->bcode, rshader->ndw * 4);
memcpy(rpshader->bo->data, rshader->bc.bytecode, rshader->bc.ndw * 4);
radeon_bo_unmap(rscreen->rw, rpshader->bo);
/* build state */
rshader->flat_shade = rctx->flat_shade;
switch (rpshader->type) {
case C_PROGRAM_TYPE_VS:
switch (rshader->processor_type) {
case TGSI_PROCESSOR_VERTEX:
r = r600_pipe_shader_vs(ctx, rpshader);
break;
case C_PROGRAM_TYPE_FS:
case TGSI_PROCESSOR_FRAGMENT:
r = r600_pipe_shader_ps(ctx, rpshader);
break;
default:
@ -124,104 +196,610 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *r
return r;
}
struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx, unsigned type, const struct tgsi_token *tokens)
{
struct r600_screen *rscreen = r600_screen(ctx->screen);
struct r600_pipe_shader *rpshader = CALLOC_STRUCT(r600_pipe_shader);
struct r600_shader *rshader = &rpshader->shader;
int r;
enum radeon_family family;
if (rpshader == NULL)
return NULL;
rpshader->type = type;
family = radeon_get_family(rscreen->rw);
rshader->r6xx_compile = (family >= CHIP_R600 && family < CHIP_RV770);
LIST_INITHEAD(&rshader->nodes);
fprintf(stderr, "<< %s\n", rshader->r6xx_compile ? "R600" : "R700");
tgsi_dump(tokens, 0);
fprintf(stderr, "--------------------------------------------------------------\n");
r = c_shader_from_tgsi(&rshader->cshader, type, tokens);
if (r) {
r600_pipe_shader_destroy(ctx, rpshader);
fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
return NULL;
}
r = r600_shader_insert_fetch(&rshader->cshader);
if (r) {
r600_pipe_shader_destroy(ctx, rpshader);
fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
return NULL;
}
r = c_shader_build_dominator_tree(&rshader->cshader);
if (r) {
r600_pipe_shader_destroy(ctx, rpshader);
fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
return NULL;
}
r = r600_cshader_legalize(&rshader->cshader);
if (r) {
r600_pipe_shader_destroy(ctx, rpshader);
fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
return NULL;
}
c_shader_dump(&rshader->cshader);
r = r700_shader_translate(rshader);
if (r) {
r600_pipe_shader_destroy(ctx, rpshader);
fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
return NULL;
}
#if 1
#if 0
fprintf(stderr, "--------------------------------------------------------------\n");
for (int i = 0; i < rshader->ndw; i++) {
fprintf(stderr, "0x%08X\n", rshader->bcode[i]);
}
#endif
fprintf(stderr, ">>\n\n");
#endif
return rpshader;
}
void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
{
struct r600_screen *rscreen = r600_screen(ctx->screen);
if (rpshader == NULL)
return;
radeon_bo_decref(rscreen->rw, rpshader->bo);
rpshader->bo = NULL;
r600_shader_cleanup(&rpshader->shader);
FREE(rpshader);
}
int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
{
struct r600_context *rctx = r600_context(ctx);
struct r600_shader *rshader;
enum pipe_format resource_format[160];
unsigned i, nresources = 0;
int r;
if (rpshader == NULL)
return -EINVAL;
rshader = &rpshader->shader;
switch (rpshader->type) {
case C_PROGRAM_TYPE_VS:
for (i = 0; i < rctx->vertex_elements->count; i++) {
resource_format[nresources++] = rctx->vertex_elements->elements[i].src_format;
}
break;
default:
break;
}
/* there should be enough input */
if (nresources < rshader->nresource)
if (rctx->vertex_elements->count < rpshader->shader.bc.nresource) {
R600_ERR("%d resources provided, expecting %d\n",
rctx->vertex_elements->count, rpshader->shader.bc.nresource);
return -EINVAL;
/* FIXME compare resources */
r = r600_shader_update(rshader, resource_format);
}
r = r600_shader_update(ctx, &rpshader->shader);
if (r)
return r;
return r600_pipe_shader(ctx, rpshader);
}
struct r600_shader_tgsi_instruction;
struct r600_shader_ctx {
struct tgsi_shader_info info;
struct tgsi_parse_context parse;
const struct tgsi_token *tokens;
unsigned type;
unsigned file_offset[TGSI_FILE_COUNT];
unsigned temp_reg;
struct r600_shader_tgsi_instruction *inst_info;
struct r600_bc *bc;
struct r600_shader *shader;
};
struct r600_shader_tgsi_instruction {
unsigned tgsi_opcode;
unsigned is_op3;
unsigned r600_opcode;
int (*process)(struct r600_shader_ctx *ctx);
};
static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[];
static int tgsi_is_supported(struct r600_shader_ctx *ctx)
{
struct tgsi_full_instruction *i = &ctx->parse.FullToken.FullInstruction;
int j;
if (i->Instruction.NumDstRegs > 1) {
R600_ERR("too many dst (%d)\n", i->Instruction.NumDstRegs);
return -EINVAL;
}
if (i->Instruction.Saturate) {
R600_ERR("staturate unsupported\n");
return -EINVAL;
}
if (i->Instruction.Predicate) {
R600_ERR("predicate unsupported\n");
return -EINVAL;
}
if (i->Instruction.Label) {
R600_ERR("label unsupported\n");
return -EINVAL;
}
if (i->Instruction.Texture) {
R600_ERR("texture unsupported\n");
return -EINVAL;
}
for (j = 0; j < i->Instruction.NumSrcRegs; j++) {
if (i->Src[j].Register.Indirect ||
i->Src[j].Register.Dimension ||
i->Src[j].Register.Absolute) {
R600_ERR("unsupported src (indirect|dimension|absolute)\n");
return -EINVAL;
}
}
for (j = 0; j < i->Instruction.NumDstRegs; j++) {
if (i->Dst[j].Register.Indirect || i->Dst[j].Register.Dimension) {
R600_ERR("unsupported dst (indirect|dimension)\n");
return -EINVAL;
}
}
return 0;
}
static int tgsi_declaration(struct r600_shader_ctx *ctx)
{
struct tgsi_full_declaration *d = &ctx->parse.FullToken.FullDeclaration;
struct r600_bc_vtx vtx;
unsigned i;
int r;
switch (d->Declaration.File) {
case TGSI_FILE_INPUT:
i = ctx->shader->ninput++;
ctx->shader->input[i].name = d->Semantic.Name;
ctx->shader->input[i].sid = d->Semantic.Index;
ctx->shader->input[i].gpr = ctx->file_offset[TGSI_FILE_INPUT] + i;
if (ctx->type == TGSI_PROCESSOR_VERTEX) {
/* turn input into fetch */
memset(&vtx, 0, sizeof(struct r600_bc_vtx));
vtx.inst = 0;
vtx.fetch_type = 0;
vtx.buffer_id = i;
/* register containing the index into the buffer */
vtx.src_gpr = 0;
vtx.src_sel_x = 0;
vtx.mega_fetch_count = 0x1F;
vtx.dst_gpr = ctx->shader->input[i].gpr;
vtx.dst_sel_x = 0;
vtx.dst_sel_y = 1;
vtx.dst_sel_z = 2;
vtx.dst_sel_w = 3;
r = r600_bc_add_vtx(ctx->bc, &vtx);
if (r)
return r;
}
break;
case TGSI_FILE_OUTPUT:
i = ctx->shader->noutput++;
ctx->shader->output[i].name = d->Semantic.Name;
ctx->shader->output[i].sid = d->Semantic.Index;
ctx->shader->output[i].gpr = ctx->file_offset[TGSI_FILE_OUTPUT] + i;
break;
case TGSI_FILE_CONSTANT:
case TGSI_FILE_TEMPORARY:
break;
default:
R600_ERR("unsupported file %d declaration\n", d->Declaration.File);
return -EINVAL;
}
return 0;
}
int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader)
{
struct tgsi_full_immediate *immediate;
struct r600_shader_ctx ctx;
struct r600_bc_output output;
unsigned opcode;
int i, r = 0, pos0;
u32 value[4];
ctx.bc = &shader->bc;
ctx.shader = shader;
r = r600_bc_init(ctx.bc, shader->family);
if (r)
return r;
ctx.tokens = tokens;
tgsi_scan_shader(tokens, &ctx.info);
tgsi_parse_init(&ctx.parse, tokens);
ctx.type = ctx.parse.FullHeader.Processor.Processor;
shader->processor_type = ctx.type;
/* register allocations */
/* Values [0,127] correspond to GPR[0..127].
* Values [256,511] correspond to cfile constants c[0..255].
* Other special values are shown in the list below.
* 248 SQ_ALU_SRC_0: special constant 0.0.
* 249 SQ_ALU_SRC_1: special constant 1.0 float.
* 250 SQ_ALU_SRC_1_INT: special constant 1 integer.
* 251 SQ_ALU_SRC_M_1_INT: special constant -1 integer.
* 252 SQ_ALU_SRC_0_5: special constant 0.5 float.
* 253 SQ_ALU_SRC_LITERAL: literal constant.
* 254 SQ_ALU_SRC_PV: previous vector result.
* 255 SQ_ALU_SRC_PS: previous scalar result.
*/
for (i = 0; i < TGSI_FILE_COUNT; i++) {
ctx.file_offset[i] = 0;
}
if (ctx.type == TGSI_PROCESSOR_VERTEX) {
ctx.file_offset[TGSI_FILE_INPUT] = 1;
}
ctx.file_offset[TGSI_FILE_OUTPUT] = ctx.file_offset[TGSI_FILE_INPUT] +
ctx.info.file_count[TGSI_FILE_INPUT];
ctx.file_offset[TGSI_FILE_TEMPORARY] = ctx.file_offset[TGSI_FILE_OUTPUT] +
ctx.info.file_count[TGSI_FILE_OUTPUT];
ctx.file_offset[TGSI_FILE_CONSTANT] = 256;
ctx.file_offset[TGSI_FILE_IMMEDIATE] = 253;
ctx.temp_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] +
ctx.info.file_count[TGSI_FILE_TEMPORARY];
while (!tgsi_parse_end_of_tokens(&ctx.parse)) {
tgsi_parse_token(&ctx.parse);
switch (ctx.parse.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_IMMEDIATE:
// R600_ERR("TGSI_TOKEN_TYPE_IMMEDIATE unsupported\n");
immediate = &ctx.parse.FullToken.FullImmediate;
value[0] = immediate->u[0].Uint;
value[1] = immediate->u[1].Uint;
value[2] = immediate->u[2].Uint;
value[3] = immediate->u[3].Uint;
break;
case TGSI_TOKEN_TYPE_DECLARATION:
r = tgsi_declaration(&ctx);
if (r)
goto out_err;
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
r = tgsi_is_supported(&ctx);
if (r)
goto out_err;
opcode = ctx.parse.FullToken.FullInstruction.Instruction.Opcode;
ctx.inst_info = &r600_shader_tgsi_instruction[opcode];
r = ctx.inst_info->process(&ctx);
if (r)
goto out_err;
r = r600_bc_add_literal(ctx.bc, value);
if (r)
goto out_err;
break;
default:
R600_ERR("unsupported token type %d\n", ctx.parse.FullToken.Token.Type);
r = -EINVAL;
goto out_err;
}
}
/* export output */
for (i = 0, pos0 = 0; i < shader->noutput; i++) {
memset(&output, 0, sizeof(struct r600_bc_output));
output.gpr = shader->output[i].gpr;
output.elem_size = 3;
output.swizzle_x = 0;
output.swizzle_y = 1;
output.swizzle_z = 2;
output.swizzle_w = 3;
output.barrier = 1;
output.type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
output.array_base = i - pos0;
output.inst = V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE;
switch (ctx.type == TGSI_PROCESSOR_VERTEX) {
case TGSI_PROCESSOR_VERTEX:
if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
output.array_base = 60;
output.type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
/* position doesn't count in array_base */
pos0 = 1;
}
break;
case TGSI_PROCESSOR_FRAGMENT:
if (shader->output[i].name == TGSI_SEMANTIC_COLOR) {
output.array_base = 0;
output.type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
} else {
R600_ERR("unsupported fragment output name %d\n", shader->output[i].name);
r = -EINVAL;
goto out_err;
}
break;
default:
R600_ERR("unsupported processor type %d\n", ctx.type);
r = -EINVAL;
goto out_err;
}
if (i == (shader->noutput - 1)) {
output.end_of_program = 1;
}
r = r600_bc_add_output(ctx.bc, &output);
if (r)
goto out_err;
}
tgsi_parse_free(&ctx.parse);
return 0;
out_err:
tgsi_parse_free(&ctx.parse);
return r;
}
static int tgsi_unsupported(struct r600_shader_ctx *ctx)
{
R600_ERR("%d tgsi opcode unsupported\n", ctx->inst_info->tgsi_opcode);
return -EINVAL;
}
static int tgsi_end(struct r600_shader_ctx *ctx)
{
return 0;
}
static int tgsi_src(struct r600_shader_ctx *ctx,
const struct tgsi_full_src_register *tgsi_src,
unsigned swizzle,
struct r600_bc_alu_src *r600_src)
{
r600_src->sel = tgsi_src->Register.Index;
if (tgsi_src->Register.File == TGSI_FILE_IMMEDIATE) {
r600_src->sel = 0;
}
r600_src->sel += ctx->file_offset[tgsi_src->Register.File];
switch (swizzle) {
case 0:
r600_src->chan = tgsi_src->Register.SwizzleX;
break;
case 1:
r600_src->chan = tgsi_src->Register.SwizzleY;
break;
case 2:
r600_src->chan = tgsi_src->Register.SwizzleZ;
break;
case 3:
r600_src->chan = tgsi_src->Register.SwizzleW;
break;
default:
return -EINVAL;
}
return 0;
}
static int tgsi_dst(struct r600_shader_ctx *ctx,
const struct tgsi_full_dst_register *tgsi_dst,
unsigned swizzle,
struct r600_bc_alu_dst *r600_dst)
{
r600_dst->sel = tgsi_dst->Register.Index;
r600_dst->sel += ctx->file_offset[tgsi_dst->Register.File];
r600_dst->chan = swizzle;
r600_dst->write = 1;
return 0;
}
static int tgsi_op2(struct r600_shader_ctx *ctx)
{
struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
struct r600_bc_alu alu;
int i, j, r;
for (i = 0; i < 4; i++) {
memset(&alu, 0, sizeof(struct r600_bc_alu));
if (!(inst->Dst[0].Register.WriteMask & (1 << i))) {
alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
} else {
alu.inst = ctx->inst_info->r600_opcode;
for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
r = tgsi_src(ctx, &inst->Src[j], i, &alu.src[j]);
if (r)
return r;
}
r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
if (r)
return r;
}
/* handle some special cases */
switch (ctx->inst_info->tgsi_opcode) {
case TGSI_OPCODE_SUB:
alu.src[1].neg = 1;
break;
case TGSI_OPCODE_DP2:
if (i > 1) {
alu.src[0].sel = alu.src[1].sel = 248;
alu.src[0].chan = alu.src[1].chan = 0;
}
break;
case TGSI_OPCODE_DP3:
if (i > 2) {
alu.src[0].sel = alu.src[1].sel = 248;
alu.src[0].chan = alu.src[1].chan = 0;
}
break;
default:
break;
}
if (i == 3) {
alu.last = 1;
}
alu.nliteral = 0;
r = r600_bc_add_alu(ctx->bc, &alu);
if (r)
return r;
}
return 0;
}
static int tgsi_slt(struct r600_shader_ctx *ctx)
{
struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
struct r600_bc_alu alu;
int i, r;
for (i = 0; i < 4; i++) {
memset(&alu, 0, sizeof(struct r600_bc_alu));
if (!(inst->Dst[0].Register.WriteMask & (1 << i))) {
alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
} else {
alu.inst = ctx->inst_info->r600_opcode;
r = tgsi_src(ctx, &inst->Src[0], i, &alu.src[1]);
if (r)
return r;
r = tgsi_src(ctx, &inst->Src[1], i, &alu.src[0]);
if (r)
return r;
r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
if (r)
return r;
}
if (i == 3) {
alu.last = 1;
}
r = r600_bc_add_alu(ctx->bc, &alu);
if (r)
return r;
}
return 0;
}
static int tgsi_op3(struct r600_shader_ctx *ctx)
{
struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
struct r600_bc_alu alu;
int i, j, r;
/* do it in 2 step as op3 doesn't support writemask */
for (i = 0; i < 4; i++) {
memset(&alu, 0, sizeof(struct r600_bc_alu));
alu.inst = ctx->inst_info->r600_opcode;
for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
r = tgsi_src(ctx, &inst->Src[j], i, &alu.src[j]);
if (r)
return r;
}
alu.dst.sel = ctx->temp_reg;
alu.dst.chan = i;
alu.is_op3 = 1;
if (i == 3) {
alu.last = 1;
}
r = r600_bc_add_alu(ctx->bc, &alu);
if (r)
return r;
}
for (i = 0; i < 4; i++) {
memset(&alu, 0, sizeof(struct r600_bc_alu));
if (!(inst->Dst[0].Register.WriteMask & (1 << i))) {
alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
} else {
alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
if (r)
return r;
alu.src[0].sel = ctx->temp_reg;
alu.src[0].chan = i;
}
if (i == 3) {
alu.last = 1;
}
r = r600_bc_add_alu(ctx->bc, &alu);
if (r)
return r;
}
return 0;
}
static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
{TGSI_OPCODE_ARL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_MOV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV, tgsi_op2},
{TGSI_OPCODE_LIT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_RCP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_RSQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_EXP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_LOG, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_MUL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL, tgsi_op2},
{TGSI_OPCODE_ADD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, tgsi_op2},
{TGSI_OPCODE_DP3, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, tgsi_op2},
{TGSI_OPCODE_DP4, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, tgsi_op2},
{TGSI_OPCODE_DST, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_MIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_MAX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX, tgsi_op2},
{TGSI_OPCODE_SLT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT, tgsi_slt},
{TGSI_OPCODE_SGE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_MAD, 1, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD, tgsi_op3},
{TGSI_OPCODE_SUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, tgsi_op2},
{TGSI_OPCODE_LRP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_CND, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{20, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_DP2A, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{22, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{23, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_FRC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_CLAMP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_FLR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ROUND, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_EX2, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_LG2, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_POW, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_XPD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{32, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ABS, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_RCC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_DPH, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_COS, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_DDX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_DDY, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_KILP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, /* predicated kill */
{TGSI_OPCODE_PK2H, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_PK2US, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_PK4B, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_PK4UB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_RFL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SEQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SFL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SGT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SLE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SNE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_STR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_TEX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_TXD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_TXP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UP2H, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UP2US, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UP4B, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UP4UB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_X2D, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ARA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ARR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_BRA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_CAL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_RET, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SSG, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, /* SGN */
{TGSI_OPCODE_CMP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SCS, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_TXB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_NRM, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_DIV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_DP2, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, tgsi_op2},
{TGSI_OPCODE_TXL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_BRK, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_IF, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{75, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{76, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ELSE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDIF, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{79, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{80, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_PUSHA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_POPA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_CEIL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_I2F, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_NOT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_TRUNC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SHL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{88, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_AND, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_OR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_MOD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_XOR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SAD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_TXF, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_TXQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_CONT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_EMIT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDPRIM, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_BGNLOOP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_BGNSUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDLOOP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDSUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{103, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{104, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{105, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{106, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_NOP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
/* gap */
{108, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{109, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{110, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{111, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_NRM4, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_CALLNZ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_IFC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_BREAKC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_KIL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, /* conditional kill */
{TGSI_OPCODE_END, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_end}, /* aka HALT */
/* gap */
{118, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_F2I, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_IDIV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_IMAX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_IMIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_INEG, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ISGE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ISHR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ISLT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_F2U, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_U2F, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UADD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UDIV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UMAD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UMAX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UMIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UMOD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_UMUL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_USEQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_USGE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_USHR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_USLT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_USNE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_SWITCH, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_CASE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_DEFAULT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDSWITCH, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_LAST, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
};

View File

@ -23,243 +23,23 @@
#ifndef R600_SHADER_H
#define R600_SHADER_H
#include "r600_compiler.h"
#include "radeon.h"
struct r600_shader_operand {
struct c_vector *vector;
unsigned sel;
unsigned chan;
unsigned neg;
unsigned abs;
};
struct r600_shader_vfetch {
struct list_head head;
unsigned cf_addr;
struct r600_shader_operand src[2];
struct r600_shader_operand dst[4];
};
struct r600_shader_inst {
unsigned is_op3;
unsigned opcode;
unsigned inst;
struct r600_shader_operand src[3];
struct r600_shader_operand dst;
unsigned last;
};
struct r600_shader_alu {
struct list_head head;
unsigned nalu;
unsigned nliteral;
unsigned nconstant;
struct r600_shader_inst alu[5];
u32 literal[4];
};
struct r600_shader_node {
struct list_head head;
unsigned cf_id; /**< cf index (in dw) in byte code */
unsigned cf_addr; /**< instructions index (in dw) in byte code */
unsigned nslot; /**< number of slot (2 dw) needed by this node */
unsigned nfetch;
struct c_node *node; /**< compiler node from which this node originate */
struct list_head vfetch; /**< list of vfetch instructions */
struct list_head alu; /**< list of alu instructions */
};
#include "r600_asm.h"
struct r600_shader_io {
unsigned name;
unsigned gpr;
int sid;
unsigned name;
unsigned gpr;
int sid;
};
struct r600_shader {
unsigned stack_size; /**< stack size needed by this shader */
unsigned ngpr; /**< number of GPR needed by this shader */
unsigned nconstant; /**< number of constants used by this shader */
unsigned nresource; /**< number of resources used by this shader */
unsigned noutput;
unsigned ninput;
unsigned nvector;
unsigned ncf; /**< total number of cf clauses */
unsigned nslot; /**< total number of slots (2 dw) */
unsigned flat_shade; /**< are we flat shading */
struct list_head nodes; /**< list of node */
struct r600_shader_io input[32];
struct r600_shader_io output[32];
/* TODO replace GPR by some better register allocator */
struct c_vector **gpr;
unsigned ndw; /**< bytes code size in dw */
u32 *bcode; /**< bytes code */
enum pipe_format resource_format[160]; /**< format of resource */
struct c_shader cshader;
boolean r6xx_compile;
unsigned processor_type;
struct r600_bc bc;
boolean flat_shade;
unsigned ninput;
unsigned noutput;
struct r600_shader_io input[32];
struct r600_shader_io output[32];
enum radeon_family family;
};
void r600_shader_cleanup(struct r600_shader *rshader);
int r600_shader_register(struct r600_shader *rshader);
int r600_shader_node(struct r600_shader *shader);
void r600_shader_node_place(struct r600_shader *rshader);
int r600_shader_find_gpr(struct r600_shader *rshader, struct c_vector *v, unsigned swizzle,
struct r600_shader_operand *operand);
int r600_shader_vfetch_bytecode(struct r600_shader *rshader,
struct r600_shader_node *rnode,
struct r600_shader_vfetch *vfetch,
unsigned *cid);
int r600_shader_update(struct r600_shader *rshader,
enum pipe_format *resource_format);
int r600_shader_legalize(struct r600_shader *rshader);
int r600_cshader_legalize(struct c_shader *shader);
int r700_shader_translate(struct r600_shader *rshader);
int c_shader_from_tgsi(struct c_shader *shader, unsigned type,
const struct tgsi_token *tokens);
int r600_shader_register(struct r600_shader *rshader);
int r600_shader_translate_rec(struct r600_shader *rshader, struct c_node *node);
int r700_shader_translate(struct r600_shader *rshader);
int r600_shader_insert_fetch(struct c_shader *shader);
int r6xx_shader_alu_translate(struct r600_shader *rshader,
struct r600_shader_node *rnode,
unsigned *cid);
enum r600_instruction {
INST_ADD = 0,
INST_MUL = 1,
INST_MUL_IEEE = 2,
INST_MAX = 3,
INST_MIN = 4,
INST_MAX_DX10 = 5,
INST_MIN_DX10 = 6,
INST_SETE = 7,
INST_SETGT = 8,
INST_SETGE = 9,
INST_SETNE = 10,
INST_SETE_DX10 = 11,
INST_SETGT_DX10 = 12,
INST_SETGE_DX10 = 13,
INST_SETNE_DX10 = 14,
INST_FRACT = 15,
INST_TRUNC = 16,
INST_CEIL = 17,
INST_RNDNE = 18,
INST_FLOOR = 19,
INST_MOVA = 20,
INST_MOVA_FLOOR = 21,
INST_MOVA_INT = 22,
INST_MOV = 23,
INST_NOP = 24,
INST_PRED_SETGT_UINT = 25,
INST_PRED_SETGE_UINT = 26,
INST_PRED_SETE = 27,
INST_PRED_SETGT = 28,
INST_PRED_SETGE = 29,
INST_PRED_SETNE = 30,
INST_PRED_SET_INV = 31,
INST_PRED_SET_POP = 32,
INST_PRED_SET_CLR = 33,
INST_PRED_SET_RESTORE = 34,
INST_PRED_SETE_PUSH = 35,
INST_PRED_SETGT_PUSH = 36,
INST_PRED_SETGE_PUSH = 37,
INST_PRED_SETNE_PUSH = 38,
INST_KILLE = 39,
INST_KILLGT = 40,
INST_KILLGE = 41,
INST_KILLNE = 42,
INST_AND_INT = 43,
INST_OR_INT = 44,
INST_XOR_INT = 45,
INST_NOT_INT = 46,
INST_ADD_INT = 47,
INST_SUB_INT = 48,
INST_MAX_INT = 49,
INST_MIN_INT = 50,
INST_MAX_UINT = 51,
INST_MIN_UINT = 52,
INST_SETE_INT = 53,
INST_SETGT_INT = 54,
INST_SETGE_INT = 55,
INST_SETNE_INT = 56,
INST_SETGT_UINT = 57,
INST_SETGE_UINT = 58,
INST_KILLGT_UINT = 59,
INST_KILLGE_UINT = 60,
INST_PRED_SETE_INT = 61,
INST_PRED_SETGT_INT = 62,
INST_PRED_SETGE_INT = 63,
INST_PRED_SETNE_INT = 64,
INST_KILLE_INT = 65,
INST_KILLGT_INT = 66,
INST_KILLGE_INT = 67,
INST_KILLNE_INT = 68,
INST_PRED_SETE_PUSH_INT = 69,
INST_PRED_SETGT_PUSH_INT = 70,
INST_PRED_SETGE_PUSH_INT = 71,
INST_PRED_SETNE_PUSH_INT = 72,
INST_PRED_SETLT_PUSH_INT = 73,
INST_PRED_SETLE_PUSH_INT = 74,
INST_DOT4 = 75,
INST_DOT4_IEEE = 76,
INST_CUBE = 77,
INST_MAX4 = 78,
INST_MOVA_GPR_INT = 79,
INST_EXP_IEEE = 80,
INST_LOG_CLAMPED = 81,
INST_LOG_IEEE = 82,
INST_RECIP_CLAMPED = 83,
INST_RECIP_FF = 84,
INST_RECIP_IEEE = 85,
INST_RECIPSQRT_CLAMPED = 86,
INST_RECIPSQRT_FF = 87,
INST_RECIPSQRT_IEEE = 88,
INST_SQRT_IEEE = 89,
INST_FLT_TO_INT = 90,
INST_INT_TO_FLT = 91,
INST_UINT_TO_FLT = 92,
INST_SIN = 93,
INST_COS = 94,
INST_ASHR_INT = 95,
INST_LSHR_INT = 96,
INST_LSHL_INT = 97,
INST_MULLO_INT = 98,
INST_MULHI_INT = 99,
INST_MULLO_UINT = 100,
INST_MULHI_UINT = 101,
INST_RECIP_INT = 102,
INST_RECIP_UINT = 103,
INST_FLT_TO_UINT = 104,
INST_MUL_LIT = 105,
INST_MUL_LIT_M2 = 106,
INST_MUL_LIT_M4 = 107,
INST_MUL_LIT_D2 = 108,
INST_MULADD = 109,
INST_MULADD_M2 = 110,
INST_MULADD_M4 = 111,
INST_MULADD_D2 = 112,
INST_MULADD_IEEE = 113,
INST_MULADD_IEEE_M2 = 114,
INST_MULADD_IEEE_M4 = 115,
INST_MULADD_IEEE_D2 = 116,
INST_CNDE = 117,
INST_CNDGT = 118,
INST_CNDGE = 119,
INST_CNDE_INT = 120,
INST_CNDGT_INT = 121,
INST_CNDGE_INT = 122,
INST_COUNT
};
struct r600_instruction_info {
enum r600_instruction instruction;
unsigned opcode;
unsigned is_trans;
unsigned is_op3;
};
#endif

View File

@ -87,9 +87,9 @@
#define G_SQ_CF_WORD1_BARRIER(x) (((x) >> 31) & 0x1)
#define C_SQ_CF_WORD1_BARRIER 0x7FFFFFFF
#define P_SQ_CF_ALU_WORD0
#define S_SQ_CF_ALU_WORD0_ALU_ADDR(x) (((x) & 0x3FFFFF) << 0)
#define G_SQ_CF_ALU_WORD0_ALU_ADDR(x) (((x) >> 0) & 0x3FFFFF)
#define C_SQ_CF_ALU_WORD0_ALU_ADDR 0xFFC00000
#define S_SQ_CF_ALU_WORD0_ADDR(x) (((x) & 0x3FFFFF) << 0)
#define G_SQ_CF_ALU_WORD0_ADDR(x) (((x) >> 0) & 0x3FFFFF)
#define C_SQ_CF_ALU_WORD0_ADDR 0xFFC00000
#define S_SQ_CF_ALU_WORD0_KCACHE_BANK0(x) (((x) & 0xF) << 22)
#define G_SQ_CF_ALU_WORD0_KCACHE_BANK0(x) (((x) >> 22) & 0xF)
#define C_SQ_CF_ALU_WORD0_KCACHE_BANK0 0xFC3FFFFF
@ -109,15 +109,15 @@
#define S_SQ_CF_ALU_WORD1_KCACHE_ADDR1(x) (((x) & 0xFF) << 10)
#define G_SQ_CF_ALU_WORD1_KCACHE_ADDR1(x) (((x) >> 10) & 0xFF)
#define C_SQ_CF_ALU_WORD1_KCACHE_ADDR1 0xFFFC03FF
#define S_SQ_CF_ALU_WORD1_ALU_COUNT(x) (((x) & 0x7F) << 18)
#define G_SQ_CF_ALU_WORD1_ALU_COUNT(x) (((x) >> 18) & 0x7F)
#define C_SQ_CF_ALU_WORD1_ALU_COUNT 0xFE03FFFF
#define S_SQ_CF_ALU_WORD1_COUNT(x) (((x) & 0x7F) << 18)
#define G_SQ_CF_ALU_WORD1_COUNT(x) (((x) >> 18) & 0x7F)
#define C_SQ_CF_ALU_WORD1_COUNT 0xFE03FFFF
#define S_SQ_CF_ALU_WORD1_USES_WATERFALL(x) (((x) & 0x1) << 25)
#define G_SQ_CF_ALU_WORD1_USES_WATERFALL(x) (((x) >> 25) & 0x1)
#define C_SQ_CF_ALU_WORD1_USES_WATERFALL 0xFDFFFFFF
#define S_SQ_CF_ALU_WORD1_CF_ALU_INST(x) (((x) & 0xF) << 26)
#define G_SQ_CF_ALU_WORD1_CF_ALU_INST(x) (((x) >> 26) & 0xF)
#define C_SQ_CF_ALU_WORD1_CF_ALU_INST 0xC3FFFFFF
#define S_SQ_CF_ALU_WORD1_CF_INST(x) (((x) & 0xF) << 26)
#define G_SQ_CF_ALU_WORD1_CF_INST(x) (((x) >> 26) & 0xF)
#define C_SQ_CF_ALU_WORD1_CF_INST 0xC3FFFFFF
#define V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU 0x00000008
#define V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE 0x00000009
#define V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER 0x0000000A

View File

@ -151,7 +151,7 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
static void *r600_create_fs_state(struct pipe_context *ctx,
const struct pipe_shader_state *shader)
{
return r600_pipe_shader_create(ctx, C_PROGRAM_TYPE_FS, shader->tokens);
return r600_pipe_shader_create(ctx, shader->tokens);
}
static void r600_bind_fs_state(struct pipe_context *ctx, void *state)
@ -164,7 +164,7 @@ static void r600_bind_fs_state(struct pipe_context *ctx, void *state)
static void *r600_create_vs_state(struct pipe_context *ctx,
const struct pipe_shader_state *shader)
{
return r600_pipe_shader_create(ctx, C_PROGRAM_TYPE_VS, shader->tokens);
return r600_pipe_shader_create(ctx, shader->tokens);
}
static void r600_bind_vs_state(struct pipe_context *ctx, void *state)

View File

@ -0,0 +1,70 @@
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "r600_asm.h"
#include "r600_context.h"
#include "util/u_memory.h"
#include "r700_sq.h"
#include <stdio.h>
#include <errno.h>
int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id)
{
unsigned i;
/* don't replace gpr by pv or ps for destination register */
if (alu->is_op3) {
bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_LAST(alu->last);
bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
S_SQ_ALU_WORD1_OP3_ALU_INST(alu->inst) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
} else {
bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
S_SQ_ALU_WORD0_LAST(alu->last);
bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) |
S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) |
S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
}
if (alu->last) {
for (i = 0; i < alu->nliteral; i++) {
bc->bytecode[id++] = alu->value[i];
}
}
return 0;
}