1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_context.h"
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_defines.h"
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_state.h"
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_linkage.h"
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_debug.h"
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_shader_tokens.h"
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_parse.h"
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_dump.h"
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_util.h"
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_ureg.h"
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "draw/draw_context.h"
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nv30-40_3d.xml.h"
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nv30_context.h"
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nv30_resource.h"
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* TODO (at least...):
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *  1. Indexed consts  + ARL
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *  3. NV_vp11, NV_vp2, NV_vp3 features
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *       - extra arith opcodes
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *       - branching
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *       - texture sampling
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *       - indexed attribs
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *       - indexed results
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *  4. bugs
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nv30_vertprog.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nv40_vertprog.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct nvfx_loop_entry {
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned brk_target;
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned cont_target;
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct nvfx_vpc {
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_context* nv30;
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pipe_shader_state pipe;
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_vertprog *vp;
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct tgsi_shader_info* info;
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_vertprog_exec *vpi;
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned r_temps;
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned r_temps_discard;
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg r_result[PIPE_MAX_SHADER_OUTPUTS];
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg *r_address;
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg *r_temp;
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg *r_const;
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg r_0_1;
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg *imm;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned nr_imm;
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int hpos_idx;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int cvtx_idx;
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct util_dynarray label_relocs;
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct util_dynarray loop_stack;
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct nvfx_reg
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtemp(struct nvfx_vpc *vpc)
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int idx = ffs(~vpc->r_temps) - 1;
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (idx < 0) {
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      NOUVEAU_ERR("out of temps!!\n");
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(0);
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return nvfx_reg(NVFXSR_TEMP, 0);
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->r_temps |= (1 << idx);
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->r_temps_discard |= (1 << idx);
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return nvfx_reg(NVFXSR_TEMP, idx);
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic inline void
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgrelease_temps(struct nvfx_vpc *vpc)
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->r_temps &= ~vpc->r_temps_discard;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->r_temps_discard = 0;
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct nvfx_reg
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconstant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w)
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_vertprog *vp = vpc->vp;
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_vertprog_data *vpd;
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int idx;
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (pipe >= 0) {
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (idx = 0; idx < vp->nr_consts; idx++) {
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (vp->consts[idx].index == pipe)
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return nvfx_reg(NVFXSR_CONST, idx);
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   idx = vp->nr_consts++;
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts);
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpd = &vp->consts[idx];
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpd->index = pipe;
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpd->value[0] = x;
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpd->value[1] = y;
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpd->value[2] = z;
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpd->value[3] = w;
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return nvfx_reg(NVFXSR_CONST, idx);
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define arith(s,t,o,d,m,s0,s1,s2) \
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   nvfx_insn((s), (NVFX_VP_INST_SLOT_##t << 7) | NVFX_VP_INST_##t##_OP_##o, -1, (d), (m), (s0), (s1), (s2))
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgemit_src(struct nv30_context *nv30, struct nvfx_vpc *vpc, uint32_t *hw,
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         int pos, struct nvfx_src src)
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_vertprog *vp = vpc->vp;
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   uint32_t sr = 0;
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_relocation reloc;
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (src.reg.type) {
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case NVFXSR_TEMP:
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sr |= (NVFX_VP(SRC_REG_TYPE_TEMP) << NVFX_VP(SRC_REG_TYPE_SHIFT));
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sr |= (src.reg.index << NVFX_VP(SRC_TEMP_SRC_SHIFT));
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case NVFXSR_INPUT:
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) <<
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             NVFX_VP(SRC_REG_TYPE_SHIFT));
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vp->ir |= (1 << src.reg.index);
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[1] |= (src.reg.index << NVFX_VP(INST_INPUT_SRC_SHIFT));
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case NVFXSR_CONST:
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sr |= (NVFX_VP(SRC_REG_TYPE_CONST) <<
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             NVFX_VP(SRC_REG_TYPE_SHIFT));
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (src.reg.index < 256 && src.reg.index >= -256) {
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         reloc.location = vp->nr_insns - 1;
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         reloc.target = src.reg.index;
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         util_dynarray_append(&vp->const_relocs, struct nvfx_relocation, reloc);
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[1] |= (src.reg.index << NVFX_VP(INST_CONST_SRC_SHIFT)) &
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               NVFX_VP(INST_CONST_SRC_MASK);
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case NVFXSR_NONE:
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) <<
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             NVFX_VP(SRC_REG_TYPE_SHIFT));
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(0);
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (src.negate)
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sr |= NVFX_VP(SRC_NEGATE);
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (src.abs)
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[0] |= (1 << (21 + pos));
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sr |= ((src.swz[0] << NVFX_VP(SRC_SWZ_X_SHIFT)) |
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          (src.swz[1] << NVFX_VP(SRC_SWZ_Y_SHIFT)) |
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          (src.swz[2] << NVFX_VP(SRC_SWZ_Z_SHIFT)) |
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          (src.swz[3] << NVFX_VP(SRC_SWZ_W_SHIFT)));
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(src.indirect) {
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(src.reg.type == NVFXSR_CONST)
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= NVFX_VP(INST_INDEX_CONST);
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if(src.reg.type == NVFXSR_INPUT)
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= NVFX_VP(INST_INDEX_INPUT);
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(0);
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(src.indirect_reg)
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= NVFX_VP(INST_ADDR_REG_SELECT_1);
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[0] |= src.indirect_swz << NVFX_VP(INST_ADDR_SWZ_SHIFT);
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (pos) {
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case 0:
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[1] |= ((sr & NVFX_VP(SRC0_HIGH_MASK)) >>
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           NVFX_VP(SRC0_HIGH_SHIFT)) << NVFX_VP(INST_SRC0H_SHIFT);
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[2] |= (sr & NVFX_VP(SRC0_LOW_MASK)) <<
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           NVFX_VP(INST_SRC0L_SHIFT);
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case 1:
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[2] |= sr << NVFX_VP(INST_SRC1_SHIFT);
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case 2:
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[2] |= ((sr & NVFX_VP(SRC2_HIGH_MASK)) >>
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           NVFX_VP(SRC2_HIGH_SHIFT)) << NVFX_VP(INST_SRC2H_SHIFT);
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[3] |= (sr & NVFX_VP(SRC2_LOW_MASK)) <<
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           NVFX_VP(INST_SRC2L_SHIFT);
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(0);
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgemit_dst(struct nv30_context *nv30, struct nvfx_vpc *vpc, uint32_t *hw,
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         int slot, struct nvfx_reg dst)
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_vertprog *vp = vpc->vp;
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (dst.type) {
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case NVFXSR_NONE:
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(!nv30->is_nv4x)
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= NV30_VP_INST_DEST_TEMP_ID_MASK;
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= NV40_VP_INST_DEST_MASK;
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (slot == 0)
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK;
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case NVFXSR_TEMP:
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(!nv30->is_nv4x)
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT);
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= NV40_VP_INST_DEST_MASK;
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (slot == 0)
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[0] |= (dst.index << NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= (dst.index << NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case NVFXSR_OUTPUT:
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* TODO: this may be wrong because on nv30 COL0 and BFC0 are swapped */
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(nv30->is_nv4x) {
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         switch (dst.index) {
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV30_VP_INST_DEST_CLP(0):
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            dst.index = NVFX_VP(INST_DEST_FOGC);
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            vp->or   |= (1 << 6);
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV30_VP_INST_DEST_CLP(1):
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            dst.index = NVFX_VP(INST_DEST_FOGC);
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            vp->or   |= (1 << 7);
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV30_VP_INST_DEST_CLP(2):
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            dst.index = NVFX_VP(INST_DEST_FOGC);
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            vp->or   |= (1 << 8);
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV30_VP_INST_DEST_CLP(3):
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            dst.index = NVFX_VP(INST_DEST_PSZ);
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            vp->or   |= (1 << 9);
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV30_VP_INST_DEST_CLP(4):
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            dst.index = NVFX_VP(INST_DEST_PSZ);
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            vp->or   |= (1 << 10);
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV30_VP_INST_DEST_CLP(5):
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            dst.index = NVFX_VP(INST_DEST_PSZ);
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            vp->or   |= (1 << 11);
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV40_VP_INST_DEST_COL0: vp->or |= (1 << 0); break;
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV40_VP_INST_DEST_COL1: vp->or |= (1 << 1); break;
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV40_VP_INST_DEST_BFC0: vp->or |= (1 << 2); break;
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV40_VP_INST_DEST_BFC1: vp->or |= (1 << 3); break;
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV40_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break;
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case NV40_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break;
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(!nv30->is_nv4x) {
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT);
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK;
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /*XXX: no way this is entirely correct, someone needs to
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          *     figure out what exactly it is.
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          */
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= 0x800;
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT);
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (slot == 0) {
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[0] |= NV40_VP_INST_VEC_RESULT;
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK;
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= NV40_VP_INST_SCA_RESULT;
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(0);
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnvfx_vp_emit(struct nvfx_vpc *vpc, struct nvfx_insn insn)
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_context *nv30 = vpc->nv30;
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nv30_vertprog *vp = vpc->vp;
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned slot = insn.op >> 7;
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned op = insn.op & 0x7f;
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   uint32_t *hw;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi));
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->vpi = &vp->insns[vp->nr_insns - 1];
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(vpc->vpi, 0, sizeof(*vpc->vpi));
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   hw = vpc->vpi->data;
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (insn.cc_test != NVFX_COND_TR)
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[0] |= NVFX_VP(INST_COND_TEST_ENABLE);
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   hw[0] |= (insn.cc_test << NVFX_VP(INST_COND_SHIFT));
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   hw[0] |= ((insn.cc_swz[0] << NVFX_VP(INST_COND_SWZ_X_SHIFT)) |
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             (insn.cc_swz[1] << NVFX_VP(INST_COND_SWZ_Y_SHIFT)) |
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             (insn.cc_swz[2] << NVFX_VP(INST_COND_SWZ_Z_SHIFT)) |
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             (insn.cc_swz[3] << NVFX_VP(INST_COND_SWZ_W_SHIFT)));
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(insn.cc_update)
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw[0] |= NVFX_VP(INST_COND_UPDATE_ENABLE);
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(insn.sat) {
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(nv30->use_nv4x);
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(nv30->use_nv4x)
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= NV40_VP_INST_SATURATE;
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!nv30->is_nv4x) {
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(slot == 0)
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= ((op >> 4) << NV30_VP_INST_SCA_OPCODEH_SHIFT);
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[1] |= ((op & 0xf) << NV30_VP_INST_SCA_OPCODEL_SHIFT);
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//      hw[3] |= NVFX_VP(INST_SCA_DEST_TEMP_MASK);
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//      hw[3] |= (mask << NVFX_VP(INST_VEC_WRITEMASK_SHIFT));
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (insn.dst.type == NVFXSR_OUTPUT) {
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (slot)
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= (insn.mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= (insn.mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (slot)
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= (insn.mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw[3] |= (insn.mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else {
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (slot == 0) {
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT);
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= (insn.mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT);
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       } else {
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT);
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK ;
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw[3] |= (insn.mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit_dst(nv30, vpc, hw, slot, insn.dst);
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit_src(nv30, vpc, hw, 0, insn.src[0]);
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit_src(nv30, vpc, hw, 1, insn.src[1]);
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit_src(nv30, vpc, hw, 2, insn.src[2]);
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//   if(insn.src[0].indirect || op == NVFX_VP_INST_VEC_OP_ARL)
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//      hw[3] |= NV40_VP_INST_SCA_RESULT;
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic inline struct nvfx_src
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_src src;
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (fsrc->Register.File) {
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_INPUT:
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      src.reg = nvfx_reg(NVFXSR_INPUT, fsrc->Register.Index);
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_CONSTANT:
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(fsrc->Register.Indirect) {
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.reg = vpc->r_const[0];
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.reg.index = fsrc->Register.Index;
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.reg = vpc->r_const[fsrc->Register.Index];
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_IMMEDIATE:
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      src.reg = vpc->imm[fsrc->Register.Index];
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_TEMPORARY:
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      src.reg = vpc->r_temp[fsrc->Register.Index];
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      NOUVEAU_ERR("bad src file\n");
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      src.reg.index = 0;
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      src.reg.type = -1;
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.abs = fsrc->Register.Absolute;
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.negate = fsrc->Register.Negate;
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.swz[0] = fsrc->Register.SwizzleX;
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.swz[1] = fsrc->Register.SwizzleY;
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.swz[2] = fsrc->Register.SwizzleZ;
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.swz[3] = fsrc->Register.SwizzleW;
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.indirect = 0;
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.indirect_reg = 0;
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src.indirect_swz = 0;
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(fsrc->Register.Indirect) {
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(fsrc->Indirect.File == TGSI_FILE_ADDRESS &&
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         (fsrc->Register.File == TGSI_FILE_CONSTANT ||
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          fsrc->Register.File == TGSI_FILE_INPUT)) {
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.indirect = 1;
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.indirect_reg = fsrc->Indirect.Index;
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.indirect_swz = fsrc->Indirect.SwizzleX;
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.reg.index = 0;
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src.reg.type = -1;
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return src;
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE struct nvfx_reg
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtgsi_dst(struct nvfx_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg dst;
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (fdst->Register.File) {
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_NULL:
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dst = nvfx_reg(NVFXSR_NONE, 0);
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_OUTPUT:
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dst = vpc->r_result[fdst->Register.Index];
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_TEMPORARY:
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dst = vpc->r_temp[fdst->Register.Index];
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_FILE_ADDRESS:
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dst = vpc->r_address[fdst->Register.Index];
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      NOUVEAU_ERR("bad dst file %i\n", fdst->Register.File);
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dst.index = 0;
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dst.type = 0;
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return dst;
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic inline int
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtgsi_mask(uint tgsi)
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int mask = 0;
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (tgsi & TGSI_WRITEMASK_X) mask |= NVFX_VP_MASK_X;
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (tgsi & TGSI_WRITEMASK_Y) mask |= NVFX_VP_MASK_Y;
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (tgsi & TGSI_WRITEMASK_Z) mask |= NVFX_VP_MASK_Z;
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (tgsi & TGSI_WRITEMASK_W) mask |= NVFX_VP_MASK_W;
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return mask;
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnvfx_vertprog_parse_instruction(struct nv30_context *nv30, struct nvfx_vpc *vpc,
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            unsigned idx, const struct tgsi_full_instruction *finst)
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_src src[3], tmp;
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg dst;
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_reg final_dst;
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_insn insn;
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_relocation reloc;
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_loop_entry loop;
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   boolean sat = FALSE;
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int mask;
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int ai = -1, ci = -1, ii = -1;
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int i;
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned sub_depth = 0;
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct tgsi_full_src_register *fsrc;
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      fsrc = &finst->Src[i];
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (fsrc->Register.File == TGSI_FILE_TEMPORARY) {
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         src[i] = tgsi_src(vpc, fsrc);
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct tgsi_full_src_register *fsrc;
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      fsrc = &finst->Src[i];
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch (fsrc->Register.File) {
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_FILE_INPUT:
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (ai == -1 || ai == fsrc->Register.Index) {
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ai = fsrc->Register.Index;
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            src[i] = tgsi_src(vpc, fsrc);
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            src[i] = nvfx_src(temp(vpc));
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            nvfx_vp_emit(vpc, arith(0, VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL,
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         tgsi_src(vpc, fsrc), none, none));
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_FILE_CONSTANT:
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if ((ci == -1 && ii == -1) ||
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             ci == fsrc->Register.Index) {
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ci = fsrc->Register.Index;
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            src[i] = tgsi_src(vpc, fsrc);
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            src[i] = nvfx_src(temp(vpc));
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            nvfx_vp_emit(vpc, arith(0, VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL,
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         tgsi_src(vpc, fsrc), none, none));
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_FILE_IMMEDIATE:
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if ((ci == -1 && ii == -1) ||
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             ii == fsrc->Register.Index) {
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ii = fsrc->Register.Index;
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            src[i] = tgsi_src(vpc, fsrc);
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            src[i] = nvfx_src(temp(vpc));
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            nvfx_vp_emit(vpc, arith(0, VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL,
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         tgsi_src(vpc, fsrc), none, none));
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_FILE_TEMPORARY:
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* handled above */
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         NOUVEAU_ERR("bad src file\n");
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return FALSE;
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(src[i].reg.type < 0)
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return FALSE;
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(finst->Dst[0].Register.File == TGSI_FILE_ADDRESS &&
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      finst->Instruction.Opcode != TGSI_OPCODE_ARL)
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   final_dst = dst  = tgsi_dst(vpc, &finst->Dst[0]);
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mask = tgsi_mask(finst->Dst[0].Register.WriteMask);
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) {
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(finst->Instruction.Opcode != TGSI_OPCODE_ARL);
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (nv30->use_nv4x)
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         sat = TRUE;
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(dst.type != NVFXSR_TEMP)
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         dst = temp(vpc);
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (finst->Instruction.Opcode) {
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_ABS:
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, abs(src[0]), none, none));
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_ADD:
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, ADD, dst, mask, src[0], none, src[1]));
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_ARL:
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, ARL, dst, mask, src[0], none, none));
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_CEIL:
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmp = nvfx_src(temp(vpc));
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, FLR, tmp.reg, mask, neg(src[0]), none, none));
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, neg(tmp), none, none));
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_CMP:
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn = arith(0, VEC, MOV, none.reg, mask, src[0], none, none);
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_update = 1;
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn = arith(sat, VEC, MOV, dst, mask, src[2], none, none);
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_test = NVFX_COND_GE;
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn = arith(sat, VEC, MOV, dst, mask, src[1], none, none);
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_test = NVFX_COND_LT;
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_COS:
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, COS, dst, mask, none, none, src[0]));
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_DP2:
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmp = nvfx_src(temp(vpc));
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, MUL, tmp.reg, NVFX_VP_MASK_X | NVFX_VP_MASK_Y, src[0], src[1], none));
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, ADD, dst, mask, swz(tmp, X, X, X, X), none, swz(tmp, Y, Y, Y, Y)));
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_DP3:
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, DP3, dst, mask, src[0], src[1], none));
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_DP4:
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, DP4, dst, mask, src[0], src[1], none));
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_DPH:
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, DPH, dst, mask, src[0], src[1], none));
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_DST:
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, DST, dst, mask, src[0], src[1], none));
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_EX2:
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, EX2, dst, mask, none, none, src[0]));
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_EXP:
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, EXP, dst, mask, none, none, src[0]));
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_FLR:
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, FLR, dst, mask, src[0], none, none));
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_FRC:
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, FRC, dst, mask, src[0], none, none));
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_LG2:
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, LG2, dst, mask, none, none, src[0]));
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_LIT:
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, LIT, dst, mask, none, none, src[0]));
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_LOG:
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, LOG, dst, mask, none, none, src[0]));
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_LRP:
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmp = nvfx_src(temp(vpc));
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, MAD, tmp.reg, mask, neg(src[0]), src[2], src[2]));
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MAD, dst, mask, src[0], src[1], tmp));
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_MAD:
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MAD, dst, mask, src[0], src[1], src[2]));
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_MAX:
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MAX, dst, mask, src[0], src[1], none));
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_MIN:
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MIN, dst, mask, src[0], src[1], none));
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_MOV:
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, src[0], none, none));
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_MUL:
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MUL, dst, mask, src[0], src[1], none));
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_NOP:
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_POW:
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmp = nvfx_src(temp(vpc));
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, SCA, LG2, tmp.reg, NVFX_VP_MASK_X, none, none, swz(src[0], X, X, X, X)));
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, MUL, tmp.reg, NVFX_VP_MASK_X, swz(tmp, X, X, X, X), swz(src[1], X, X, X, X), none));
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, EX2, dst, mask, none, none, swz(tmp, X, X, X, X)));
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_RCP:
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, RCP, dst, mask, none, none, src[0]));
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_RSQ:
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, RSQ, dst, mask, none, none, abs(src[0])));
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SEQ:
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SEQ, dst, mask, src[0], src[1], none));
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SFL:
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SFL, dst, mask, src[0], src[1], none));
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SGE:
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SGE, dst, mask, src[0], src[1], none));
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SGT:
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SGT, dst, mask, src[0], src[1], none));
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SIN:
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, SCA, SIN, dst, mask, none, none, src[0]));
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SLE:
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SLE, dst, mask, src[0], src[1], none));
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SLT:
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SLT, dst, mask, src[0], src[1], none));
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SNE:
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SNE, dst, mask, src[0], src[1], none));
676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SSG:
678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, SSG, dst, mask, src[0], none, none));
679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_STR:
681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, STR, dst, mask, src[0], src[1], none));
682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_SUB:
684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, ADD, dst, mask, src[0], none, neg(src[1])));
685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_TRUNC:
687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmp = nvfx_src(temp(vpc));
688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn = arith(0, VEC, MOV, none.reg, mask, src[0], none, none);
689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_update = 1;
690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, FLR, tmp.reg, mask, abs(src[0]), none, none));
693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, tmp, none, none));
694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn = arith(sat, VEC, MOV, dst, mask, neg(tmp), none, none);
696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_test = NVFX_COND_LT;
697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_XPD:
700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmp = nvfx_src(temp(vpc));
701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, MUL, tmp.reg, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none));
702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(sat, VEC, MAD, dst, (mask & ~NVFX_VP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)));
703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_IF:
705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn = arith(0, VEC, MOV, none.reg, NVFX_VP_MASK_X, src[0], none, none);
706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_update = 1;
707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.location = vpc->vp->nr_insns;
710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.target = finst->Label.Label + 1;
711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn = arith(0, SCA, BRA, none.reg, 0, none, none, none);
714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_test = NVFX_COND_EQ;
715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insn.cc_swz[0] = insn.cc_swz[1] = insn.cc_swz[2] = insn.cc_swz[3] = 0;
716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_ELSE:
719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_BRA:
720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_CAL:
721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.location = vpc->vp->nr_insns;
722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.target = finst->Label.Label;
723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(finst->Instruction.Opcode == TGSI_OPCODE_CAL)
726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         insn = arith(0, SCA, CAL, none.reg, 0, none, none, none);
727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         insn = arith(0, SCA, BRA, none.reg, 0, none, none, none);
729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, insn);
730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_RET:
732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(sub_depth || !vpc->vp->enabled_ucps) {
733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         tmp = none;
734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         tmp.swz[0] = tmp.swz[1] = tmp.swz[2] = tmp.swz[3] = 0;
735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         nvfx_vp_emit(vpc, arith(0, SCA, RET, none.reg, 0, none, none, tmp));
736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         reloc.location = vpc->vp->nr_insns;
738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         reloc.target = vpc->info->num_instructions;
739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_BGNSUB:
744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ++sub_depth;
745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_ENDSUB:
747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      --sub_depth;
748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_ENDIF:
750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* nothing to do here */
751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_BGNLOOP:
753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      loop.cont_target = idx;
754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      loop.brk_target = finst->Label.Label + 1;
755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_append(&vpc->loop_stack, struct nvfx_loop_entry, loop);
756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_ENDLOOP:
758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      loop = util_dynarray_pop(&vpc->loop_stack, struct nvfx_loop_entry);
759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.location = vpc->vp->nr_insns;
761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.target = loop.cont_target;
762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_CONT:
767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      loop = util_dynarray_top(&vpc->loop_stack, struct nvfx_loop_entry);
768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.location = vpc->vp->nr_insns;
770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.target = loop.cont_target;
771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_BRK:
776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      loop = util_dynarray_top(&vpc->loop_stack, struct nvfx_loop_entry);
777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.location = vpc->vp->nr_insns;
779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reloc.target = loop.brk_target;
780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_OPCODE_END:
785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(!sub_depth);
786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(vpc->vp->enabled_ucps) {
787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if(idx != (vpc->info->num_instructions - 1)) {
788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            reloc.location = vpc->vp->nr_insns;
789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            reloc.target = vpc->info->num_instructions;
790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if(vpc->vp->nr_insns)
795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         nvfx_vp_emit(vpc, arith(0, VEC, NOP, none.reg, 0, none, none, none));
797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE && !nv30->use_nv4x) {
806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!vpc->r_0_1.type)
807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         vpc->r_0_1 = constant(vpc, -1, 0, 1, 0, 0);
808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, MAX, dst, mask, nvfx_src(dst), swz(nvfx_src(vpc->r_0_1), X, X, X, X), none));
809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, MIN, final_dst, mask, nvfx_src(dst), swz(nvfx_src(vpc->r_0_1), Y, Y, Y, Y), none));
810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   release_temps(vpc);
813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean
817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnvfx_vertprog_parse_decl_output(struct nv30_context *nv30, struct nvfx_vpc *vpc,
818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                const struct tgsi_full_declaration *fdec)
819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_texcoords = nv30->is_nv4x ? 10 : 8;
821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned idx = fdec->Range.First;
822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int hw = 0, i;
823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (fdec->Semantic.Name) {
825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_POSITION:
826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw = NVFX_VP(INST_DEST_POS);
827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->hpos_idx = idx;
828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_CLIPVERTEX:
830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->r_result[idx] = temp(vpc);
831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->r_temps_discard = 0;
832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->cvtx_idx = idx;
833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return TRUE;
834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_COLOR:
835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (fdec->Semantic.Index == 0) {
836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw = NVFX_VP(INST_DEST_COL0);
837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else
838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (fdec->Semantic.Index == 1) {
839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw = NVFX_VP(INST_DEST_COL1);
840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         NOUVEAU_ERR("bad colour semantic index\n");
842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return FALSE;
843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_BCOLOR:
846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (fdec->Semantic.Index == 0) {
847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw = NVFX_VP(INST_DEST_BFC0);
848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else
849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (fdec->Semantic.Index == 1) {
850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         hw = NVFX_VP(INST_DEST_BFC1);
851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         NOUVEAU_ERR("bad bcolour semantic index\n");
853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return FALSE;
854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_FOG:
857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw = NVFX_VP(INST_DEST_FOGC);
858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_PSIZE:
860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw = NVFX_VP(INST_DEST_PSZ);
861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_GENERIC:
863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < num_texcoords; i++) {
864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (vpc->vp->texcoord[i] == fdec->Semantic.Index) {
865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            hw = NVFX_VP(INST_DEST_TC(i));
866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (i == num_texcoords) {
871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         vpc->r_result[idx] = nvfx_reg(NVFXSR_NONE, 0);
872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return TRUE;
873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case TGSI_SEMANTIC_EDGEFLAG:
876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* not really an error just a fallback */
877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      NOUVEAU_ERR("cannot handle edgeflag output\n");
878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      NOUVEAU_ERR("bad output semantic\n");
881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->r_result[idx] = nvfx_reg(NVFXSR_OUTPUT, hw);
885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean
889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnvfx_vertprog_prepare(struct nv30_context *nv30, struct nvfx_vpc *vpc)
890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct tgsi_parse_context p;
892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int high_const = -1, high_temp = -1, high_addr = -1, nr_imm = 0, i;
893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   tgsi_parse_init(&p, vpc->pipe.tokens);
895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while (!tgsi_parse_end_of_tokens(&p)) {
896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const union tgsi_full_token *tok = &p.FullToken;
897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tgsi_parse_token(&p);
899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch(tok->Token.Type) {
900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_TOKEN_TYPE_IMMEDIATE:
901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         nr_imm++;
902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_TOKEN_TYPE_DECLARATION:
904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         const struct tgsi_full_declaration *fdec;
906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         fdec = &p.FullToken.FullDeclaration;
908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         switch (fdec->Declaration.File) {
909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case TGSI_FILE_TEMPORARY:
910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (fdec->Range.Last > high_temp) {
911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               high_temp =
912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  fdec->Range.Last;
913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case TGSI_FILE_ADDRESS:
916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (fdec->Range.Last > high_addr) {
917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               high_addr =
918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  fdec->Range.Last;
919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case TGSI_FILE_CONSTANT:
922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (fdec->Range.Last > high_const) {
923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               high_const =
924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     fdec->Range.Last;
925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case TGSI_FILE_OUTPUT:
928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (!nvfx_vertprog_parse_decl_output(nv30, vpc, fdec))
929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               return FALSE;
930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         default:
932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   tgsi_parse_free(&p);
941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (nr_imm) {
943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->imm = CALLOC(nr_imm, sizeof(struct nvfx_reg));
944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(vpc->imm);
945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (++high_temp) {
948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_reg));
949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < high_temp; i++)
950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         vpc->r_temp[i] = temp(vpc);
951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (++high_addr) {
954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->r_address = CALLOC(high_addr, sizeof(struct nvfx_reg));
955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < high_addr; i++)
956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         vpc->r_address[i] = nvfx_reg(NVFXSR_TEMP, i);
957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(++high_const) {
960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->r_const = CALLOC(high_const, sizeof(struct nvfx_reg));
961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < high_const; i++)
962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         vpc->r_const[i] = constant(vpc, i, 0, 0, 0, 0);
963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->r_temps_discard = 0;
966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgDEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_vp, "NVFX_DUMP_VP", FALSE)
970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgboolean
972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_nvfx_vertprog_translate(struct nv30_context *nv30, struct nv30_vertprog *vp)
973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct tgsi_parse_context parse;
975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_vpc *vpc = NULL;
976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct util_dynarray insns;
978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int i, ucps;
979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vp->translated = FALSE;
981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vp->nr_insns = 0;
982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vp->nr_consts = 0;
983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc = CALLOC_STRUCT(nvfx_vpc);
985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!vpc)
986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->nv30 = nv30;
988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->vp   = vp;
989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->pipe = vp->pipe;
990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->info = &vp->info;
991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vpc->cvtx_idx = -1;
992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!nvfx_vertprog_prepare(nv30, vpc)) {
994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(vpc);
995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Redirect post-transform vertex position to a temp if user clip
999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * planes are enabled.  We need to append code to the vtxprog
1000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * to handle clip planes later.
1001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (vp->enabled_ucps && vpc->cvtx_idx < 0)  {
1003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->r_result[vpc->hpos_idx] = temp(vpc);
1004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->r_temps_discard = 0;
1005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->cvtx_idx = vpc->hpos_idx;
1006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   util_dynarray_init(&insns);
1009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   tgsi_parse_init(&parse, vp->pipe.tokens);
1011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while (!tgsi_parse_end_of_tokens(&parse)) {
1012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tgsi_parse_token(&parse);
1013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch (parse.FullToken.Token.Type) {
1015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_TOKEN_TYPE_IMMEDIATE:
1016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
1017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         const struct tgsi_full_immediate *imm;
1018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         imm = &parse.FullToken.FullImmediate;
1020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
1021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(imm->Immediate.NrTokens == 4 + 1);
1022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         vpc->imm[vpc->nr_imm++] =
1023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            constant(vpc, -1,
1024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                imm->u[0].Float,
1025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                imm->u[1].Float,
1026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                imm->u[2].Float,
1027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                imm->u[3].Float);
1028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case TGSI_TOKEN_TYPE_INSTRUCTION:
1031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
1032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         const struct tgsi_full_instruction *finst;
1033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         unsigned idx = insns.size >> 2;
1034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         util_dynarray_append(&insns, unsigned, vp->nr_insns);
1035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         finst = &parse.FullToken.FullInstruction;
1036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!nvfx_vertprog_parse_instruction(nv30, vpc, idx, finst))
1037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            goto out;
1038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
1041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   util_dynarray_append(&insns, unsigned, vp->nr_insns);
1046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for(unsigned i = 0; i < vpc->label_relocs.size; i += sizeof(struct nvfx_relocation))
1048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct nvfx_relocation* label_reloc = (struct nvfx_relocation*)((char*)vpc->label_relocs.data + i);
1050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct nvfx_relocation hw_reloc;
1051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw_reloc.location = label_reloc->location;
1053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hw_reloc.target = ((unsigned*)insns.data)[label_reloc->target];
1054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      //debug_printf("hw %u -> tgsi %u = hw %u\n", hw_reloc.location, label_reloc->target, hw_reloc.target);
1056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_append(&vp->branch_relocs, struct nvfx_relocation, hw_reloc);
1058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   util_dynarray_fini(&insns);
1060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   util_dynarray_trim(&vp->branch_relocs);
1061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* XXX: what if we add a RET before?!  make sure we jump here...*/
1063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Write out HPOS if it was redirected to a temp earlier */
1065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (vpc->r_result[vpc->hpos_idx].type != NVFXSR_OUTPUT) {
1066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct nvfx_reg hpos = nvfx_reg(NVFXSR_OUTPUT,
1067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  NVFX_VP(INST_DEST_POS));
1068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct nvfx_src htmp = nvfx_src(vpc->r_result[vpc->hpos_idx]);
1069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, MOV, hpos, NVFX_VP_MASK_ALL, htmp, none, none));
1071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Insert code to handle user clip planes */
1074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ucps = vp->enabled_ucps;
1075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while (ucps) {
1076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int i = ffs(ucps) - 1; ucps &= ~(1 << i);
1077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct nvfx_reg cdst = nvfx_reg(NVFXSR_OUTPUT, NV30_VP_INST_DEST_CLP(i));
1078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct nvfx_src ceqn = nvfx_src(nvfx_reg(NVFXSR_CONST, 512 + i));
1079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct nvfx_src htmp = nvfx_src(vpc->r_result[vpc->cvtx_idx]);
1080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned mask;
1081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(nv30->is_nv4x)
1083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
1084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         switch (i) {
1085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case 0: case 3: mask = NVFX_VP_MASK_Y; break;
1086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case 1: case 4: mask = NVFX_VP_MASK_Z; break;
1087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case 2: case 5: mask = NVFX_VP_MASK_W; break;
1088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         default:
1089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            NOUVEAU_ERR("invalid clip dist #%d\n", i);
1090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            goto out;
1091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
1094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         mask = NVFX_VP_MASK_X;
1095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      nvfx_vp_emit(vpc, arith(0, VEC, DP4, cdst, mask, htmp, ceqn, none));
1097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (vpc->vp->nr_insns)
1100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
1101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(debug_get_option_nvfx_dump_vp())
1103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf("\n");
1105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tgsi_dump(vpc->pipe.tokens, 0);
1106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf("\n%s vertex program:\n", nv30->is_nv4x ? "nv4x" : "nv3x");
1108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < vp->nr_insns; i++)
1109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         debug_printf("%3u: %08x %08x %08x %08x\n", i, vp->insns[i].data[0], vp->insns[i].data[1], vp->insns[i].data[2], vp->insns[i].data[3]);
1110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf("\n");
1111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vp->translated = TRUE;
1114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgout:
1116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   tgsi_parse_free(&parse);
1117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(vpc) {
1118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_fini(&vpc->label_relocs);
1119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      util_dynarray_fini(&vpc->loop_stack);
1120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(vpc->r_temp);
1121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(vpc->r_address);
1122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(vpc->r_const);
1123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(vpc->imm);
1124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(vpc);
1125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return vp->translated;
1128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1129