aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2006-11-25 09:58:35 +0000
committerBen Skeggs <[email protected]>2006-11-25 09:58:35 +0000
commit9c9e6abbf82fbf591575a9c352f86721bc72aa90 (patch)
tree4b0f41371fbe0d5d10ae869bec13f953b9a2b82e /src/mesa/drivers/dri/nouveau/nv30_fragprog.c
parent902b26a0d670ca7d2f37103d1c4de242694ff337 (diff)
Incomplete shader stuff, should mostly work for NV40. Other cards, not so
much..
Diffstat (limited to 'src/mesa/drivers/dri/nouveau/nv30_fragprog.c')
-rw-r--r--src/mesa/drivers/dri/nouveau/nv30_fragprog.c707
1 files changed, 707 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nv30_fragprog.c b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
new file mode 100644
index 00000000000..2e35d08c07c
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
@@ -0,0 +1,707 @@
+#include <stdint.h>
+
+#include "glheader.h"
+#include "macros.h"
+
+#include "nouveau_context.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+#include "nouveau_drm.h"
+#include "nouveau_shader.h"
+#include "nouveau_object.h"
+#include "nouveau_msg.h"
+#include "nv30_shader.h"
+
+unsigned int NVFP_TX_AOP_COUNT = 64;
+struct _op_xlat NVFP_TX_AOP[64];
+
+/*******************************************************************************
+ * Support routines
+ */
+
+/*XXX: bad bad bad bad */
+static uint64_t fragprog_ofs;
+static uint32_t *fragprog_buf = NULL;
+
+static void
+NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ drm_nouveau_mem_alloc_t mem;
+
+ if (!fragprog_buf) {
+ mem.flags = NOUVEAU_MEM_FB|NOUVEAU_MEM_MAPPED;
+ mem.size = nvs->program_size * sizeof(uint32_t);
+ mem.alignment = 0;
+ mem.region_offset = &fragprog_ofs;
+ if (drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC, &mem,
+ sizeof(mem))) {
+ fprintf(stderr, "MEM_ALLOC fail\n");
+ return;
+ }
+
+ if (drmMap(nmesa->driFd, fragprog_ofs, mem.size, &fragprog_buf)) {
+ fprintf(stderr, "MEM_MAP fail\n");
+ return;
+ }
+ }
+
+ /*XXX: should do a DMA.. and not copy over a possibly in-use program.. */
+ /* not using state cache here, updated programs at the same address
+ * seem to not take effect unless ACTIVE_PROGRAM is called again. hw
+ * caches the program somewhere? so, maybe not so bad to just clobber the
+ * old program in vram..
+ */
+ memcpy(fragprog_buf, nvs->program, nvs->program_size * sizeof(uint32_t));
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
+ OUT_RING(((uint32_t)fragprog_ofs-0xE0000000)|1);
+}
+
+static void
+NV30FPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
+{
+ uint32_t *current = nvs->program + nvs->params[id].hw_index;
+ uint32_t *new = nvs->params[id].source_val ?
+ nvs->params[id].source_val : nvs->params[id].val;
+
+ COPY_4V(current, new);
+ nvs->on_hardware = 0;
+}
+
+/*******************************************************************************
+ * Assembly helpers
+ */
+static struct _op_xlat *
+NV30FPGetOPTXFromSOP(nvsOpcode op, int *id)
+{
+ int i;
+
+ for (i=0; i<NVFP_TX_AOP_COUNT; i++) {
+ if (NVFP_TX_AOP[i].SOP == op) {
+ if (id) *id = 0;
+ return &NVFP_TX_AOP[i];
+ }
+ }
+
+ return NULL;
+}
+
+static int
+NV30FPSupportsOpcode(nvsFunc *shader, nvsOpcode op)
+{
+ if (shader->GetOPTXFromSOP(op, NULL))
+ return 1;
+ return 0;
+}
+
+static void
+NV30FPSetOpcode(nvsFunc *shader, unsigned int opcode, int slot)
+{
+ shader->inst[0] |= (opcode << NV30_FP_OP_OPCODE_SHIFT);
+}
+
+static void
+NV30FPSetCCUpdate(nvsFunc *shader)
+{
+ shader->inst[0] |= NV30_FP_OP_COND_WRITE_ENABLE;
+}
+
+static void
+NV30FPSetCondition(nvsFunc *shader, int on, nvsCond cond, int reg,
+ nvsSwzComp *swz)
+{
+ nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
+ unsigned int hwcond;
+
+ /* cond masking is always enabled */
+ if (!on) {
+ cond = NVS_COND_TR;
+ reg = 0;
+ swz = default_swz;
+ }
+
+ switch (cond) {
+ case NVS_COND_TR: hwcond = NV30_FP_OP_COND_TR; break;
+ case NVS_COND_FL: hwcond = NV30_FP_OP_COND_FL; break;
+ case NVS_COND_LT: hwcond = NV30_FP_OP_COND_LT; break;
+ case NVS_COND_GT: hwcond = NV30_FP_OP_COND_GT; break;
+ case NVS_COND_LE: hwcond = NV30_FP_OP_COND_LE; break;
+ case NVS_COND_GE: hwcond = NV30_FP_OP_COND_GE; break;
+ case NVS_COND_EQ: hwcond = NV30_FP_OP_COND_EQ; break;
+ case NVS_COND_NE: hwcond = NV30_FP_OP_COND_NE; break;
+ default:
+ WARN_ONCE("unknown fp condmask=%d\n", cond);
+ hwcond = NV30_FP_OP_COND_TR;
+ break;
+ }
+
+ shader->inst[1] |= (hwcond << NV30_FP_OP_COND_SHIFT);
+ shader->inst[1] |= (swz[NVS_SWZ_X] << NV30_FP_OP_COND_SWZ_X_SHIFT);
+ shader->inst[1] |= (swz[NVS_SWZ_Y] << NV30_FP_OP_COND_SWZ_Y_SHIFT);
+ shader->inst[1] |= (swz[NVS_SWZ_Z] << NV30_FP_OP_COND_SWZ_Z_SHIFT);
+ shader->inst[1] |= (swz[NVS_SWZ_W] << NV30_FP_OP_COND_SWZ_W_SHIFT);
+}
+
+static void
+NV30FPSetResult(nvsFunc *shader, nvsRegister *reg, unsigned int mask, int slot)
+{
+ unsigned int hwreg, hwmask = 0;
+
+ if (mask & SMASK_X) shader->inst[0] |= NV30_FP_OP_OUT_X;
+ if (mask & SMASK_Y) shader->inst[0] |= NV30_FP_OP_OUT_Y;
+ if (mask & SMASK_Z) shader->inst[0] |= NV30_FP_OP_OUT_Z;
+ if (mask & SMASK_W) shader->inst[0] |= NV30_FP_OP_OUT_W;
+
+ if (reg->file == NVS_FILE_RESULT) {
+ hwreg = 0; /* FIXME: this is only fragment.color */
+ /* This is *not* correct, I have no idea what it is either */
+ shader->inst[0] |= NV30_FP_OP_UNK0_7;
+ } else
+ hwreg = reg->index;
+ shader->inst[0] |= (hwreg << NV30_FP_OP_OUT_REG_SHIFT);
+}
+
+static void
+NV30FPSetSource(nvsFunc *shader, nvsRegister *reg, int pos)
+{
+ unsigned int hwsrc = 0;
+
+ switch (reg->file) {
+ case NVS_FILE_TEMP:
+ hwsrc |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT);
+ hwsrc |= (reg->index << NV30_FP_REG_SRC_SHIFT);
+ break;
+ case NVS_FILE_ATTRIB:
+ {
+ unsigned int hwin;
+
+ switch (reg->index) {
+ case NVS_FR_POSITION : hwin = NV30_FP_OP_INPUT_SRC_POSITION; break;
+ case NVS_FR_COL0 : hwin = NV30_FP_OP_INPUT_SRC_COL0; break;
+ case NVS_FR_COL1 : hwin = NV30_FP_OP_INPUT_SRC_COL1; break;
+ case NVS_FR_FOGCOORD : hwin = NV30_FP_OP_INPUT_SRC_FOGC; break;
+ case NVS_FR_TEXCOORD0: hwin = NV30_FP_OP_INPUT_SRC_TC(0); break;
+ case NVS_FR_TEXCOORD1: hwin = NV30_FP_OP_INPUT_SRC_TC(1); break;
+ case NVS_FR_TEXCOORD2: hwin = NV30_FP_OP_INPUT_SRC_TC(2); break;
+ case NVS_FR_TEXCOORD3: hwin = NV30_FP_OP_INPUT_SRC_TC(3); break;
+ case NVS_FR_TEXCOORD4: hwin = NV30_FP_OP_INPUT_SRC_TC(4); break;
+ case NVS_FR_TEXCOORD5: hwin = NV30_FP_OP_INPUT_SRC_TC(5); break;
+ case NVS_FR_TEXCOORD6: hwin = NV30_FP_OP_INPUT_SRC_TC(6); break;
+ case NVS_FR_TEXCOORD7: hwin = NV30_FP_OP_INPUT_SRC_TC(7); break;
+ default:
+ WARN_ONCE("unknown fp input %d\n", reg->index);
+ hwin = NV30_FP_OP_INPUT_SRC_COL0;
+ break;
+ }
+ shader->inst[0] |= (hwin << NV30_FP_OP_INPUT_SRC_SHIFT);
+ hwsrc |= (hwin << NV30_FP_REG_SRC_SHIFT);
+ }
+ hwsrc |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT);
+ break;
+ case NVS_FILE_CONST:
+ /* consts are inlined after the inst */
+ hwsrc |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (reg->negate)
+ hwsrc |= NV30_FP_REG_NEGATE;
+ if (reg->abs)
+ shader->inst[1] |= (1 << (29+pos));
+ hwsrc |= (reg->swizzle[NVS_SWZ_X] << NV30_FP_REG_SWZ_X_SHIFT);
+ hwsrc |= (reg->swizzle[NVS_SWZ_Y] << NV30_FP_REG_SWZ_Y_SHIFT);
+ hwsrc |= (reg->swizzle[NVS_SWZ_Z] << NV30_FP_REG_SWZ_Z_SHIFT);
+ hwsrc |= (reg->swizzle[NVS_SWZ_W] << NV30_FP_REG_SWZ_W_SHIFT);
+
+ shader->inst[pos+1] |= hwsrc;
+}
+
+static void
+NV30FPSetUnusedSource(nvsFunc *shader, int pos)
+{
+ shader->inst[pos+1] |= (
+ (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT) |
+ (NVS_SWZ_X << NV30_FP_REG_SWZ_X_SHIFT) |
+ (NVS_SWZ_Y << NV30_FP_REG_SWZ_Y_SHIFT) |
+ (NVS_SWZ_Z << NV30_FP_REG_SWZ_Z_SHIFT) |
+ (NVS_SWZ_W << NV30_FP_REG_SWZ_W_SHIFT)
+ );
+}
+
+static void
+NV30FPSetTexImageUnit(nvsFunc *shader, int unit)
+{
+ shader->inst[0] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT);
+}
+
+static void
+NV30FPSetSaturate(nvsFunc *shader)
+{
+ shader->inst[0] |= NV30_FP_OP_OUT_SAT;
+}
+
+static void
+NV30FPSetLastInst(nvsFunc *shader)
+{
+ shader->inst[0] |= 1;
+
+}
+
+/*******************************************************************************
+ * Disassembly helpers
+ */
+static struct _op_xlat *
+NV30FPGetOPTXRec(nvsFunc * shader, int merged)
+{
+ int op;
+
+ op = shader->GetOpcodeHW(shader, 0);
+ if (op > NVFP_TX_AOP_COUNT)
+ return NULL;
+ if (NVFP_TX_AOP[op].SOP == NVS_OP_UNKNOWN)
+ return NULL;
+ return &NVFP_TX_AOP[op];
+}
+
+static int
+NV30FPHasMergedInst(nvsFunc * shader)
+{
+ return 0;
+}
+
+static int
+NV30FPIsLastInst(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_PROGRAM_END) ? 1 : 0);
+}
+
+static int
+NV30FPGetOffsetNext(nvsFunc * shader)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ if (shader->GetSourceFile(shader, 0, i) == NVS_FILE_CONST)
+ return 8;
+ return 4;
+}
+
+static nvsOpcode
+NV30FPGetOpcode(nvsFunc * shader, int merged)
+{
+ struct _op_xlat *opr;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr)
+ return NVS_OP_UNKNOWN;
+
+ return opr->SOP;
+}
+
+static unsigned int
+NV30FPGetOpcodeHW(nvsFunc * shader, int slot)
+{
+ int op;
+
+ op = (shader->inst[0] & NV30_FP_OP_OPCODE_MASK) >> NV30_FP_OP_OPCODE_SHIFT;
+
+ return op;
+}
+
+static nvsRegFile
+NV30FPGetDestFile(nvsFunc * shader, int merged)
+{
+ /* Result regs overlap temporary regs */
+ return NVS_FILE_TEMP;
+}
+
+static unsigned int
+NV30FPGetDestID(nvsFunc * shader, int merged)
+{
+ int id;
+
+ switch (shader->GetDestFile(shader, merged)) {
+ case NVS_FILE_TEMP:
+ id = ((shader->inst[0] & NV30_FP_OP_OUT_REG_MASK)
+ >> NV30_FP_OP_OUT_REG_SHIFT);
+ return id;
+ default:
+ return -1;
+ }
+}
+
+static unsigned int
+NV30FPGetDestMask(nvsFunc * shader, int merged)
+{
+ unsigned int mask = 0;
+
+ if (shader->inst[0] & NV30_FP_OP_OUT_X) mask |= SMASK_X;
+ if (shader->inst[0] & NV30_FP_OP_OUT_Y) mask |= SMASK_Y;
+ if (shader->inst[0] & NV30_FP_OP_OUT_Z) mask |= SMASK_Z;
+ if (shader->inst[0] & NV30_FP_OP_OUT_W) mask |= SMASK_W;
+
+ return mask;
+}
+
+static unsigned int
+NV30FPGetSourceHW(nvsFunc * shader, int merged, int pos)
+{
+ struct _op_xlat *opr;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return -1;
+
+ return shader->inst[opr->srcpos[pos] + 1];
+}
+
+static nvsRegFile
+NV30FPGetSourceFile(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+ struct _op_xlat *opr;
+ int file;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return NVS_FILE_UNKNOWN;
+
+ switch (opr->srcpos[pos]) {
+ case SPOS_ADDRESS: return NVS_FILE_ADDRESS;
+ default:
+ src = shader->GetSourceHW(shader, merged, pos);
+ file = (src & NV30_FP_REG_TYPE_MASK) >> NV30_FP_REG_TYPE_SHIFT;
+
+ switch (file) {
+ case NV30_FP_REG_TYPE_TEMP : return NVS_FILE_TEMP;
+ case NV30_FP_REG_TYPE_INPUT: return NVS_FILE_ATTRIB;
+ case NV30_FP_REG_TYPE_CONST: return NVS_FILE_CONST;
+ default:
+ return NVS_FILE_UNKNOWN;
+ }
+ }
+}
+
+static int
+NV30FPGetSourceID(nvsFunc * shader, int merged, int pos)
+{
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_ATTRIB:
+ switch ((shader->inst[0] & NV30_FP_OP_INPUT_SRC_MASK)
+ >> NV30_FP_OP_INPUT_SRC_SHIFT) {
+ case NV30_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION;
+ case NV30_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0;
+ case NV30_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1;
+ case NV30_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD;
+ case NV30_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0;
+ case NV30_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1;
+ case NV30_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2;
+ case NV30_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3;
+ case NV30_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4;
+ case NV30_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5;
+ case NV30_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6;
+ case NV30_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7;
+ default:
+ return -1;
+ }
+ break;
+ case NVS_FILE_TEMP:
+ {
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ return ((src & NV30_FP_REG_SRC_MASK) >> NV30_FP_REG_SRC_SHIFT);
+ }
+ case NVS_FILE_CONST: /* inlined into fragprog */
+ default:
+ return -1;
+ }
+}
+
+static int
+NV30FPGetTexImageUnit(nvsFunc *shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_TEX_UNIT_MASK)
+ >> NV30_FP_OP_TEX_UNIT_SHIFT);
+}
+
+static int
+NV30FPGetSourceNegate(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+
+ if (src == -1)
+ return -1;
+ return ((src & NV30_FP_REG_NEGATE) ? 1 : 0);
+}
+
+static int
+NV30FPGetSourceAbs(nvsFunc * shader, int merged, int pos)
+{
+ struct _op_xlat *opr;
+ static unsigned int abspos[3] = {
+ NV30_FP_OP_OUT_ABS,
+ (1 << 30), /* guess */
+ (1 << 31) /* guess */
+ };
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return -1;
+
+ return ((shader->inst[1] & abspos[opr->srcpos[pos]]) ? 1 : 0);
+}
+
+nvsSwzComp NV30FP_TX_SWIZZLE[4] = {NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
+
+static void
+NV30FPTXSwizzle(int hwswz, nvsSwzComp *swz)
+{
+ swz[NVS_SWZ_W] = NV30FP_TX_SWIZZLE[(hwswz & 0xC0) >> 6];
+ swz[NVS_SWZ_Z] = NV30FP_TX_SWIZZLE[(hwswz & 0x30) >> 4];
+ swz[NVS_SWZ_Y] = NV30FP_TX_SWIZZLE[(hwswz & 0x0C) >> 2];
+ swz[NVS_SWZ_X] = NV30FP_TX_SWIZZLE[(hwswz & 0x03) >> 0];
+}
+
+static void
+NV30FPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz)
+{
+ unsigned int src;
+ int swzbits;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ swzbits = (src & NV30_FP_REG_SWZ_ALL_MASK) >> NV30_FP_REG_SWZ_ALL_SHIFT;
+ NV30FPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV30FPGetSourceIndexed(nvsFunc * shader, int merged, int pos)
+{
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_ATTRIB:
+ return ((shader->inst[3] & NV30_FP_OP_INDEX_INPUT) ? 1 : 0);
+ default:
+ return 0;
+ }
+}
+
+static void
+NV30FPGetSourceConstVal(nvsFunc * shader, int merged, int pos, float *val)
+{
+ val[0] = *(float *) &(shader->inst[4]);
+ val[1] = *(float *) &(shader->inst[5]);
+ val[2] = *(float *) &(shader->inst[6]);
+ val[3] = *(float *) &(shader->inst[7]);
+}
+
+static int
+NV30FPGetSourceScale(nvsFunc * shader, int merged, int pos)
+{
+/*FIXME: is this per-source, only for a specific source, or all sources??*/
+ return (1 << ((shader->inst[2] & NV30_FP_OP_SRC_SCALE_MASK)
+ >> NV30_FP_OP_SRC_SCALE_SHIFT));
+}
+
+static int
+NV30FPGetAddressRegID(nvsFunc * shader)
+{
+ return 0;
+}
+
+static nvsSwzComp
+NV30FPGetAddressRegSwizzle(nvsFunc * shader)
+{
+ return NVS_SWZ_X;
+}
+
+static int
+NV30FPSupportsConditional(nvsFunc * shader)
+{
+ /*FIXME: Is this true of all ops? */
+ return 1;
+}
+
+static int
+NV30FPGetConditionUpdate(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_COND_WRITE_ENABLE) ? 1 : 0);
+}
+
+static int
+NV30FPGetConditionTest(nvsFunc * shader)
+{
+ /*FIXME: always? */
+ return 1;
+}
+
+static nvsCond
+NV30FPGetCondition(nvsFunc * shader)
+{
+ int cond;
+
+ cond = ((shader->inst[1] & NV30_FP_OP_COND_MASK)
+ >> NV30_FP_OP_COND_SHIFT);
+
+ switch (cond) {
+ case NV30_FP_OP_COND_FL: return NVS_COND_FL;
+ case NV30_FP_OP_COND_LT: return NVS_COND_LT;
+ case NV30_FP_OP_COND_EQ: return NVS_COND_EQ;
+ case NV30_FP_OP_COND_LE: return NVS_COND_LE;
+ case NV30_FP_OP_COND_GT: return NVS_COND_GT;
+ case NV30_FP_OP_COND_NE: return NVS_COND_NE;
+ case NV30_FP_OP_COND_GE: return NVS_COND_GE;
+ case NV30_FP_OP_COND_TR: return NVS_COND_TR;
+ default:
+ return NVS_COND_UNKNOWN;
+ }
+}
+
+static void
+NV30FPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
+{
+ int swzbits;
+
+ swzbits = (shader->inst[1] & NV30_FP_OP_COND_SWZ_ALL_MASK)
+ >> NV30_FP_OP_COND_SWZ_ALL_SHIFT;
+ NV30FPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV30FPGetCondRegID(nvsFunc * shader)
+{
+ return 0;
+}
+
+static nvsPrecision
+NV30FPGetPrecision(nvsFunc * shader)
+{
+ int p;
+
+ p = (shader->inst[0] & NV30_FP_OP_PRECISION_MASK)
+ >> NV30_FP_OP_PRECISION_SHIFT;
+
+ switch (p) {
+ case NV30_FP_PRECISION_FP32: return NVS_PREC_FLOAT32;
+ case NV30_FP_PRECISION_FP16: return NVS_PREC_FLOAT16;
+ case NV30_FP_PRECISION_FX12: return NVS_PREC_FIXED12;
+ default:
+ return NVS_PREC_UNKNOWN;
+ }
+}
+
+static int
+NV30FPGetSaturate(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_OUT_SAT) ? 1 : 0);
+}
+
+/*******************************************************************************
+ * Init
+ */
+void
+NV30FPInitShaderFuncs(nvsFunc * shader)
+{
+ /* These are probably bogus, I made them up... */
+ shader->MaxInst = 1024;
+ shader->MaxAttrib = 16;
+ shader->MaxTemp = 32;
+ shader->MaxAddress = 1;
+ shader->MaxConst = 256;
+ shader->caps = SCAP_SRC_ABS;
+
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MOV, NVS_OP_MOV, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MUL, NVS_OP_MUL, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_ADD, NVS_OP_ADD, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAD, NVS_OP_MAD, 0, 1, 2);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP3, NVS_OP_DP3, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP4, NVS_OP_DP4, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DST, NVS_OP_DST, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MIN, NVS_OP_MIN, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAX, NVS_OP_MAX, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLT, NVS_OP_SLT, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGE, NVS_OP_SGE, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FRC, NVS_OP_FRC, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FLR, NVS_OP_FLR, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TEX, NVS_OP_TEX, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXD, NVS_OP_TXD, 0, 1, 2);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXP, NVS_OP_TXP, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXB, NVS_OP_TXB, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SEQ, NVS_OP_SEQ, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGT, NVS_OP_SGT, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLE, NVS_OP_SLE, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SNE, NVS_OP_SNE, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RCP, NVS_OP_RCP, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LG2, NVS_OP_LG2, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_EX2, NVS_OP_EX2, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_COS, NVS_OP_COS, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SIN, NVS_OP_SIN, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDX, NVS_OP_DDX, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDY, NVS_OP_DDY, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_KIL, NVS_OP_KIL, -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4B, NVS_OP_PK4B, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4B, NVS_OP_UP4B, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2H, NVS_OP_PK2H, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2H, NVS_OP_UP2H, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4UB, NVS_OP_PK4UB, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4UB, NVS_OP_UP4UB, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2US, NVS_OP_PK2US, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2US, NVS_OP_UP2US, 0, -1, -1);
+ /*FIXME: Haven't confirmed the source positions for the below opcodes */
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LIT, NVS_OP_LIT, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LRP, NVS_OP_LRP, 0, 1, 2);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_POW, NVS_OP_POW, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RSQ, NVS_OP_RSQ, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RFL, NVS_OP_RFL, 0, 1, -1);
+
+ shader->GetOPTXRec = NV30FPGetOPTXRec;
+ shader->GetOPTXFromSOP = NV30FPGetOPTXFromSOP;
+
+ shader->UploadToHW = NV30FPUploadToHW;
+ shader->UpdateConst = NV30FPUpdateConst;
+
+ shader->SupportsOpcode = NV30FPSupportsOpcode;
+ shader->SetOpcode = NV30FPSetOpcode;
+ shader->SetCCUpdate = NV30FPSetCCUpdate;
+ shader->SetCondition = NV30FPSetCondition;
+ shader->SetResult = NV30FPSetResult;
+ shader->SetSource = NV30FPSetSource;
+ shader->SetUnusedSource = NV30FPSetUnusedSource;
+ shader->SetTexImageUnit = NV30FPSetTexImageUnit;
+ shader->SetSaturate = NV30FPSetSaturate;
+ shader->SetLastInst = NV30FPSetLastInst;
+
+ shader->HasMergedInst = NV30FPHasMergedInst;
+ shader->IsLastInst = NV30FPIsLastInst;
+ shader->GetOffsetNext = NV30FPGetOffsetNext;
+ shader->GetOpcode = NV30FPGetOpcode;
+ shader->GetOpcodeHW = NV30FPGetOpcodeHW;
+ shader->GetDestFile = NV30FPGetDestFile;
+ shader->GetDestID = NV30FPGetDestID;
+ shader->GetDestMask = NV30FPGetDestMask;
+ shader->GetSourceHW = NV30FPGetSourceHW;
+ shader->GetSourceFile = NV30FPGetSourceFile;
+ shader->GetSourceID = NV30FPGetSourceID;
+ shader->GetTexImageUnit = NV30FPGetTexImageUnit;
+ shader->GetSourceNegate = NV30FPGetSourceNegate;
+ shader->GetSourceAbs = NV30FPGetSourceAbs;
+ shader->GetSourceSwizzle = NV30FPGetSourceSwizzle;
+ shader->GetSourceIndexed = NV30FPGetSourceIndexed;
+ shader->GetSourceConstVal = NV30FPGetSourceConstVal;
+ shader->GetSourceScale = NV30FPGetSourceScale;
+ shader->GetRelAddressRegID = NV30FPGetAddressRegID;
+ shader->GetRelAddressSwizzle = NV30FPGetAddressRegSwizzle;
+ shader->GetPrecision = NV30FPGetPrecision;
+ shader->GetSaturate = NV30FPGetSaturate;
+ shader->SupportsConditional = NV30FPSupportsConditional;
+ shader->GetConditionUpdate = NV30FPGetConditionUpdate;
+ shader->GetConditionTest = NV30FPGetConditionTest;
+ shader->GetCondition = NV30FPGetCondition;
+ shader->GetCondRegSwizzle = NV30FPGetCondRegSwizzle;
+ shader->GetCondRegID = NV30FPGetCondRegID;
+}