1bf215546Sopenharmony_ci/**********************************************************
2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation
6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without
7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy,
8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies
9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci **********************************************************/
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h"
28bf215546Sopenharmony_ci#include "tgsi/tgsi_dump.h"
29bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
30bf215546Sopenharmony_ci#include "util/u_memory.h"
31bf215546Sopenharmony_ci#include "util/u_math.h"
32bf215546Sopenharmony_ci#include "util/u_pstipple.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "svga_tgsi_emit.h"
35bf215546Sopenharmony_ci#include "svga_context.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistatic boolean emit_vs_postamble( struct svga_shader_emitter *emit );
39bf215546Sopenharmony_cistatic boolean emit_ps_postamble( struct svga_shader_emitter *emit );
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic SVGA3dShaderOpCodeType
43bf215546Sopenharmony_citranslate_opcode(enum tgsi_opcode opcode)
44bf215546Sopenharmony_ci{
45bf215546Sopenharmony_ci   switch (opcode) {
46bf215546Sopenharmony_ci   case TGSI_OPCODE_ADD:        return SVGA3DOP_ADD;
47bf215546Sopenharmony_ci   case TGSI_OPCODE_DP3:        return SVGA3DOP_DP3;
48bf215546Sopenharmony_ci   case TGSI_OPCODE_DP4:        return SVGA3DOP_DP4;
49bf215546Sopenharmony_ci   case TGSI_OPCODE_FRC:        return SVGA3DOP_FRC;
50bf215546Sopenharmony_ci   case TGSI_OPCODE_MAD:        return SVGA3DOP_MAD;
51bf215546Sopenharmony_ci   case TGSI_OPCODE_MAX:        return SVGA3DOP_MAX;
52bf215546Sopenharmony_ci   case TGSI_OPCODE_MIN:        return SVGA3DOP_MIN;
53bf215546Sopenharmony_ci   case TGSI_OPCODE_MOV:        return SVGA3DOP_MOV;
54bf215546Sopenharmony_ci   case TGSI_OPCODE_MUL:        return SVGA3DOP_MUL;
55bf215546Sopenharmony_ci   case TGSI_OPCODE_NOP:        return SVGA3DOP_NOP;
56bf215546Sopenharmony_ci   default:
57bf215546Sopenharmony_ci      assert(!"svga: unexpected opcode in translate_opcode()");
58bf215546Sopenharmony_ci      return SVGA3DOP_LAST_INST;
59bf215546Sopenharmony_ci   }
60bf215546Sopenharmony_ci}
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_cistatic SVGA3dShaderRegType
64bf215546Sopenharmony_citranslate_file(enum tgsi_file_type file)
65bf215546Sopenharmony_ci{
66bf215546Sopenharmony_ci   switch (file) {
67bf215546Sopenharmony_ci   case TGSI_FILE_TEMPORARY: return SVGA3DREG_TEMP;
68bf215546Sopenharmony_ci   case TGSI_FILE_INPUT:     return SVGA3DREG_INPUT;
69bf215546Sopenharmony_ci   case TGSI_FILE_OUTPUT:    return SVGA3DREG_OUTPUT; /* VS3.0+ only */
70bf215546Sopenharmony_ci   case TGSI_FILE_IMMEDIATE: return SVGA3DREG_CONST;
71bf215546Sopenharmony_ci   case TGSI_FILE_CONSTANT:  return SVGA3DREG_CONST;
72bf215546Sopenharmony_ci   case TGSI_FILE_SAMPLER:   return SVGA3DREG_SAMPLER;
73bf215546Sopenharmony_ci   case TGSI_FILE_ADDRESS:   return SVGA3DREG_ADDR;
74bf215546Sopenharmony_ci   default:
75bf215546Sopenharmony_ci      assert(!"svga: unexpected register file in translate_file()");
76bf215546Sopenharmony_ci      return SVGA3DREG_TEMP;
77bf215546Sopenharmony_ci   }
78bf215546Sopenharmony_ci}
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci/**
82bf215546Sopenharmony_ci * Translate a TGSI destination register to an SVGA3DShaderDestToken.
83bf215546Sopenharmony_ci * \param insn  the TGSI instruction
84bf215546Sopenharmony_ci * \param idx  which TGSI dest register to translate (usually (always?) zero)
85bf215546Sopenharmony_ci */
86bf215546Sopenharmony_cistatic SVGA3dShaderDestToken
87bf215546Sopenharmony_citranslate_dst_register( struct svga_shader_emitter *emit,
88bf215546Sopenharmony_ci                        const struct tgsi_full_instruction *insn,
89bf215546Sopenharmony_ci                        unsigned idx )
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   const struct tgsi_full_dst_register *reg = &insn->Dst[idx];
92bf215546Sopenharmony_ci   SVGA3dShaderDestToken dest;
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   switch (reg->Register.File) {
95bf215546Sopenharmony_ci   case TGSI_FILE_OUTPUT:
96bf215546Sopenharmony_ci      /* Output registers encode semantic information in their name.
97bf215546Sopenharmony_ci       * Need to lookup a table built at decl time:
98bf215546Sopenharmony_ci       */
99bf215546Sopenharmony_ci      dest = emit->output_map[reg->Register.Index];
100bf215546Sopenharmony_ci      emit->num_output_writes++;
101bf215546Sopenharmony_ci      break;
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   default:
104bf215546Sopenharmony_ci      {
105bf215546Sopenharmony_ci         unsigned index = reg->Register.Index;
106bf215546Sopenharmony_ci         assert(index < SVGA3D_TEMPREG_MAX);
107bf215546Sopenharmony_ci         index = MIN2(index, SVGA3D_TEMPREG_MAX - 1);
108bf215546Sopenharmony_ci         dest = dst_register(translate_file(reg->Register.File), index);
109bf215546Sopenharmony_ci      }
110bf215546Sopenharmony_ci      break;
111bf215546Sopenharmony_ci   }
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   if (reg->Register.Indirect) {
114bf215546Sopenharmony_ci      debug_warning("Indirect indexing of dest registers is not supported!\n");
115bf215546Sopenharmony_ci   }
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   dest.mask = reg->Register.WriteMask;
118bf215546Sopenharmony_ci   assert(dest.mask);
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   if (insn->Instruction.Saturate)
121bf215546Sopenharmony_ci      dest.dstMod = SVGA3DDSTMOD_SATURATE;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   return dest;
124bf215546Sopenharmony_ci}
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci/**
128bf215546Sopenharmony_ci * Apply a swizzle to a src_register, returning a new src_register
129bf215546Sopenharmony_ci * Ex: swizzle(SRC.ZZYY, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_X, SWIZZLE_Y)
130bf215546Sopenharmony_ci * would return SRC.YYZZ
131bf215546Sopenharmony_ci */
132bf215546Sopenharmony_cistatic struct src_register
133bf215546Sopenharmony_ciswizzle(struct src_register src,
134bf215546Sopenharmony_ci        unsigned x, unsigned y, unsigned z, unsigned w)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   assert(x < 4);
137bf215546Sopenharmony_ci   assert(y < 4);
138bf215546Sopenharmony_ci   assert(z < 4);
139bf215546Sopenharmony_ci   assert(w < 4);
140bf215546Sopenharmony_ci   x = (src.base.swizzle >> (x * 2)) & 0x3;
141bf215546Sopenharmony_ci   y = (src.base.swizzle >> (y * 2)) & 0x3;
142bf215546Sopenharmony_ci   z = (src.base.swizzle >> (z * 2)) & 0x3;
143bf215546Sopenharmony_ci   w = (src.base.swizzle >> (w * 2)) & 0x3;
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   src.base.swizzle = TRANSLATE_SWIZZLE(x, y, z, w);
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   return src;
148bf215546Sopenharmony_ci}
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci/**
152bf215546Sopenharmony_ci * Apply a "scalar" swizzle to a src_register returning a new
153bf215546Sopenharmony_ci * src_register where all the swizzle terms are the same.
154bf215546Sopenharmony_ci * Ex: scalar(SRC.WZYX, SWIZZLE_Y) would return SRC.ZZZZ
155bf215546Sopenharmony_ci */
156bf215546Sopenharmony_cistatic struct src_register
157bf215546Sopenharmony_ciscalar(struct src_register src, unsigned comp)
158bf215546Sopenharmony_ci{
159bf215546Sopenharmony_ci   assert(comp < 4);
160bf215546Sopenharmony_ci   return swizzle( src, comp, comp, comp, comp );
161bf215546Sopenharmony_ci}
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_cistatic boolean
165bf215546Sopenharmony_cisvga_arl_needs_adjustment( const struct svga_shader_emitter *emit )
166bf215546Sopenharmony_ci{
167bf215546Sopenharmony_ci   unsigned i;
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   for (i = 0; i < emit->num_arl_consts; ++i) {
170bf215546Sopenharmony_ci      if (emit->arl_consts[i].arl_num == emit->current_arl)
171bf215546Sopenharmony_ci         return TRUE;
172bf215546Sopenharmony_ci   }
173bf215546Sopenharmony_ci   return FALSE;
174bf215546Sopenharmony_ci}
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_cistatic int
178bf215546Sopenharmony_cisvga_arl_adjustment( const struct svga_shader_emitter *emit )
179bf215546Sopenharmony_ci{
180bf215546Sopenharmony_ci   unsigned i;
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   for (i = 0; i < emit->num_arl_consts; ++i) {
183bf215546Sopenharmony_ci      if (emit->arl_consts[i].arl_num == emit->current_arl)
184bf215546Sopenharmony_ci         return emit->arl_consts[i].number;
185bf215546Sopenharmony_ci   }
186bf215546Sopenharmony_ci   return 0;
187bf215546Sopenharmony_ci}
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci/**
191bf215546Sopenharmony_ci * Translate a TGSI src register to a src_register.
192bf215546Sopenharmony_ci */
193bf215546Sopenharmony_cistatic struct src_register
194bf215546Sopenharmony_citranslate_src_register( const struct svga_shader_emitter *emit,
195bf215546Sopenharmony_ci                        const struct tgsi_full_src_register *reg )
196bf215546Sopenharmony_ci{
197bf215546Sopenharmony_ci   struct src_register src;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   switch (reg->Register.File) {
200bf215546Sopenharmony_ci   case TGSI_FILE_INPUT:
201bf215546Sopenharmony_ci      /* Input registers are referred to by their semantic name rather
202bf215546Sopenharmony_ci       * than by index.  Use the mapping build up from the decls:
203bf215546Sopenharmony_ci       */
204bf215546Sopenharmony_ci      src = emit->input_map[reg->Register.Index];
205bf215546Sopenharmony_ci      break;
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci   case TGSI_FILE_IMMEDIATE:
208bf215546Sopenharmony_ci      /* Immediates are appended after TGSI constants in the D3D
209bf215546Sopenharmony_ci       * constant buffer.
210bf215546Sopenharmony_ci       */
211bf215546Sopenharmony_ci      src = src_register( translate_file( reg->Register.File ),
212bf215546Sopenharmony_ci                          reg->Register.Index + emit->imm_start );
213bf215546Sopenharmony_ci      break;
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   default:
216bf215546Sopenharmony_ci      src = src_register( translate_file( reg->Register.File ),
217bf215546Sopenharmony_ci                          reg->Register.Index );
218bf215546Sopenharmony_ci      break;
219bf215546Sopenharmony_ci   }
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci   /* Indirect addressing.
222bf215546Sopenharmony_ci    */
223bf215546Sopenharmony_ci   if (reg->Register.Indirect) {
224bf215546Sopenharmony_ci      if (emit->unit == PIPE_SHADER_FRAGMENT) {
225bf215546Sopenharmony_ci         /* Pixel shaders have only loop registers for relative
226bf215546Sopenharmony_ci          * addressing into inputs. Ignore the redundant address
227bf215546Sopenharmony_ci          * register, the contents of aL should be in sync with it.
228bf215546Sopenharmony_ci          */
229bf215546Sopenharmony_ci         if (reg->Register.File == TGSI_FILE_INPUT) {
230bf215546Sopenharmony_ci            src.base.relAddr = 1;
231bf215546Sopenharmony_ci            src.indirect = src_token(SVGA3DREG_LOOP, 0);
232bf215546Sopenharmony_ci         }
233bf215546Sopenharmony_ci      }
234bf215546Sopenharmony_ci      else {
235bf215546Sopenharmony_ci         /* Constant buffers only.
236bf215546Sopenharmony_ci          */
237bf215546Sopenharmony_ci         if (reg->Register.File == TGSI_FILE_CONSTANT) {
238bf215546Sopenharmony_ci            /* we shift the offset towards the minimum */
239bf215546Sopenharmony_ci            if (svga_arl_needs_adjustment( emit )) {
240bf215546Sopenharmony_ci               src.base.num -= svga_arl_adjustment( emit );
241bf215546Sopenharmony_ci            }
242bf215546Sopenharmony_ci            src.base.relAddr = 1;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci            /* Not really sure what should go in the second token:
245bf215546Sopenharmony_ci             */
246bf215546Sopenharmony_ci            src.indirect = src_token( SVGA3DREG_ADDR,
247bf215546Sopenharmony_ci                                      reg->Indirect.Index );
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci            src.indirect.swizzle = SWIZZLE_XXXX;
250bf215546Sopenharmony_ci         }
251bf215546Sopenharmony_ci      }
252bf215546Sopenharmony_ci   }
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   src = swizzle( src,
255bf215546Sopenharmony_ci                  reg->Register.SwizzleX,
256bf215546Sopenharmony_ci                  reg->Register.SwizzleY,
257bf215546Sopenharmony_ci                  reg->Register.SwizzleZ,
258bf215546Sopenharmony_ci                  reg->Register.SwizzleW );
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   /* src.mod isn't a bitfield, unfortunately */
261bf215546Sopenharmony_ci   if (reg->Register.Absolute) {
262bf215546Sopenharmony_ci      if (reg->Register.Negate)
263bf215546Sopenharmony_ci         src.base.srcMod = SVGA3DSRCMOD_ABSNEG;
264bf215546Sopenharmony_ci      else
265bf215546Sopenharmony_ci         src.base.srcMod = SVGA3DSRCMOD_ABS;
266bf215546Sopenharmony_ci   }
267bf215546Sopenharmony_ci   else {
268bf215546Sopenharmony_ci      if (reg->Register.Negate)
269bf215546Sopenharmony_ci         src.base.srcMod = SVGA3DSRCMOD_NEG;
270bf215546Sopenharmony_ci      else
271bf215546Sopenharmony_ci         src.base.srcMod = SVGA3DSRCMOD_NONE;
272bf215546Sopenharmony_ci   }
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   return src;
275bf215546Sopenharmony_ci}
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci/*
279bf215546Sopenharmony_ci * Get a temporary register.
280bf215546Sopenharmony_ci * Note: if we exceed the temporary register limit we just use
281bf215546Sopenharmony_ci * register SVGA3D_TEMPREG_MAX - 1.
282bf215546Sopenharmony_ci */
283bf215546Sopenharmony_cistatic SVGA3dShaderDestToken
284bf215546Sopenharmony_ciget_temp( struct svga_shader_emitter *emit )
285bf215546Sopenharmony_ci{
286bf215546Sopenharmony_ci   int i = emit->nr_hw_temp + emit->internal_temp_count++;
287bf215546Sopenharmony_ci   if (i >= SVGA3D_TEMPREG_MAX) {
288bf215546Sopenharmony_ci      debug_warn_once("svga: Too many temporary registers used in shader\n");
289bf215546Sopenharmony_ci      i = SVGA3D_TEMPREG_MAX - 1;
290bf215546Sopenharmony_ci   }
291bf215546Sopenharmony_ci   return dst_register( SVGA3DREG_TEMP, i );
292bf215546Sopenharmony_ci}
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci/**
296bf215546Sopenharmony_ci * Release a single temp.  Currently only effective if it was the last
297bf215546Sopenharmony_ci * allocated temp, otherwise release will be delayed until the next
298bf215546Sopenharmony_ci * call to reset_temp_regs().
299bf215546Sopenharmony_ci */
300bf215546Sopenharmony_cistatic void
301bf215546Sopenharmony_cirelease_temp( struct svga_shader_emitter *emit,
302bf215546Sopenharmony_ci              SVGA3dShaderDestToken temp )
303bf215546Sopenharmony_ci{
304bf215546Sopenharmony_ci   if (temp.num == emit->internal_temp_count - 1)
305bf215546Sopenharmony_ci      emit->internal_temp_count--;
306bf215546Sopenharmony_ci}
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci/**
310bf215546Sopenharmony_ci * Release all temps.
311bf215546Sopenharmony_ci */
312bf215546Sopenharmony_cistatic void
313bf215546Sopenharmony_cireset_temp_regs(struct svga_shader_emitter *emit)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci   emit->internal_temp_count = 0;
316bf215546Sopenharmony_ci}
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci/** Emit bytecode for a src_register */
320bf215546Sopenharmony_cistatic boolean
321bf215546Sopenharmony_ciemit_src(struct svga_shader_emitter *emit, const struct src_register src)
322bf215546Sopenharmony_ci{
323bf215546Sopenharmony_ci   if (src.base.relAddr) {
324bf215546Sopenharmony_ci      assert(src.base.reserved0);
325bf215546Sopenharmony_ci      assert(src.indirect.reserved0);
326bf215546Sopenharmony_ci      return (svga_shader_emit_dword( emit, src.base.value ) &&
327bf215546Sopenharmony_ci              svga_shader_emit_dword( emit, src.indirect.value ));
328bf215546Sopenharmony_ci   }
329bf215546Sopenharmony_ci   else {
330bf215546Sopenharmony_ci      assert(src.base.reserved0);
331bf215546Sopenharmony_ci      return svga_shader_emit_dword( emit, src.base.value );
332bf215546Sopenharmony_ci   }
333bf215546Sopenharmony_ci}
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci/** Emit bytecode for a dst_register */
337bf215546Sopenharmony_cistatic boolean
338bf215546Sopenharmony_ciemit_dst(struct svga_shader_emitter *emit, SVGA3dShaderDestToken dest)
339bf215546Sopenharmony_ci{
340bf215546Sopenharmony_ci   assert(dest.reserved0);
341bf215546Sopenharmony_ci   assert(dest.mask);
342bf215546Sopenharmony_ci   return svga_shader_emit_dword( emit, dest.value );
343bf215546Sopenharmony_ci}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci/** Emit bytecode for a 1-operand instruction */
347bf215546Sopenharmony_cistatic boolean
348bf215546Sopenharmony_ciemit_op1(struct svga_shader_emitter *emit,
349bf215546Sopenharmony_ci         SVGA3dShaderInstToken inst,
350bf215546Sopenharmony_ci         SVGA3dShaderDestToken dest,
351bf215546Sopenharmony_ci         struct src_register src0)
352bf215546Sopenharmony_ci{
353bf215546Sopenharmony_ci   return (emit_instruction(emit, inst) &&
354bf215546Sopenharmony_ci           emit_dst(emit, dest) &&
355bf215546Sopenharmony_ci           emit_src(emit, src0));
356bf215546Sopenharmony_ci}
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci/** Emit bytecode for a 2-operand instruction */
360bf215546Sopenharmony_cistatic boolean
361bf215546Sopenharmony_ciemit_op2(struct svga_shader_emitter *emit,
362bf215546Sopenharmony_ci         SVGA3dShaderInstToken inst,
363bf215546Sopenharmony_ci         SVGA3dShaderDestToken dest,
364bf215546Sopenharmony_ci         struct src_register src0,
365bf215546Sopenharmony_ci         struct src_register src1)
366bf215546Sopenharmony_ci{
367bf215546Sopenharmony_ci   return (emit_instruction(emit, inst) &&
368bf215546Sopenharmony_ci           emit_dst(emit, dest) &&
369bf215546Sopenharmony_ci           emit_src(emit, src0) &&
370bf215546Sopenharmony_ci           emit_src(emit, src1));
371bf215546Sopenharmony_ci}
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci/** Emit bytecode for a 3-operand instruction */
375bf215546Sopenharmony_cistatic boolean
376bf215546Sopenharmony_ciemit_op3(struct svga_shader_emitter *emit,
377bf215546Sopenharmony_ci         SVGA3dShaderInstToken inst,
378bf215546Sopenharmony_ci         SVGA3dShaderDestToken dest,
379bf215546Sopenharmony_ci         struct src_register src0,
380bf215546Sopenharmony_ci         struct src_register src1,
381bf215546Sopenharmony_ci         struct src_register src2)
382bf215546Sopenharmony_ci{
383bf215546Sopenharmony_ci   return (emit_instruction(emit, inst) &&
384bf215546Sopenharmony_ci           emit_dst(emit, dest) &&
385bf215546Sopenharmony_ci           emit_src(emit, src0) &&
386bf215546Sopenharmony_ci           emit_src(emit, src1) &&
387bf215546Sopenharmony_ci           emit_src(emit, src2));
388bf215546Sopenharmony_ci}
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci/** Emit bytecode for a 4-operand instruction */
392bf215546Sopenharmony_cistatic boolean
393bf215546Sopenharmony_ciemit_op4(struct svga_shader_emitter *emit,
394bf215546Sopenharmony_ci         SVGA3dShaderInstToken inst,
395bf215546Sopenharmony_ci         SVGA3dShaderDestToken dest,
396bf215546Sopenharmony_ci         struct src_register src0,
397bf215546Sopenharmony_ci         struct src_register src1,
398bf215546Sopenharmony_ci         struct src_register src2,
399bf215546Sopenharmony_ci         struct src_register src3)
400bf215546Sopenharmony_ci{
401bf215546Sopenharmony_ci   return (emit_instruction(emit, inst) &&
402bf215546Sopenharmony_ci           emit_dst(emit, dest) &&
403bf215546Sopenharmony_ci           emit_src(emit, src0) &&
404bf215546Sopenharmony_ci           emit_src(emit, src1) &&
405bf215546Sopenharmony_ci           emit_src(emit, src2) &&
406bf215546Sopenharmony_ci           emit_src(emit, src3));
407bf215546Sopenharmony_ci}
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci/**
411bf215546Sopenharmony_ci * Apply the absolute value modifier to the given src_register, returning
412bf215546Sopenharmony_ci * a new src_register.
413bf215546Sopenharmony_ci */
414bf215546Sopenharmony_cistatic struct src_register
415bf215546Sopenharmony_ciabsolute(struct src_register src)
416bf215546Sopenharmony_ci{
417bf215546Sopenharmony_ci   src.base.srcMod = SVGA3DSRCMOD_ABS;
418bf215546Sopenharmony_ci   return src;
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci/**
423bf215546Sopenharmony_ci * Apply the negation modifier to the given src_register, returning
424bf215546Sopenharmony_ci * a new src_register.
425bf215546Sopenharmony_ci */
426bf215546Sopenharmony_cistatic struct src_register
427bf215546Sopenharmony_cinegate(struct src_register src)
428bf215546Sopenharmony_ci{
429bf215546Sopenharmony_ci   switch (src.base.srcMod) {
430bf215546Sopenharmony_ci   case SVGA3DSRCMOD_ABS:
431bf215546Sopenharmony_ci      src.base.srcMod = SVGA3DSRCMOD_ABSNEG;
432bf215546Sopenharmony_ci      break;
433bf215546Sopenharmony_ci   case SVGA3DSRCMOD_ABSNEG:
434bf215546Sopenharmony_ci      src.base.srcMod = SVGA3DSRCMOD_ABS;
435bf215546Sopenharmony_ci      break;
436bf215546Sopenharmony_ci   case SVGA3DSRCMOD_NEG:
437bf215546Sopenharmony_ci      src.base.srcMod = SVGA3DSRCMOD_NONE;
438bf215546Sopenharmony_ci      break;
439bf215546Sopenharmony_ci   case SVGA3DSRCMOD_NONE:
440bf215546Sopenharmony_ci      src.base.srcMod = SVGA3DSRCMOD_NEG;
441bf215546Sopenharmony_ci      break;
442bf215546Sopenharmony_ci   }
443bf215546Sopenharmony_ci   return src;
444bf215546Sopenharmony_ci}
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci/* Replace the src with the temporary specified in the dst, but copying
449bf215546Sopenharmony_ci * only the necessary channels, and preserving the original swizzle (which is
450bf215546Sopenharmony_ci * important given that several opcodes have constraints in the allowed
451bf215546Sopenharmony_ci * swizzles).
452bf215546Sopenharmony_ci */
453bf215546Sopenharmony_cistatic boolean
454bf215546Sopenharmony_ciemit_repl(struct svga_shader_emitter *emit,
455bf215546Sopenharmony_ci          SVGA3dShaderDestToken dst,
456bf215546Sopenharmony_ci          struct src_register *src0)
457bf215546Sopenharmony_ci{
458bf215546Sopenharmony_ci   unsigned src0_swizzle;
459bf215546Sopenharmony_ci   unsigned chan;
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci   assert(SVGA3dShaderGetRegType(dst.value) == SVGA3DREG_TEMP);
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   src0_swizzle = src0->base.swizzle;
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   dst.mask = 0;
466bf215546Sopenharmony_ci   for (chan = 0; chan < 4; ++chan) {
467bf215546Sopenharmony_ci      unsigned swizzle = (src0_swizzle >> (chan *2)) & 0x3;
468bf215546Sopenharmony_ci      dst.mask |= 1 << swizzle;
469bf215546Sopenharmony_ci   }
470bf215546Sopenharmony_ci   assert(dst.mask);
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci   src0->base.swizzle = SVGA3DSWIZZLE_NONE;
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci   if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, *src0 ))
475bf215546Sopenharmony_ci      return FALSE;
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci   *src0 = src( dst );
478bf215546Sopenharmony_ci   src0->base.swizzle = src0_swizzle;
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   return TRUE;
481bf215546Sopenharmony_ci}
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci/**
485bf215546Sopenharmony_ci * Submit/emit an instruction with zero operands.
486bf215546Sopenharmony_ci */
487bf215546Sopenharmony_cistatic boolean
488bf215546Sopenharmony_cisubmit_op0(struct svga_shader_emitter *emit,
489bf215546Sopenharmony_ci           SVGA3dShaderInstToken inst,
490bf215546Sopenharmony_ci           SVGA3dShaderDestToken dest)
491bf215546Sopenharmony_ci{
492bf215546Sopenharmony_ci   return (emit_instruction( emit, inst ) &&
493bf215546Sopenharmony_ci           emit_dst( emit, dest ));
494bf215546Sopenharmony_ci}
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci/**
498bf215546Sopenharmony_ci * Submit/emit an instruction with one operand.
499bf215546Sopenharmony_ci */
500bf215546Sopenharmony_cistatic boolean
501bf215546Sopenharmony_cisubmit_op1(struct svga_shader_emitter *emit,
502bf215546Sopenharmony_ci           SVGA3dShaderInstToken inst,
503bf215546Sopenharmony_ci           SVGA3dShaderDestToken dest,
504bf215546Sopenharmony_ci           struct src_register src0)
505bf215546Sopenharmony_ci{
506bf215546Sopenharmony_ci   return emit_op1( emit, inst, dest, src0 );
507bf215546Sopenharmony_ci}
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci/**
511bf215546Sopenharmony_ci * Submit/emit an instruction with two operands.
512bf215546Sopenharmony_ci *
513bf215546Sopenharmony_ci * SVGA shaders may not refer to >1 constant register in a single
514bf215546Sopenharmony_ci * instruction.  This function checks for that usage and inserts a
515bf215546Sopenharmony_ci * move to temporary if detected.
516bf215546Sopenharmony_ci *
517bf215546Sopenharmony_ci * The same applies to input registers -- at most a single input
518bf215546Sopenharmony_ci * register may be read by any instruction.
519bf215546Sopenharmony_ci */
520bf215546Sopenharmony_cistatic boolean
521bf215546Sopenharmony_cisubmit_op2(struct svga_shader_emitter *emit,
522bf215546Sopenharmony_ci           SVGA3dShaderInstToken inst,
523bf215546Sopenharmony_ci           SVGA3dShaderDestToken dest,
524bf215546Sopenharmony_ci           struct src_register src0,
525bf215546Sopenharmony_ci           struct src_register src1)
526bf215546Sopenharmony_ci{
527bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp;
528bf215546Sopenharmony_ci   SVGA3dShaderRegType type0, type1;
529bf215546Sopenharmony_ci   boolean need_temp = FALSE;
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci   temp.value = 0;
532bf215546Sopenharmony_ci   type0 = SVGA3dShaderGetRegType( src0.base.value );
533bf215546Sopenharmony_ci   type1 = SVGA3dShaderGetRegType( src1.base.value );
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci   if (type0 == SVGA3DREG_CONST &&
536bf215546Sopenharmony_ci       type1 == SVGA3DREG_CONST &&
537bf215546Sopenharmony_ci       src0.base.num != src1.base.num)
538bf215546Sopenharmony_ci      need_temp = TRUE;
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci   if (type0 == SVGA3DREG_INPUT &&
541bf215546Sopenharmony_ci       type1 == SVGA3DREG_INPUT &&
542bf215546Sopenharmony_ci       src0.base.num != src1.base.num)
543bf215546Sopenharmony_ci      need_temp = TRUE;
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci   if (need_temp) {
546bf215546Sopenharmony_ci      temp = get_temp( emit );
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci      if (!emit_repl( emit, temp, &src0 ))
549bf215546Sopenharmony_ci         return FALSE;
550bf215546Sopenharmony_ci   }
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci   if (!emit_op2( emit, inst, dest, src0, src1 ))
553bf215546Sopenharmony_ci      return FALSE;
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci   if (need_temp)
556bf215546Sopenharmony_ci      release_temp( emit, temp );
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   return TRUE;
559bf215546Sopenharmony_ci}
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci/**
563bf215546Sopenharmony_ci * Submit/emit an instruction with three operands.
564bf215546Sopenharmony_ci *
565bf215546Sopenharmony_ci * SVGA shaders may not refer to >1 constant register in a single
566bf215546Sopenharmony_ci * instruction.  This function checks for that usage and inserts a
567bf215546Sopenharmony_ci * move to temporary if detected.
568bf215546Sopenharmony_ci */
569bf215546Sopenharmony_cistatic boolean
570bf215546Sopenharmony_cisubmit_op3(struct svga_shader_emitter *emit,
571bf215546Sopenharmony_ci           SVGA3dShaderInstToken inst,
572bf215546Sopenharmony_ci           SVGA3dShaderDestToken dest,
573bf215546Sopenharmony_ci           struct src_register src0,
574bf215546Sopenharmony_ci           struct src_register src1,
575bf215546Sopenharmony_ci           struct src_register src2)
576bf215546Sopenharmony_ci{
577bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp0;
578bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp1;
579bf215546Sopenharmony_ci   boolean need_temp0 = FALSE;
580bf215546Sopenharmony_ci   boolean need_temp1 = FALSE;
581bf215546Sopenharmony_ci   SVGA3dShaderRegType type0, type1, type2;
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci   temp0.value = 0;
584bf215546Sopenharmony_ci   temp1.value = 0;
585bf215546Sopenharmony_ci   type0 = SVGA3dShaderGetRegType( src0.base.value );
586bf215546Sopenharmony_ci   type1 = SVGA3dShaderGetRegType( src1.base.value );
587bf215546Sopenharmony_ci   type2 = SVGA3dShaderGetRegType( src2.base.value );
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ci   if (inst.op != SVGA3DOP_SINCOS) {
590bf215546Sopenharmony_ci      if (type0 == SVGA3DREG_CONST &&
591bf215546Sopenharmony_ci          ((type1 == SVGA3DREG_CONST && src0.base.num != src1.base.num) ||
592bf215546Sopenharmony_ci           (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num)))
593bf215546Sopenharmony_ci         need_temp0 = TRUE;
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ci      if (type1 == SVGA3DREG_CONST &&
596bf215546Sopenharmony_ci          (type2 == SVGA3DREG_CONST && src1.base.num != src2.base.num))
597bf215546Sopenharmony_ci         need_temp1 = TRUE;
598bf215546Sopenharmony_ci   }
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci   if (type0 == SVGA3DREG_INPUT &&
601bf215546Sopenharmony_ci       ((type1 == SVGA3DREG_INPUT && src0.base.num != src1.base.num) ||
602bf215546Sopenharmony_ci        (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num)))
603bf215546Sopenharmony_ci      need_temp0 = TRUE;
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   if (type1 == SVGA3DREG_INPUT &&
606bf215546Sopenharmony_ci       (type2 == SVGA3DREG_INPUT && src1.base.num != src2.base.num))
607bf215546Sopenharmony_ci      need_temp1 = TRUE;
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci   if (need_temp0) {
610bf215546Sopenharmony_ci      temp0 = get_temp( emit );
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_ci      if (!emit_repl( emit, temp0, &src0 ))
613bf215546Sopenharmony_ci         return FALSE;
614bf215546Sopenharmony_ci   }
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   if (need_temp1) {
617bf215546Sopenharmony_ci      temp1 = get_temp( emit );
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_ci      if (!emit_repl( emit, temp1, &src1 ))
620bf215546Sopenharmony_ci         return FALSE;
621bf215546Sopenharmony_ci   }
622bf215546Sopenharmony_ci
623bf215546Sopenharmony_ci   if (!emit_op3( emit, inst, dest, src0, src1, src2 ))
624bf215546Sopenharmony_ci      return FALSE;
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci   if (need_temp1)
627bf215546Sopenharmony_ci      release_temp( emit, temp1 );
628bf215546Sopenharmony_ci   if (need_temp0)
629bf215546Sopenharmony_ci      release_temp( emit, temp0 );
630bf215546Sopenharmony_ci   return TRUE;
631bf215546Sopenharmony_ci}
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci/**
635bf215546Sopenharmony_ci * Submit/emit an instruction with four operands.
636bf215546Sopenharmony_ci *
637bf215546Sopenharmony_ci * SVGA shaders may not refer to >1 constant register in a single
638bf215546Sopenharmony_ci * instruction.  This function checks for that usage and inserts a
639bf215546Sopenharmony_ci * move to temporary if detected.
640bf215546Sopenharmony_ci */
641bf215546Sopenharmony_cistatic boolean
642bf215546Sopenharmony_cisubmit_op4(struct svga_shader_emitter *emit,
643bf215546Sopenharmony_ci           SVGA3dShaderInstToken inst,
644bf215546Sopenharmony_ci           SVGA3dShaderDestToken dest,
645bf215546Sopenharmony_ci           struct src_register src0,
646bf215546Sopenharmony_ci           struct src_register src1,
647bf215546Sopenharmony_ci           struct src_register src2,
648bf215546Sopenharmony_ci           struct src_register src3)
649bf215546Sopenharmony_ci{
650bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp0;
651bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp3;
652bf215546Sopenharmony_ci   boolean need_temp0 = FALSE;
653bf215546Sopenharmony_ci   boolean need_temp3 = FALSE;
654bf215546Sopenharmony_ci   SVGA3dShaderRegType type0, type1, type2, type3;
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci   temp0.value = 0;
657bf215546Sopenharmony_ci   temp3.value = 0;
658bf215546Sopenharmony_ci   type0 = SVGA3dShaderGetRegType( src0.base.value );
659bf215546Sopenharmony_ci   type1 = SVGA3dShaderGetRegType( src1.base.value );
660bf215546Sopenharmony_ci   type2 = SVGA3dShaderGetRegType( src2.base.value );
661bf215546Sopenharmony_ci   type3 = SVGA3dShaderGetRegType( src2.base.value );
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci   /* Make life a little easier - this is only used by the TXD
664bf215546Sopenharmony_ci    * instruction which is guaranteed not to have a constant/input reg
665bf215546Sopenharmony_ci    * in one slot at least:
666bf215546Sopenharmony_ci    */
667bf215546Sopenharmony_ci   assert(type1 == SVGA3DREG_SAMPLER);
668bf215546Sopenharmony_ci   (void) type1;
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci   if (type0 == SVGA3DREG_CONST &&
671bf215546Sopenharmony_ci       ((type3 == SVGA3DREG_CONST && src0.base.num != src3.base.num) ||
672bf215546Sopenharmony_ci        (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num)))
673bf215546Sopenharmony_ci      need_temp0 = TRUE;
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci   if (type3 == SVGA3DREG_CONST &&
676bf215546Sopenharmony_ci       (type2 == SVGA3DREG_CONST && src3.base.num != src2.base.num))
677bf215546Sopenharmony_ci      need_temp3 = TRUE;
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   if (type0 == SVGA3DREG_INPUT &&
680bf215546Sopenharmony_ci       ((type3 == SVGA3DREG_INPUT && src0.base.num != src3.base.num) ||
681bf215546Sopenharmony_ci        (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num)))
682bf215546Sopenharmony_ci      need_temp0 = TRUE;
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_ci   if (type3 == SVGA3DREG_INPUT &&
685bf215546Sopenharmony_ci       (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num))
686bf215546Sopenharmony_ci      need_temp3 = TRUE;
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci   if (need_temp0) {
689bf215546Sopenharmony_ci      temp0 = get_temp( emit );
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci      if (!emit_repl( emit, temp0, &src0 ))
692bf215546Sopenharmony_ci         return FALSE;
693bf215546Sopenharmony_ci   }
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci   if (need_temp3) {
696bf215546Sopenharmony_ci      temp3 = get_temp( emit );
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci      if (!emit_repl( emit, temp3, &src3 ))
699bf215546Sopenharmony_ci         return FALSE;
700bf215546Sopenharmony_ci   }
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ci   if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 ))
703bf215546Sopenharmony_ci      return FALSE;
704bf215546Sopenharmony_ci
705bf215546Sopenharmony_ci   if (need_temp3)
706bf215546Sopenharmony_ci      release_temp( emit, temp3 );
707bf215546Sopenharmony_ci   if (need_temp0)
708bf215546Sopenharmony_ci      release_temp( emit, temp0 );
709bf215546Sopenharmony_ci   return TRUE;
710bf215546Sopenharmony_ci}
711bf215546Sopenharmony_ci
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci/**
714bf215546Sopenharmony_ci * Do the src and dest registers refer to the same register?
715bf215546Sopenharmony_ci */
716bf215546Sopenharmony_cistatic boolean
717bf215546Sopenharmony_cialias_src_dst(struct src_register src,
718bf215546Sopenharmony_ci              SVGA3dShaderDestToken dst)
719bf215546Sopenharmony_ci{
720bf215546Sopenharmony_ci   if (src.base.num != dst.num)
721bf215546Sopenharmony_ci      return FALSE;
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci   if (SVGA3dShaderGetRegType(dst.value) !=
724bf215546Sopenharmony_ci       SVGA3dShaderGetRegType(src.base.value))
725bf215546Sopenharmony_ci      return FALSE;
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci   return TRUE;
728bf215546Sopenharmony_ci}
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci
731bf215546Sopenharmony_ci/**
732bf215546Sopenharmony_ci * Helper for emitting SVGA immediate values using the SVGA3DOP_DEF[I]
733bf215546Sopenharmony_ci * instructions.
734bf215546Sopenharmony_ci */
735bf215546Sopenharmony_cistatic boolean
736bf215546Sopenharmony_ciemit_def_const(struct svga_shader_emitter *emit,
737bf215546Sopenharmony_ci               SVGA3dShaderConstType type,
738bf215546Sopenharmony_ci               unsigned idx, float a, float b, float c, float d)
739bf215546Sopenharmony_ci{
740bf215546Sopenharmony_ci   SVGA3DOpDefArgs def;
741bf215546Sopenharmony_ci   SVGA3dShaderInstToken opcode;
742bf215546Sopenharmony_ci
743bf215546Sopenharmony_ci   switch (type) {
744bf215546Sopenharmony_ci   case SVGA3D_CONST_TYPE_FLOAT:
745bf215546Sopenharmony_ci      opcode = inst_token( SVGA3DOP_DEF );
746bf215546Sopenharmony_ci      def.dst = dst_register( SVGA3DREG_CONST, idx );
747bf215546Sopenharmony_ci      def.constValues[0] = a;
748bf215546Sopenharmony_ci      def.constValues[1] = b;
749bf215546Sopenharmony_ci      def.constValues[2] = c;
750bf215546Sopenharmony_ci      def.constValues[3] = d;
751bf215546Sopenharmony_ci      break;
752bf215546Sopenharmony_ci   case SVGA3D_CONST_TYPE_INT:
753bf215546Sopenharmony_ci      opcode = inst_token( SVGA3DOP_DEFI );
754bf215546Sopenharmony_ci      def.dst = dst_register( SVGA3DREG_CONSTINT, idx );
755bf215546Sopenharmony_ci      def.constIValues[0] = (int)a;
756bf215546Sopenharmony_ci      def.constIValues[1] = (int)b;
757bf215546Sopenharmony_ci      def.constIValues[2] = (int)c;
758bf215546Sopenharmony_ci      def.constIValues[3] = (int)d;
759bf215546Sopenharmony_ci      break;
760bf215546Sopenharmony_ci   default:
761bf215546Sopenharmony_ci      assert(0);
762bf215546Sopenharmony_ci      opcode = inst_token( SVGA3DOP_NOP );
763bf215546Sopenharmony_ci      break;
764bf215546Sopenharmony_ci   }
765bf215546Sopenharmony_ci
766bf215546Sopenharmony_ci   if (!emit_instruction(emit, opcode) ||
767bf215546Sopenharmony_ci       !svga_shader_emit_dwords( emit, def.values, ARRAY_SIZE(def.values)))
768bf215546Sopenharmony_ci      return FALSE;
769bf215546Sopenharmony_ci
770bf215546Sopenharmony_ci   return TRUE;
771bf215546Sopenharmony_ci}
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_ci
774bf215546Sopenharmony_cistatic boolean
775bf215546Sopenharmony_cicreate_loop_const( struct svga_shader_emitter *emit )
776bf215546Sopenharmony_ci{
777bf215546Sopenharmony_ci   unsigned idx = emit->nr_hw_int_const++;
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_ci   if (!emit_def_const( emit, SVGA3D_CONST_TYPE_INT, idx,
780bf215546Sopenharmony_ci                        255, /* iteration count */
781bf215546Sopenharmony_ci                        0, /* initial value */
782bf215546Sopenharmony_ci                        1, /* step size */
783bf215546Sopenharmony_ci                        0 /* not used, must be 0 */))
784bf215546Sopenharmony_ci      return FALSE;
785bf215546Sopenharmony_ci
786bf215546Sopenharmony_ci   emit->loop_const_idx = idx;
787bf215546Sopenharmony_ci   emit->created_loop_const = TRUE;
788bf215546Sopenharmony_ci
789bf215546Sopenharmony_ci   return TRUE;
790bf215546Sopenharmony_ci}
791bf215546Sopenharmony_ci
792bf215546Sopenharmony_cistatic boolean
793bf215546Sopenharmony_cicreate_arl_consts( struct svga_shader_emitter *emit )
794bf215546Sopenharmony_ci{
795bf215546Sopenharmony_ci   int i;
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci   for (i = 0; i < emit->num_arl_consts; i += 4) {
798bf215546Sopenharmony_ci      int j;
799bf215546Sopenharmony_ci      unsigned idx = emit->nr_hw_float_const++;
800bf215546Sopenharmony_ci      float vals[4];
801bf215546Sopenharmony_ci      for (j = 0; j < 4 && (j + i) < emit->num_arl_consts; ++j) {
802bf215546Sopenharmony_ci         vals[j] = (float) emit->arl_consts[i + j].number;
803bf215546Sopenharmony_ci         emit->arl_consts[i + j].idx = idx;
804bf215546Sopenharmony_ci         switch (j) {
805bf215546Sopenharmony_ci         case 0:
806bf215546Sopenharmony_ci            emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_X;
807bf215546Sopenharmony_ci            break;
808bf215546Sopenharmony_ci         case 1:
809bf215546Sopenharmony_ci            emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_Y;
810bf215546Sopenharmony_ci            break;
811bf215546Sopenharmony_ci         case 2:
812bf215546Sopenharmony_ci            emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_Z;
813bf215546Sopenharmony_ci            break;
814bf215546Sopenharmony_ci         case 3:
815bf215546Sopenharmony_ci            emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_W;
816bf215546Sopenharmony_ci            break;
817bf215546Sopenharmony_ci         }
818bf215546Sopenharmony_ci      }
819bf215546Sopenharmony_ci      while (j < 4)
820bf215546Sopenharmony_ci         vals[j++] = 0;
821bf215546Sopenharmony_ci
822bf215546Sopenharmony_ci      if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT, idx,
823bf215546Sopenharmony_ci                           vals[0], vals[1],
824bf215546Sopenharmony_ci                           vals[2], vals[3]))
825bf215546Sopenharmony_ci         return FALSE;
826bf215546Sopenharmony_ci   }
827bf215546Sopenharmony_ci
828bf215546Sopenharmony_ci   return TRUE;
829bf215546Sopenharmony_ci}
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci/**
833bf215546Sopenharmony_ci * Return the register which holds the pixel shaders front/back-
834bf215546Sopenharmony_ci * facing value.
835bf215546Sopenharmony_ci */
836bf215546Sopenharmony_cistatic struct src_register
837bf215546Sopenharmony_ciget_vface( struct svga_shader_emitter *emit )
838bf215546Sopenharmony_ci{
839bf215546Sopenharmony_ci   assert(emit->emitted_vface);
840bf215546Sopenharmony_ci   return src_register(SVGA3DREG_MISCTYPE, SVGA3DMISCREG_FACE);
841bf215546Sopenharmony_ci}
842bf215546Sopenharmony_ci
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ci/**
845bf215546Sopenharmony_ci * Create/emit a "common" constant with values {0, 0.5, -1, 1}.
846bf215546Sopenharmony_ci * We can swizzle this to produce other useful constants such as
847bf215546Sopenharmony_ci * {0, 0, 0, 0}, {1, 1, 1, 1}, etc.
848bf215546Sopenharmony_ci */
849bf215546Sopenharmony_cistatic boolean
850bf215546Sopenharmony_cicreate_common_immediate( struct svga_shader_emitter *emit )
851bf215546Sopenharmony_ci{
852bf215546Sopenharmony_ci   unsigned idx = emit->nr_hw_float_const++;
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci   /* Emit the constant (0, 0.5, -1, 1) and use swizzling to generate
855bf215546Sopenharmony_ci    * other useful vectors.
856bf215546Sopenharmony_ci    */
857bf215546Sopenharmony_ci   if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT,
858bf215546Sopenharmony_ci                        idx, 0.0f, 0.5f, -1.0f, 1.0f ))
859bf215546Sopenharmony_ci      return FALSE;
860bf215546Sopenharmony_ci   emit->common_immediate_idx[0] = idx;
861bf215546Sopenharmony_ci   idx++;
862bf215546Sopenharmony_ci
863bf215546Sopenharmony_ci   /* Emit constant {2, 0, 0, 0} (only the 2 is used for now) */
864bf215546Sopenharmony_ci   if (emit->key.vs.adjust_attrib_range) {
865bf215546Sopenharmony_ci      if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT,
866bf215546Sopenharmony_ci                           idx, 2.0f, 0.0f, 0.0f, 0.0f ))
867bf215546Sopenharmony_ci         return FALSE;
868bf215546Sopenharmony_ci      emit->common_immediate_idx[1] = idx;
869bf215546Sopenharmony_ci   }
870bf215546Sopenharmony_ci   else {
871bf215546Sopenharmony_ci      emit->common_immediate_idx[1] = -1;
872bf215546Sopenharmony_ci   }
873bf215546Sopenharmony_ci
874bf215546Sopenharmony_ci   emit->created_common_immediate = TRUE;
875bf215546Sopenharmony_ci
876bf215546Sopenharmony_ci   return TRUE;
877bf215546Sopenharmony_ci}
878bf215546Sopenharmony_ci
879bf215546Sopenharmony_ci
880bf215546Sopenharmony_ci/**
881bf215546Sopenharmony_ci * Return swizzle/position for the given value in the "common" immediate.
882bf215546Sopenharmony_ci */
883bf215546Sopenharmony_cistatic inline unsigned
884bf215546Sopenharmony_cicommon_immediate_swizzle(float value)
885bf215546Sopenharmony_ci{
886bf215546Sopenharmony_ci   if (value == 0.0f)
887bf215546Sopenharmony_ci      return TGSI_SWIZZLE_X;
888bf215546Sopenharmony_ci   else if (value == 0.5f)
889bf215546Sopenharmony_ci      return TGSI_SWIZZLE_Y;
890bf215546Sopenharmony_ci   else if (value == -1.0f)
891bf215546Sopenharmony_ci      return TGSI_SWIZZLE_Z;
892bf215546Sopenharmony_ci   else if (value == 1.0f)
893bf215546Sopenharmony_ci      return TGSI_SWIZZLE_W;
894bf215546Sopenharmony_ci   else {
895bf215546Sopenharmony_ci      assert(!"illegal value in common_immediate_swizzle");
896bf215546Sopenharmony_ci      return TGSI_SWIZZLE_X;
897bf215546Sopenharmony_ci   }
898bf215546Sopenharmony_ci}
899bf215546Sopenharmony_ci
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci/**
902bf215546Sopenharmony_ci * Returns an immediate reg where all the terms are either 0, 1, 2 or 0.5
903bf215546Sopenharmony_ci */
904bf215546Sopenharmony_cistatic struct src_register
905bf215546Sopenharmony_ciget_immediate(struct svga_shader_emitter *emit,
906bf215546Sopenharmony_ci              float x, float y, float z, float w)
907bf215546Sopenharmony_ci{
908bf215546Sopenharmony_ci   unsigned sx = common_immediate_swizzle(x);
909bf215546Sopenharmony_ci   unsigned sy = common_immediate_swizzle(y);
910bf215546Sopenharmony_ci   unsigned sz = common_immediate_swizzle(z);
911bf215546Sopenharmony_ci   unsigned sw = common_immediate_swizzle(w);
912bf215546Sopenharmony_ci   assert(emit->created_common_immediate);
913bf215546Sopenharmony_ci   assert(emit->common_immediate_idx[0] >= 0);
914bf215546Sopenharmony_ci   return swizzle(src_register(SVGA3DREG_CONST, emit->common_immediate_idx[0]),
915bf215546Sopenharmony_ci                  sx, sy, sz, sw);
916bf215546Sopenharmony_ci}
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci
919bf215546Sopenharmony_ci/**
920bf215546Sopenharmony_ci * returns {0, 0, 0, 0} immediate
921bf215546Sopenharmony_ci */
922bf215546Sopenharmony_cistatic struct src_register
923bf215546Sopenharmony_ciget_zero_immediate( struct svga_shader_emitter *emit )
924bf215546Sopenharmony_ci{
925bf215546Sopenharmony_ci   assert(emit->created_common_immediate);
926bf215546Sopenharmony_ci   assert(emit->common_immediate_idx[0] >= 0);
927bf215546Sopenharmony_ci   return swizzle(src_register( SVGA3DREG_CONST,
928bf215546Sopenharmony_ci                                emit->common_immediate_idx[0]),
929bf215546Sopenharmony_ci                  0, 0, 0, 0);
930bf215546Sopenharmony_ci}
931bf215546Sopenharmony_ci
932bf215546Sopenharmony_ci
933bf215546Sopenharmony_ci/**
934bf215546Sopenharmony_ci * returns {1, 1, 1, 1} immediate
935bf215546Sopenharmony_ci */
936bf215546Sopenharmony_cistatic struct src_register
937bf215546Sopenharmony_ciget_one_immediate( struct svga_shader_emitter *emit )
938bf215546Sopenharmony_ci{
939bf215546Sopenharmony_ci   assert(emit->created_common_immediate);
940bf215546Sopenharmony_ci   assert(emit->common_immediate_idx[0] >= 0);
941bf215546Sopenharmony_ci   return swizzle(src_register( SVGA3DREG_CONST,
942bf215546Sopenharmony_ci                                emit->common_immediate_idx[0]),
943bf215546Sopenharmony_ci                  3, 3, 3, 3);
944bf215546Sopenharmony_ci}
945bf215546Sopenharmony_ci
946bf215546Sopenharmony_ci
947bf215546Sopenharmony_ci/**
948bf215546Sopenharmony_ci * returns {0.5, 0.5, 0.5, 0.5} immediate
949bf215546Sopenharmony_ci */
950bf215546Sopenharmony_cistatic struct src_register
951bf215546Sopenharmony_ciget_half_immediate( struct svga_shader_emitter *emit )
952bf215546Sopenharmony_ci{
953bf215546Sopenharmony_ci   assert(emit->created_common_immediate);
954bf215546Sopenharmony_ci   assert(emit->common_immediate_idx[0] >= 0);
955bf215546Sopenharmony_ci   return swizzle(src_register(SVGA3DREG_CONST, emit->common_immediate_idx[0]),
956bf215546Sopenharmony_ci                  1, 1, 1, 1);
957bf215546Sopenharmony_ci}
958bf215546Sopenharmony_ci
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_ci/**
961bf215546Sopenharmony_ci * returns {2, 2, 2, 2} immediate
962bf215546Sopenharmony_ci */
963bf215546Sopenharmony_cistatic struct src_register
964bf215546Sopenharmony_ciget_two_immediate( struct svga_shader_emitter *emit )
965bf215546Sopenharmony_ci{
966bf215546Sopenharmony_ci   /* Note we use the second common immediate here */
967bf215546Sopenharmony_ci   assert(emit->created_common_immediate);
968bf215546Sopenharmony_ci   assert(emit->common_immediate_idx[1] >= 0);
969bf215546Sopenharmony_ci   return swizzle(src_register( SVGA3DREG_CONST,
970bf215546Sopenharmony_ci                                emit->common_immediate_idx[1]),
971bf215546Sopenharmony_ci                  0, 0, 0, 0);
972bf215546Sopenharmony_ci}
973bf215546Sopenharmony_ci
974bf215546Sopenharmony_ci
975bf215546Sopenharmony_ci/**
976bf215546Sopenharmony_ci * returns the loop const
977bf215546Sopenharmony_ci */
978bf215546Sopenharmony_cistatic struct src_register
979bf215546Sopenharmony_ciget_loop_const( struct svga_shader_emitter *emit )
980bf215546Sopenharmony_ci{
981bf215546Sopenharmony_ci   assert(emit->created_loop_const);
982bf215546Sopenharmony_ci   assert(emit->loop_const_idx >= 0);
983bf215546Sopenharmony_ci   return src_register( SVGA3DREG_CONSTINT,
984bf215546Sopenharmony_ci                        emit->loop_const_idx );
985bf215546Sopenharmony_ci}
986bf215546Sopenharmony_ci
987bf215546Sopenharmony_ci
988bf215546Sopenharmony_cistatic struct src_register
989bf215546Sopenharmony_ciget_fake_arl_const( struct svga_shader_emitter *emit )
990bf215546Sopenharmony_ci{
991bf215546Sopenharmony_ci   struct src_register reg;
992bf215546Sopenharmony_ci   int idx = 0, swizzle = 0, i;
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_ci   for (i = 0; i < emit->num_arl_consts; ++ i) {
995bf215546Sopenharmony_ci      if (emit->arl_consts[i].arl_num == emit->current_arl) {
996bf215546Sopenharmony_ci         idx = emit->arl_consts[i].idx;
997bf215546Sopenharmony_ci         swizzle = emit->arl_consts[i].swizzle;
998bf215546Sopenharmony_ci      }
999bf215546Sopenharmony_ci   }
1000bf215546Sopenharmony_ci
1001bf215546Sopenharmony_ci   reg = src_register( SVGA3DREG_CONST, idx );
1002bf215546Sopenharmony_ci   return scalar(reg, swizzle);
1003bf215546Sopenharmony_ci}
1004bf215546Sopenharmony_ci
1005bf215546Sopenharmony_ci
1006bf215546Sopenharmony_ci/**
1007bf215546Sopenharmony_ci * Return a register which holds the width and height of the texture
1008bf215546Sopenharmony_ci * currently bound to the given sampler.
1009bf215546Sopenharmony_ci */
1010bf215546Sopenharmony_cistatic struct src_register
1011bf215546Sopenharmony_ciget_tex_dimensions( struct svga_shader_emitter *emit, int sampler_num )
1012bf215546Sopenharmony_ci{
1013bf215546Sopenharmony_ci   int idx;
1014bf215546Sopenharmony_ci   struct src_register reg;
1015bf215546Sopenharmony_ci
1016bf215546Sopenharmony_ci   /* the width/height indexes start right after constants */
1017bf215546Sopenharmony_ci   idx = emit->key.tex[sampler_num].width_height_idx +
1018bf215546Sopenharmony_ci         emit->info.file_max[TGSI_FILE_CONSTANT] + 1;
1019bf215546Sopenharmony_ci
1020bf215546Sopenharmony_ci   reg = src_register( SVGA3DREG_CONST, idx );
1021bf215546Sopenharmony_ci   return reg;
1022bf215546Sopenharmony_ci}
1023bf215546Sopenharmony_ci
1024bf215546Sopenharmony_ci
1025bf215546Sopenharmony_cistatic boolean
1026bf215546Sopenharmony_ciemit_fake_arl(struct svga_shader_emitter *emit,
1027bf215546Sopenharmony_ci              const struct tgsi_full_instruction *insn)
1028bf215546Sopenharmony_ci{
1029bf215546Sopenharmony_ci   const struct src_register src0 =
1030bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
1031bf215546Sopenharmony_ci   struct src_register src1 = get_fake_arl_const( emit );
1032bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1033bf215546Sopenharmony_ci   SVGA3dShaderDestToken tmp = get_temp( emit );
1034bf215546Sopenharmony_ci
1035bf215546Sopenharmony_ci   if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), tmp, src0))
1036bf215546Sopenharmony_ci      return FALSE;
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci   if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), tmp, src( tmp ),
1039bf215546Sopenharmony_ci                    src1))
1040bf215546Sopenharmony_ci      return FALSE;
1041bf215546Sopenharmony_ci
1042bf215546Sopenharmony_ci   /* replicate the original swizzle */
1043bf215546Sopenharmony_ci   src1 = src(tmp);
1044bf215546Sopenharmony_ci   src1.base.swizzle = src0.base.swizzle;
1045bf215546Sopenharmony_ci
1046bf215546Sopenharmony_ci   return submit_op1( emit, inst_token( SVGA3DOP_MOVA ),
1047bf215546Sopenharmony_ci                      dst, src1 );
1048bf215546Sopenharmony_ci}
1049bf215546Sopenharmony_ci
1050bf215546Sopenharmony_ci
1051bf215546Sopenharmony_cistatic boolean
1052bf215546Sopenharmony_ciemit_if(struct svga_shader_emitter *emit,
1053bf215546Sopenharmony_ci        const struct tgsi_full_instruction *insn)
1054bf215546Sopenharmony_ci{
1055bf215546Sopenharmony_ci   struct src_register src0 =
1056bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0]);
1057bf215546Sopenharmony_ci   struct src_register zero = get_zero_immediate(emit);
1058bf215546Sopenharmony_ci   SVGA3dShaderInstToken if_token = inst_token( SVGA3DOP_IFC );
1059bf215546Sopenharmony_ci
1060bf215546Sopenharmony_ci   if_token.control = SVGA3DOPCOMPC_NE;
1061bf215546Sopenharmony_ci
1062bf215546Sopenharmony_ci   if (SVGA3dShaderGetRegType(src0.base.value) == SVGA3DREG_CONST) {
1063bf215546Sopenharmony_ci      /*
1064bf215546Sopenharmony_ci       * Max different constant registers readable per IFC instruction is 1.
1065bf215546Sopenharmony_ci       */
1066bf215546Sopenharmony_ci      SVGA3dShaderDestToken tmp = get_temp( emit );
1067bf215546Sopenharmony_ci
1068bf215546Sopenharmony_ci      if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), tmp, src0))
1069bf215546Sopenharmony_ci         return FALSE;
1070bf215546Sopenharmony_ci
1071bf215546Sopenharmony_ci      src0 = scalar(src( tmp ), TGSI_SWIZZLE_X);
1072bf215546Sopenharmony_ci   }
1073bf215546Sopenharmony_ci
1074bf215546Sopenharmony_ci   emit->dynamic_branching_level++;
1075bf215546Sopenharmony_ci
1076bf215546Sopenharmony_ci   return (emit_instruction( emit, if_token ) &&
1077bf215546Sopenharmony_ci           emit_src( emit, src0 ) &&
1078bf215546Sopenharmony_ci           emit_src( emit, zero ) );
1079bf215546Sopenharmony_ci}
1080bf215546Sopenharmony_ci
1081bf215546Sopenharmony_ci
1082bf215546Sopenharmony_cistatic boolean
1083bf215546Sopenharmony_ciemit_else(struct svga_shader_emitter *emit,
1084bf215546Sopenharmony_ci          const struct tgsi_full_instruction *insn)
1085bf215546Sopenharmony_ci{
1086bf215546Sopenharmony_ci   return emit_instruction(emit, inst_token(SVGA3DOP_ELSE));
1087bf215546Sopenharmony_ci}
1088bf215546Sopenharmony_ci
1089bf215546Sopenharmony_ci
1090bf215546Sopenharmony_cistatic boolean
1091bf215546Sopenharmony_ciemit_endif(struct svga_shader_emitter *emit,
1092bf215546Sopenharmony_ci           const struct tgsi_full_instruction *insn)
1093bf215546Sopenharmony_ci{
1094bf215546Sopenharmony_ci   emit->dynamic_branching_level--;
1095bf215546Sopenharmony_ci
1096bf215546Sopenharmony_ci   return emit_instruction(emit, inst_token(SVGA3DOP_ENDIF));
1097bf215546Sopenharmony_ci}
1098bf215546Sopenharmony_ci
1099bf215546Sopenharmony_ci
1100bf215546Sopenharmony_ci/**
1101bf215546Sopenharmony_ci * Translate the following TGSI FLR instruction.
1102bf215546Sopenharmony_ci *    FLR  DST, SRC
1103bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence.
1104bf215546Sopenharmony_ci *    FRC  TMP, SRC
1105bf215546Sopenharmony_ci *    SUB  DST, SRC, TMP
1106bf215546Sopenharmony_ci */
1107bf215546Sopenharmony_cistatic boolean
1108bf215546Sopenharmony_ciemit_floor(struct svga_shader_emitter *emit,
1109bf215546Sopenharmony_ci           const struct tgsi_full_instruction *insn )
1110bf215546Sopenharmony_ci{
1111bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1112bf215546Sopenharmony_ci   const struct src_register src0 =
1113bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
1114bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp = get_temp( emit );
1115bf215546Sopenharmony_ci
1116bf215546Sopenharmony_ci   /* FRC  TMP, SRC */
1117bf215546Sopenharmony_ci   if (!submit_op1( emit, inst_token( SVGA3DOP_FRC ), temp, src0 ))
1118bf215546Sopenharmony_ci      return FALSE;
1119bf215546Sopenharmony_ci
1120bf215546Sopenharmony_ci   /* SUB  DST, SRC, TMP */
1121bf215546Sopenharmony_ci   if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, src0,
1122bf215546Sopenharmony_ci                    negate( src( temp ) ) ))
1123bf215546Sopenharmony_ci      return FALSE;
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_ci   return TRUE;
1126bf215546Sopenharmony_ci}
1127bf215546Sopenharmony_ci
1128bf215546Sopenharmony_ci
1129bf215546Sopenharmony_ci/**
1130bf215546Sopenharmony_ci * Translate the following TGSI CEIL instruction.
1131bf215546Sopenharmony_ci *    CEIL  DST, SRC
1132bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence.
1133bf215546Sopenharmony_ci *    FRC  TMP, -SRC
1134bf215546Sopenharmony_ci *    ADD  DST, SRC, TMP
1135bf215546Sopenharmony_ci */
1136bf215546Sopenharmony_cistatic boolean
1137bf215546Sopenharmony_ciemit_ceil(struct svga_shader_emitter *emit,
1138bf215546Sopenharmony_ci          const struct tgsi_full_instruction *insn)
1139bf215546Sopenharmony_ci{
1140bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register(emit, insn, 0);
1141bf215546Sopenharmony_ci   const struct src_register src0 =
1142bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0]);
1143bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp = get_temp(emit);
1144bf215546Sopenharmony_ci
1145bf215546Sopenharmony_ci   /* FRC  TMP, -SRC */
1146bf215546Sopenharmony_ci   if (!submit_op1(emit, inst_token(SVGA3DOP_FRC), temp, negate(src0)))
1147bf215546Sopenharmony_ci      return FALSE;
1148bf215546Sopenharmony_ci
1149bf215546Sopenharmony_ci   /* ADD DST, SRC, TMP */
1150bf215546Sopenharmony_ci   if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), dst, src0, src(temp)))
1151bf215546Sopenharmony_ci      return FALSE;
1152bf215546Sopenharmony_ci
1153bf215546Sopenharmony_ci   return TRUE;
1154bf215546Sopenharmony_ci}
1155bf215546Sopenharmony_ci
1156bf215546Sopenharmony_ci
1157bf215546Sopenharmony_ci/**
1158bf215546Sopenharmony_ci * Translate the following TGSI DIV instruction.
1159bf215546Sopenharmony_ci *    DIV  DST.xy, SRC0, SRC1
1160bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence.
1161bf215546Sopenharmony_ci *    RCP  TMP.x, SRC1.xxxx
1162bf215546Sopenharmony_ci *    RCP  TMP.y, SRC1.yyyy
1163bf215546Sopenharmony_ci *    MUL  DST.xy, SRC0, TMP
1164bf215546Sopenharmony_ci */
1165bf215546Sopenharmony_cistatic boolean
1166bf215546Sopenharmony_ciemit_div(struct svga_shader_emitter *emit,
1167bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn )
1168bf215546Sopenharmony_ci{
1169bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1170bf215546Sopenharmony_ci   const struct src_register src0 =
1171bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
1172bf215546Sopenharmony_ci   const struct src_register src1 =
1173bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[1] );
1174bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp = get_temp( emit );
1175bf215546Sopenharmony_ci   unsigned i;
1176bf215546Sopenharmony_ci
1177bf215546Sopenharmony_ci   /* For each enabled element, perform a RCP instruction.  Note that
1178bf215546Sopenharmony_ci    * RCP is scalar in SVGA3D:
1179bf215546Sopenharmony_ci    */
1180bf215546Sopenharmony_ci   for (i = 0; i < 4; i++) {
1181bf215546Sopenharmony_ci      unsigned channel = 1 << i;
1182bf215546Sopenharmony_ci      if (dst.mask & channel) {
1183bf215546Sopenharmony_ci         /* RCP  TMP.?, SRC1.???? */
1184bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ),
1185bf215546Sopenharmony_ci                          writemask(temp, channel),
1186bf215546Sopenharmony_ci                          scalar(src1, i) ))
1187bf215546Sopenharmony_ci            return FALSE;
1188bf215546Sopenharmony_ci      }
1189bf215546Sopenharmony_ci   }
1190bf215546Sopenharmony_ci
1191bf215546Sopenharmony_ci   /* Vector mul:
1192bf215546Sopenharmony_ci    * MUL  DST, SRC0, TMP
1193bf215546Sopenharmony_ci    */
1194bf215546Sopenharmony_ci   if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), dst, src0,
1195bf215546Sopenharmony_ci                    src( temp ) ))
1196bf215546Sopenharmony_ci      return FALSE;
1197bf215546Sopenharmony_ci
1198bf215546Sopenharmony_ci   return TRUE;
1199bf215546Sopenharmony_ci}
1200bf215546Sopenharmony_ci
1201bf215546Sopenharmony_ci
1202bf215546Sopenharmony_ci/**
1203bf215546Sopenharmony_ci * Translate the following TGSI DP2 instruction.
1204bf215546Sopenharmony_ci *    DP2  DST, SRC1, SRC2
1205bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence.
1206bf215546Sopenharmony_ci *    MUL  TMP, SRC1, SRC2
1207bf215546Sopenharmony_ci *    ADD  DST, TMP.xxxx, TMP.yyyy
1208bf215546Sopenharmony_ci */
1209bf215546Sopenharmony_cistatic boolean
1210bf215546Sopenharmony_ciemit_dp2(struct svga_shader_emitter *emit,
1211bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn )
1212bf215546Sopenharmony_ci{
1213bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1214bf215546Sopenharmony_ci   const struct src_register src0 =
1215bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0]);
1216bf215546Sopenharmony_ci   const struct src_register src1 =
1217bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[1]);
1218bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp = get_temp( emit );
1219bf215546Sopenharmony_ci   struct src_register temp_src0, temp_src1;
1220bf215546Sopenharmony_ci
1221bf215546Sopenharmony_ci   /* MUL  TMP, SRC1, SRC2 */
1222bf215546Sopenharmony_ci   if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), temp, src0, src1 ))
1223bf215546Sopenharmony_ci      return FALSE;
1224bf215546Sopenharmony_ci
1225bf215546Sopenharmony_ci   temp_src0 = scalar(src( temp ), TGSI_SWIZZLE_X);
1226bf215546Sopenharmony_ci   temp_src1 = scalar(src( temp ), TGSI_SWIZZLE_Y);
1227bf215546Sopenharmony_ci
1228bf215546Sopenharmony_ci   /* ADD  DST, TMP.xxxx, TMP.yyyy */
1229bf215546Sopenharmony_ci   if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst,
1230bf215546Sopenharmony_ci                    temp_src0, temp_src1 ))
1231bf215546Sopenharmony_ci      return FALSE;
1232bf215546Sopenharmony_ci
1233bf215546Sopenharmony_ci   return TRUE;
1234bf215546Sopenharmony_ci}
1235bf215546Sopenharmony_ci
1236bf215546Sopenharmony_ci
1237bf215546Sopenharmony_ci/**
1238bf215546Sopenharmony_ci * Sine / Cosine helper function.
1239bf215546Sopenharmony_ci */
1240bf215546Sopenharmony_cistatic boolean
1241bf215546Sopenharmony_cido_emit_sincos(struct svga_shader_emitter *emit,
1242bf215546Sopenharmony_ci               SVGA3dShaderDestToken dst,
1243bf215546Sopenharmony_ci               struct src_register src0)
1244bf215546Sopenharmony_ci{
1245bf215546Sopenharmony_ci   src0 = scalar(src0, TGSI_SWIZZLE_X);
1246bf215546Sopenharmony_ci   return submit_op1(emit, inst_token(SVGA3DOP_SINCOS), dst, src0);
1247bf215546Sopenharmony_ci}
1248bf215546Sopenharmony_ci
1249bf215546Sopenharmony_ci
1250bf215546Sopenharmony_ci/**
1251bf215546Sopenharmony_ci * Translate TGSI SIN instruction into:
1252bf215546Sopenharmony_ci * SCS TMP SRC
1253bf215546Sopenharmony_ci * MOV DST TMP.yyyy
1254bf215546Sopenharmony_ci */
1255bf215546Sopenharmony_cistatic boolean
1256bf215546Sopenharmony_ciemit_sin(struct svga_shader_emitter *emit,
1257bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn )
1258bf215546Sopenharmony_ci{
1259bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1260bf215546Sopenharmony_ci   struct src_register src0 =
1261bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
1262bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp = get_temp( emit );
1263bf215546Sopenharmony_ci
1264bf215546Sopenharmony_ci   /* SCS TMP SRC */
1265bf215546Sopenharmony_ci   if (!do_emit_sincos(emit, writemask(temp, TGSI_WRITEMASK_Y), src0))
1266bf215546Sopenharmony_ci      return FALSE;
1267bf215546Sopenharmony_ci
1268bf215546Sopenharmony_ci   src0 = scalar(src( temp ), TGSI_SWIZZLE_Y);
1269bf215546Sopenharmony_ci
1270bf215546Sopenharmony_ci   /* MOV DST TMP.yyyy */
1271bf215546Sopenharmony_ci   if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src0 ))
1272bf215546Sopenharmony_ci      return FALSE;
1273bf215546Sopenharmony_ci
1274bf215546Sopenharmony_ci   return TRUE;
1275bf215546Sopenharmony_ci}
1276bf215546Sopenharmony_ci
1277bf215546Sopenharmony_ci
1278bf215546Sopenharmony_ci/*
1279bf215546Sopenharmony_ci * Translate TGSI COS instruction into:
1280bf215546Sopenharmony_ci * SCS TMP SRC
1281bf215546Sopenharmony_ci * MOV DST TMP.xxxx
1282bf215546Sopenharmony_ci */
1283bf215546Sopenharmony_cistatic boolean
1284bf215546Sopenharmony_ciemit_cos(struct svga_shader_emitter *emit,
1285bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
1286bf215546Sopenharmony_ci{
1287bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1288bf215546Sopenharmony_ci   struct src_register src0 =
1289bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
1290bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp = get_temp( emit );
1291bf215546Sopenharmony_ci
1292bf215546Sopenharmony_ci   /* SCS TMP SRC */
1293bf215546Sopenharmony_ci   if (!do_emit_sincos( emit, writemask(temp, TGSI_WRITEMASK_X), src0 ))
1294bf215546Sopenharmony_ci      return FALSE;
1295bf215546Sopenharmony_ci
1296bf215546Sopenharmony_ci   src0 = scalar(src( temp ), TGSI_SWIZZLE_X);
1297bf215546Sopenharmony_ci
1298bf215546Sopenharmony_ci   /* MOV DST TMP.xxxx */
1299bf215546Sopenharmony_ci   if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src0 ))
1300bf215546Sopenharmony_ci      return FALSE;
1301bf215546Sopenharmony_ci
1302bf215546Sopenharmony_ci   return TRUE;
1303bf215546Sopenharmony_ci}
1304bf215546Sopenharmony_ci
1305bf215546Sopenharmony_ci
1306bf215546Sopenharmony_ci/**
1307bf215546Sopenharmony_ci * Translate/emit TGSI SSG (Set Sign: -1, 0, +1) instruction.
1308bf215546Sopenharmony_ci */
1309bf215546Sopenharmony_cistatic boolean
1310bf215546Sopenharmony_ciemit_ssg(struct svga_shader_emitter *emit,
1311bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
1312bf215546Sopenharmony_ci{
1313bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1314bf215546Sopenharmony_ci   struct src_register src0 =
1315bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
1316bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp0 = get_temp( emit );
1317bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp1 = get_temp( emit );
1318bf215546Sopenharmony_ci   struct src_register zero, one;
1319bf215546Sopenharmony_ci
1320bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
1321bf215546Sopenharmony_ci      /* SGN  DST, SRC0, TMP0, TMP1 */
1322bf215546Sopenharmony_ci      return submit_op3( emit, inst_token( SVGA3DOP_SGN ), dst, src0,
1323bf215546Sopenharmony_ci                         src( temp0 ), src( temp1 ) );
1324bf215546Sopenharmony_ci   }
1325bf215546Sopenharmony_ci
1326bf215546Sopenharmony_ci   one = get_one_immediate(emit);
1327bf215546Sopenharmony_ci   zero = get_zero_immediate(emit);
1328bf215546Sopenharmony_ci
1329bf215546Sopenharmony_ci   /* CMP  TMP0, SRC0, one, zero */
1330bf215546Sopenharmony_ci   if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ),
1331bf215546Sopenharmony_ci                    writemask( temp0, dst.mask ), src0, one, zero ))
1332bf215546Sopenharmony_ci      return FALSE;
1333bf215546Sopenharmony_ci
1334bf215546Sopenharmony_ci   /* CMP  TMP1, negate(SRC0), negate(one), zero */
1335bf215546Sopenharmony_ci   if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ),
1336bf215546Sopenharmony_ci                    writemask( temp1, dst.mask ), negate( src0 ), negate( one ),
1337bf215546Sopenharmony_ci                    zero ))
1338bf215546Sopenharmony_ci      return FALSE;
1339bf215546Sopenharmony_ci
1340bf215546Sopenharmony_ci   /* ADD  DST, TMP0, TMP1 */
1341bf215546Sopenharmony_ci   return submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, src( temp0 ),
1342bf215546Sopenharmony_ci                      src( temp1 ) );
1343bf215546Sopenharmony_ci}
1344bf215546Sopenharmony_ci
1345bf215546Sopenharmony_ci
1346bf215546Sopenharmony_ci/**
1347bf215546Sopenharmony_ci * Translate/emit the conditional discard instruction (discard if
1348bf215546Sopenharmony_ci * any of X,Y,Z,W are negative).
1349bf215546Sopenharmony_ci */
1350bf215546Sopenharmony_cistatic boolean
1351bf215546Sopenharmony_ciemit_cond_discard(struct svga_shader_emitter *emit,
1352bf215546Sopenharmony_ci                  const struct tgsi_full_instruction *insn)
1353bf215546Sopenharmony_ci{
1354bf215546Sopenharmony_ci   const struct tgsi_full_src_register *reg = &insn->Src[0];
1355bf215546Sopenharmony_ci   struct src_register src0, srcIn;
1356bf215546Sopenharmony_ci   const boolean special = (reg->Register.Absolute ||
1357bf215546Sopenharmony_ci                            reg->Register.Negate ||
1358bf215546Sopenharmony_ci                            reg->Register.Indirect ||
1359bf215546Sopenharmony_ci                            reg->Register.SwizzleX != 0 ||
1360bf215546Sopenharmony_ci                            reg->Register.SwizzleY != 1 ||
1361bf215546Sopenharmony_ci                            reg->Register.SwizzleZ != 2 ||
1362bf215546Sopenharmony_ci                            reg->Register.File != TGSI_FILE_TEMPORARY);
1363bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp;
1364bf215546Sopenharmony_ci
1365bf215546Sopenharmony_ci   src0 = srcIn = translate_src_register( emit, reg );
1366bf215546Sopenharmony_ci
1367bf215546Sopenharmony_ci   if (special) {
1368bf215546Sopenharmony_ci      /* need a temp reg */
1369bf215546Sopenharmony_ci      temp = get_temp( emit );
1370bf215546Sopenharmony_ci   }
1371bf215546Sopenharmony_ci
1372bf215546Sopenharmony_ci   if (special) {
1373bf215546Sopenharmony_ci      /* move the source into a temp register */
1374bf215546Sopenharmony_ci      submit_op1(emit, inst_token(SVGA3DOP_MOV), temp, src0);
1375bf215546Sopenharmony_ci
1376bf215546Sopenharmony_ci      src0 = src( temp );
1377bf215546Sopenharmony_ci   }
1378bf215546Sopenharmony_ci
1379bf215546Sopenharmony_ci   /* Do the discard by checking if any of the XYZW components are < 0.
1380bf215546Sopenharmony_ci    * Note that ps_2_0 and later take XYZW in consideration, while ps_1_x
1381bf215546Sopenharmony_ci    * only used XYZ.  The MSDN documentation about this is incorrect.
1382bf215546Sopenharmony_ci    */
1383bf215546Sopenharmony_ci   if (!submit_op0( emit, inst_token( SVGA3DOP_TEXKILL ), dst(src0) ))
1384bf215546Sopenharmony_ci      return FALSE;
1385bf215546Sopenharmony_ci
1386bf215546Sopenharmony_ci   return TRUE;
1387bf215546Sopenharmony_ci}
1388bf215546Sopenharmony_ci
1389bf215546Sopenharmony_ci
1390bf215546Sopenharmony_ci/**
1391bf215546Sopenharmony_ci * Translate/emit the unconditional discard instruction (usually found inside
1392bf215546Sopenharmony_ci * an IF/ELSE/ENDIF block).
1393bf215546Sopenharmony_ci */
1394bf215546Sopenharmony_cistatic boolean
1395bf215546Sopenharmony_ciemit_discard(struct svga_shader_emitter *emit,
1396bf215546Sopenharmony_ci             const struct tgsi_full_instruction *insn)
1397bf215546Sopenharmony_ci{
1398bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp;
1399bf215546Sopenharmony_ci   struct src_register one = get_one_immediate(emit);
1400bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_TEXKILL );
1401bf215546Sopenharmony_ci
1402bf215546Sopenharmony_ci   /* texkill doesn't allow negation on the operand so lets move
1403bf215546Sopenharmony_ci    * negation of {1} to a temp register */
1404bf215546Sopenharmony_ci   temp = get_temp( emit );
1405bf215546Sopenharmony_ci   if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), temp,
1406bf215546Sopenharmony_ci                    negate( one ) ))
1407bf215546Sopenharmony_ci      return FALSE;
1408bf215546Sopenharmony_ci
1409bf215546Sopenharmony_ci   return submit_op0( emit, inst, temp );
1410bf215546Sopenharmony_ci}
1411bf215546Sopenharmony_ci
1412bf215546Sopenharmony_ci
1413bf215546Sopenharmony_ci/**
1414bf215546Sopenharmony_ci * Test if r1 and r2 are the same register.
1415bf215546Sopenharmony_ci */
1416bf215546Sopenharmony_cistatic boolean
1417bf215546Sopenharmony_cisame_register(struct src_register r1, struct src_register r2)
1418bf215546Sopenharmony_ci{
1419bf215546Sopenharmony_ci   return (r1.base.num == r2.base.num &&
1420bf215546Sopenharmony_ci           r1.base.type_upper == r2.base.type_upper &&
1421bf215546Sopenharmony_ci           r1.base.type_lower == r2.base.type_lower);
1422bf215546Sopenharmony_ci}
1423bf215546Sopenharmony_ci
1424bf215546Sopenharmony_ci
1425bf215546Sopenharmony_ci
1426bf215546Sopenharmony_ci/**
1427bf215546Sopenharmony_ci * Implement conditionals by initializing destination reg to 'fail',
1428bf215546Sopenharmony_ci * then set predicate reg with UFOP_SETP, then move 'pass' to dest
1429bf215546Sopenharmony_ci * based on predicate reg.
1430bf215546Sopenharmony_ci *
1431bf215546Sopenharmony_ci * SETP src0, cmp, src1  -- do this first to avoid aliasing problems.
1432bf215546Sopenharmony_ci * MOV dst, fail
1433bf215546Sopenharmony_ci * MOV dst, pass, p0
1434bf215546Sopenharmony_ci */
1435bf215546Sopenharmony_cistatic boolean
1436bf215546Sopenharmony_ciemit_conditional(struct svga_shader_emitter *emit,
1437bf215546Sopenharmony_ci                 enum pipe_compare_func compare_func,
1438bf215546Sopenharmony_ci                 SVGA3dShaderDestToken dst,
1439bf215546Sopenharmony_ci                 struct src_register src0,
1440bf215546Sopenharmony_ci                 struct src_register src1,
1441bf215546Sopenharmony_ci                 struct src_register pass,
1442bf215546Sopenharmony_ci                 struct src_register fail)
1443bf215546Sopenharmony_ci{
1444bf215546Sopenharmony_ci   SVGA3dShaderDestToken pred_reg = dst_register( SVGA3DREG_PREDICATE, 0 );
1445bf215546Sopenharmony_ci   SVGA3dShaderInstToken setp_token;
1446bf215546Sopenharmony_ci
1447bf215546Sopenharmony_ci   switch (compare_func) {
1448bf215546Sopenharmony_ci   case PIPE_FUNC_NEVER:
1449bf215546Sopenharmony_ci      return submit_op1( emit, inst_token( SVGA3DOP_MOV ),
1450bf215546Sopenharmony_ci                         dst, fail );
1451bf215546Sopenharmony_ci      break;
1452bf215546Sopenharmony_ci   case PIPE_FUNC_LESS:
1453bf215546Sopenharmony_ci      setp_token = inst_token_setp(SVGA3DOPCOMP_LT);
1454bf215546Sopenharmony_ci      break;
1455bf215546Sopenharmony_ci   case PIPE_FUNC_EQUAL:
1456bf215546Sopenharmony_ci      setp_token = inst_token_setp(SVGA3DOPCOMP_EQ);
1457bf215546Sopenharmony_ci      break;
1458bf215546Sopenharmony_ci   case PIPE_FUNC_LEQUAL:
1459bf215546Sopenharmony_ci      setp_token = inst_token_setp(SVGA3DOPCOMP_LE);
1460bf215546Sopenharmony_ci      break;
1461bf215546Sopenharmony_ci   case PIPE_FUNC_GREATER:
1462bf215546Sopenharmony_ci      setp_token = inst_token_setp(SVGA3DOPCOMP_GT);
1463bf215546Sopenharmony_ci      break;
1464bf215546Sopenharmony_ci   case PIPE_FUNC_NOTEQUAL:
1465bf215546Sopenharmony_ci      setp_token = inst_token_setp(SVGA3DOPCOMPC_NE);
1466bf215546Sopenharmony_ci      break;
1467bf215546Sopenharmony_ci   case PIPE_FUNC_GEQUAL:
1468bf215546Sopenharmony_ci      setp_token = inst_token_setp(SVGA3DOPCOMP_GE);
1469bf215546Sopenharmony_ci      break;
1470bf215546Sopenharmony_ci   case PIPE_FUNC_ALWAYS:
1471bf215546Sopenharmony_ci      return submit_op1( emit, inst_token( SVGA3DOP_MOV ),
1472bf215546Sopenharmony_ci                         dst, pass );
1473bf215546Sopenharmony_ci      break;
1474bf215546Sopenharmony_ci   }
1475bf215546Sopenharmony_ci
1476bf215546Sopenharmony_ci   if (same_register(src(dst), pass)) {
1477bf215546Sopenharmony_ci      /* We'll get bad results if the dst and pass registers are the same
1478bf215546Sopenharmony_ci       * so use a temp register containing pass.
1479bf215546Sopenharmony_ci       */
1480bf215546Sopenharmony_ci      SVGA3dShaderDestToken temp = get_temp(emit);
1481bf215546Sopenharmony_ci      if (!submit_op1(emit, inst_token(SVGA3DOP_MOV), temp, pass))
1482bf215546Sopenharmony_ci         return FALSE;
1483bf215546Sopenharmony_ci      pass = src(temp);
1484bf215546Sopenharmony_ci   }
1485bf215546Sopenharmony_ci
1486bf215546Sopenharmony_ci   /* SETP src0, COMPOP, src1 */
1487bf215546Sopenharmony_ci   if (!submit_op2( emit, setp_token, pred_reg,
1488bf215546Sopenharmony_ci                    src0, src1 ))
1489bf215546Sopenharmony_ci      return FALSE;
1490bf215546Sopenharmony_ci
1491bf215546Sopenharmony_ci   /* MOV dst, fail */
1492bf215546Sopenharmony_ci   if (!submit_op1(emit, inst_token(SVGA3DOP_MOV), dst, fail))
1493bf215546Sopenharmony_ci      return FALSE;
1494bf215546Sopenharmony_ci
1495bf215546Sopenharmony_ci   /* MOV dst, pass (predicated)
1496bf215546Sopenharmony_ci    *
1497bf215546Sopenharmony_ci    * Note that the predicate reg (and possible modifiers) is passed
1498bf215546Sopenharmony_ci    * as the first source argument.
1499bf215546Sopenharmony_ci    */
1500bf215546Sopenharmony_ci   if (!submit_op2(emit,
1501bf215546Sopenharmony_ci                   inst_token_predicated(SVGA3DOP_MOV), dst,
1502bf215546Sopenharmony_ci                   src(pred_reg), pass))
1503bf215546Sopenharmony_ci      return FALSE;
1504bf215546Sopenharmony_ci
1505bf215546Sopenharmony_ci   return TRUE;
1506bf215546Sopenharmony_ci}
1507bf215546Sopenharmony_ci
1508bf215546Sopenharmony_ci
1509bf215546Sopenharmony_ci/**
1510bf215546Sopenharmony_ci * Helper for emiting 'selection' commands.  Basically:
1511bf215546Sopenharmony_ci * if (src0 OP src1)
1512bf215546Sopenharmony_ci *    dst = 1.0;
1513bf215546Sopenharmony_ci * else
1514bf215546Sopenharmony_ci *    dst = 0.0;
1515bf215546Sopenharmony_ci */
1516bf215546Sopenharmony_cistatic boolean
1517bf215546Sopenharmony_ciemit_select(struct svga_shader_emitter *emit,
1518bf215546Sopenharmony_ci            enum pipe_compare_func compare_func,
1519bf215546Sopenharmony_ci            SVGA3dShaderDestToken dst,
1520bf215546Sopenharmony_ci            struct src_register src0,
1521bf215546Sopenharmony_ci            struct src_register src1 )
1522bf215546Sopenharmony_ci{
1523bf215546Sopenharmony_ci   /* There are some SVGA instructions which implement some selects
1524bf215546Sopenharmony_ci    * directly, but they are only available in the vertex shader.
1525bf215546Sopenharmony_ci    */
1526bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
1527bf215546Sopenharmony_ci      switch (compare_func) {
1528bf215546Sopenharmony_ci      case PIPE_FUNC_GEQUAL:
1529bf215546Sopenharmony_ci         return submit_op2( emit, inst_token( SVGA3DOP_SGE ), dst, src0, src1 );
1530bf215546Sopenharmony_ci      case PIPE_FUNC_LEQUAL:
1531bf215546Sopenharmony_ci         return submit_op2( emit, inst_token( SVGA3DOP_SGE ), dst, src1, src0 );
1532bf215546Sopenharmony_ci      case PIPE_FUNC_GREATER:
1533bf215546Sopenharmony_ci         return submit_op2( emit, inst_token( SVGA3DOP_SLT ), dst, src1, src0 );
1534bf215546Sopenharmony_ci      case PIPE_FUNC_LESS:
1535bf215546Sopenharmony_ci         return submit_op2( emit, inst_token( SVGA3DOP_SLT ), dst, src0, src1 );
1536bf215546Sopenharmony_ci      default:
1537bf215546Sopenharmony_ci         break;
1538bf215546Sopenharmony_ci      }
1539bf215546Sopenharmony_ci   }
1540bf215546Sopenharmony_ci
1541bf215546Sopenharmony_ci   /* Otherwise, need to use the setp approach:
1542bf215546Sopenharmony_ci    */
1543bf215546Sopenharmony_ci   {
1544bf215546Sopenharmony_ci      struct src_register one, zero;
1545bf215546Sopenharmony_ci      /* zero immediate is 0,0,0,1 */
1546bf215546Sopenharmony_ci      zero = get_zero_immediate(emit);
1547bf215546Sopenharmony_ci      one = get_one_immediate(emit);
1548bf215546Sopenharmony_ci
1549bf215546Sopenharmony_ci      return emit_conditional(emit, compare_func, dst, src0, src1, one, zero);
1550bf215546Sopenharmony_ci   }
1551bf215546Sopenharmony_ci}
1552bf215546Sopenharmony_ci
1553bf215546Sopenharmony_ci
1554bf215546Sopenharmony_ci/**
1555bf215546Sopenharmony_ci * Translate/emit a TGSI SEQ, SNE, SLT, SGE, etc. instruction.
1556bf215546Sopenharmony_ci */
1557bf215546Sopenharmony_cistatic boolean
1558bf215546Sopenharmony_ciemit_select_op(struct svga_shader_emitter *emit,
1559bf215546Sopenharmony_ci               unsigned compare,
1560bf215546Sopenharmony_ci               const struct tgsi_full_instruction *insn)
1561bf215546Sopenharmony_ci{
1562bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1563bf215546Sopenharmony_ci   struct src_register src0 = translate_src_register(
1564bf215546Sopenharmony_ci      emit, &insn->Src[0] );
1565bf215546Sopenharmony_ci   struct src_register src1 = translate_src_register(
1566bf215546Sopenharmony_ci      emit, &insn->Src[1] );
1567bf215546Sopenharmony_ci
1568bf215546Sopenharmony_ci   return emit_select( emit, compare, dst, src0, src1 );
1569bf215546Sopenharmony_ci}
1570bf215546Sopenharmony_ci
1571bf215546Sopenharmony_ci
1572bf215546Sopenharmony_ci/**
1573bf215546Sopenharmony_ci * Translate TGSI CMP instruction.  Component-wise:
1574bf215546Sopenharmony_ci * dst = (src0 < 0.0) ? src1 : src2
1575bf215546Sopenharmony_ci */
1576bf215546Sopenharmony_cistatic boolean
1577bf215546Sopenharmony_ciemit_cmp(struct svga_shader_emitter *emit,
1578bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
1579bf215546Sopenharmony_ci{
1580bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
1581bf215546Sopenharmony_ci   const struct src_register src0 =
1582bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
1583bf215546Sopenharmony_ci   const struct src_register src1 =
1584bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[1] );
1585bf215546Sopenharmony_ci   const struct src_register src2 =
1586bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[2] );
1587bf215546Sopenharmony_ci
1588bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
1589bf215546Sopenharmony_ci      struct src_register zero = get_zero_immediate(emit);
1590bf215546Sopenharmony_ci      /* We used to simulate CMP with SLT+LRP.  But that didn't work when
1591bf215546Sopenharmony_ci       * src1 or src2 was Inf/NaN.  In particular, GLSL sqrt(0) failed
1592bf215546Sopenharmony_ci       * because it involves a CMP to handle the 0 case.
1593bf215546Sopenharmony_ci       * Use a conditional expression instead.
1594bf215546Sopenharmony_ci       */
1595bf215546Sopenharmony_ci      return emit_conditional(emit, PIPE_FUNC_LESS, dst,
1596bf215546Sopenharmony_ci                              src0, zero, src1, src2);
1597bf215546Sopenharmony_ci   }
1598bf215546Sopenharmony_ci   else {
1599bf215546Sopenharmony_ci      assert(emit->unit == PIPE_SHADER_FRAGMENT);
1600bf215546Sopenharmony_ci
1601bf215546Sopenharmony_ci      /* CMP  DST, SRC0, SRC2, SRC1 */
1602bf215546Sopenharmony_ci      return submit_op3( emit, inst_token( SVGA3DOP_CMP ), dst,
1603bf215546Sopenharmony_ci                         src0, src2, src1);
1604bf215546Sopenharmony_ci   }
1605bf215546Sopenharmony_ci}
1606bf215546Sopenharmony_ci
1607bf215546Sopenharmony_ci
1608bf215546Sopenharmony_ci/**
1609bf215546Sopenharmony_ci * Translate/emit 2-operand (coord, sampler) texture instructions.
1610bf215546Sopenharmony_ci */
1611bf215546Sopenharmony_cistatic boolean
1612bf215546Sopenharmony_ciemit_tex2(struct svga_shader_emitter *emit,
1613bf215546Sopenharmony_ci          const struct tgsi_full_instruction *insn,
1614bf215546Sopenharmony_ci          SVGA3dShaderDestToken dst)
1615bf215546Sopenharmony_ci{
1616bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst;
1617bf215546Sopenharmony_ci   struct src_register texcoord;
1618bf215546Sopenharmony_ci   struct src_register sampler;
1619bf215546Sopenharmony_ci   SVGA3dShaderDestToken tmp;
1620bf215546Sopenharmony_ci
1621bf215546Sopenharmony_ci   inst.value = 0;
1622bf215546Sopenharmony_ci
1623bf215546Sopenharmony_ci   switch (insn->Instruction.Opcode) {
1624bf215546Sopenharmony_ci   case TGSI_OPCODE_TEX:
1625bf215546Sopenharmony_ci      inst.op = SVGA3DOP_TEX;
1626bf215546Sopenharmony_ci      break;
1627bf215546Sopenharmony_ci   case TGSI_OPCODE_TXP:
1628bf215546Sopenharmony_ci      inst.op = SVGA3DOP_TEX;
1629bf215546Sopenharmony_ci      inst.control = SVGA3DOPCONT_PROJECT;
1630bf215546Sopenharmony_ci      break;
1631bf215546Sopenharmony_ci   case TGSI_OPCODE_TXB:
1632bf215546Sopenharmony_ci      inst.op = SVGA3DOP_TEX;
1633bf215546Sopenharmony_ci      inst.control = SVGA3DOPCONT_BIAS;
1634bf215546Sopenharmony_ci      break;
1635bf215546Sopenharmony_ci   case TGSI_OPCODE_TXL:
1636bf215546Sopenharmony_ci      inst.op = SVGA3DOP_TEXLDL;
1637bf215546Sopenharmony_ci      break;
1638bf215546Sopenharmony_ci   default:
1639bf215546Sopenharmony_ci      assert(0);
1640bf215546Sopenharmony_ci      return FALSE;
1641bf215546Sopenharmony_ci   }
1642bf215546Sopenharmony_ci
1643bf215546Sopenharmony_ci   texcoord = translate_src_register( emit, &insn->Src[0] );
1644bf215546Sopenharmony_ci   sampler = translate_src_register( emit, &insn->Src[1] );
1645bf215546Sopenharmony_ci
1646bf215546Sopenharmony_ci   if (emit->key.tex[sampler.base.num].unnormalized ||
1647bf215546Sopenharmony_ci       emit->dynamic_branching_level > 0)
1648bf215546Sopenharmony_ci      tmp = get_temp( emit );
1649bf215546Sopenharmony_ci
1650bf215546Sopenharmony_ci   /* Can't do mipmapping inside dynamic branch constructs.  Force LOD
1651bf215546Sopenharmony_ci    * zero in that case.
1652bf215546Sopenharmony_ci    */
1653bf215546Sopenharmony_ci   if (emit->dynamic_branching_level > 0 &&
1654bf215546Sopenharmony_ci       inst.op == SVGA3DOP_TEX &&
1655bf215546Sopenharmony_ci       SVGA3dShaderGetRegType(texcoord.base.value) == SVGA3DREG_TEMP) {
1656bf215546Sopenharmony_ci      struct src_register zero = get_zero_immediate(emit);
1657bf215546Sopenharmony_ci
1658bf215546Sopenharmony_ci      /* MOV  tmp, texcoord */
1659bf215546Sopenharmony_ci      if (!submit_op1( emit,
1660bf215546Sopenharmony_ci                       inst_token( SVGA3DOP_MOV ),
1661bf215546Sopenharmony_ci                       tmp,
1662bf215546Sopenharmony_ci                       texcoord ))
1663bf215546Sopenharmony_ci         return FALSE;
1664bf215546Sopenharmony_ci
1665bf215546Sopenharmony_ci      /* MOV  tmp.w, zero */
1666bf215546Sopenharmony_ci      if (!submit_op1( emit,
1667bf215546Sopenharmony_ci                       inst_token( SVGA3DOP_MOV ),
1668bf215546Sopenharmony_ci                       writemask( tmp, TGSI_WRITEMASK_W ),
1669bf215546Sopenharmony_ci                       zero ))
1670bf215546Sopenharmony_ci         return FALSE;
1671bf215546Sopenharmony_ci
1672bf215546Sopenharmony_ci      texcoord = src( tmp );
1673bf215546Sopenharmony_ci      inst.op = SVGA3DOP_TEXLDL;
1674bf215546Sopenharmony_ci   }
1675bf215546Sopenharmony_ci
1676bf215546Sopenharmony_ci   /* Explicit normalization of texcoords:
1677bf215546Sopenharmony_ci    */
1678bf215546Sopenharmony_ci   if (emit->key.tex[sampler.base.num].unnormalized) {
1679bf215546Sopenharmony_ci      struct src_register wh = get_tex_dimensions( emit, sampler.base.num );
1680bf215546Sopenharmony_ci
1681bf215546Sopenharmony_ci      /* MUL  tmp, SRC0, WH */
1682bf215546Sopenharmony_ci      if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ),
1683bf215546Sopenharmony_ci                       tmp, texcoord, wh ))
1684bf215546Sopenharmony_ci         return FALSE;
1685bf215546Sopenharmony_ci
1686bf215546Sopenharmony_ci      texcoord = src( tmp );
1687bf215546Sopenharmony_ci   }
1688bf215546Sopenharmony_ci
1689bf215546Sopenharmony_ci   return submit_op2( emit, inst, dst, texcoord, sampler );
1690bf215546Sopenharmony_ci}
1691bf215546Sopenharmony_ci
1692bf215546Sopenharmony_ci
1693bf215546Sopenharmony_ci/**
1694bf215546Sopenharmony_ci * Translate/emit 4-operand (coord, ddx, ddy, sampler) texture instructions.
1695bf215546Sopenharmony_ci */
1696bf215546Sopenharmony_cistatic boolean
1697bf215546Sopenharmony_ciemit_tex4(struct svga_shader_emitter *emit,
1698bf215546Sopenharmony_ci          const struct tgsi_full_instruction *insn,
1699bf215546Sopenharmony_ci          SVGA3dShaderDestToken dst )
1700bf215546Sopenharmony_ci{
1701bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst;
1702bf215546Sopenharmony_ci   struct src_register texcoord;
1703bf215546Sopenharmony_ci   struct src_register ddx;
1704bf215546Sopenharmony_ci   struct src_register ddy;
1705bf215546Sopenharmony_ci   struct src_register sampler;
1706bf215546Sopenharmony_ci
1707bf215546Sopenharmony_ci   texcoord = translate_src_register( emit, &insn->Src[0] );
1708bf215546Sopenharmony_ci   ddx      = translate_src_register( emit, &insn->Src[1] );
1709bf215546Sopenharmony_ci   ddy      = translate_src_register( emit, &insn->Src[2] );
1710bf215546Sopenharmony_ci   sampler  = translate_src_register( emit, &insn->Src[3] );
1711bf215546Sopenharmony_ci
1712bf215546Sopenharmony_ci   inst.value = 0;
1713bf215546Sopenharmony_ci
1714bf215546Sopenharmony_ci   switch (insn->Instruction.Opcode) {
1715bf215546Sopenharmony_ci   case TGSI_OPCODE_TXD:
1716bf215546Sopenharmony_ci      inst.op = SVGA3DOP_TEXLDD; /* 4 args! */
1717bf215546Sopenharmony_ci      break;
1718bf215546Sopenharmony_ci   default:
1719bf215546Sopenharmony_ci      assert(0);
1720bf215546Sopenharmony_ci      return FALSE;
1721bf215546Sopenharmony_ci   }
1722bf215546Sopenharmony_ci
1723bf215546Sopenharmony_ci   return submit_op4( emit, inst, dst, texcoord, sampler, ddx, ddy );
1724bf215546Sopenharmony_ci}
1725bf215546Sopenharmony_ci
1726bf215546Sopenharmony_ci
1727bf215546Sopenharmony_ci/**
1728bf215546Sopenharmony_ci * Emit texture swizzle code.  We do this here since SVGA samplers don't
1729bf215546Sopenharmony_ci * directly support swizzles.
1730bf215546Sopenharmony_ci */
1731bf215546Sopenharmony_cistatic boolean
1732bf215546Sopenharmony_ciemit_tex_swizzle(struct svga_shader_emitter *emit,
1733bf215546Sopenharmony_ci                 SVGA3dShaderDestToken dst,
1734bf215546Sopenharmony_ci                 struct src_register src,
1735bf215546Sopenharmony_ci                 unsigned swizzle_x,
1736bf215546Sopenharmony_ci                 unsigned swizzle_y,
1737bf215546Sopenharmony_ci                 unsigned swizzle_z,
1738bf215546Sopenharmony_ci                 unsigned swizzle_w)
1739bf215546Sopenharmony_ci{
1740bf215546Sopenharmony_ci   const unsigned swizzleIn[4] = {swizzle_x, swizzle_y, swizzle_z, swizzle_w};
1741bf215546Sopenharmony_ci   unsigned srcSwizzle[4];
1742bf215546Sopenharmony_ci   unsigned srcWritemask = 0x0, zeroWritemask = 0x0, oneWritemask = 0x0;
1743bf215546Sopenharmony_ci   unsigned i;
1744bf215546Sopenharmony_ci
1745bf215546Sopenharmony_ci   /* build writemasks and srcSwizzle terms */
1746bf215546Sopenharmony_ci   for (i = 0; i < 4; i++) {
1747bf215546Sopenharmony_ci      if (swizzleIn[i] == PIPE_SWIZZLE_0) {
1748bf215546Sopenharmony_ci         srcSwizzle[i] = TGSI_SWIZZLE_X + i;
1749bf215546Sopenharmony_ci         zeroWritemask |= (1 << i);
1750bf215546Sopenharmony_ci      }
1751bf215546Sopenharmony_ci      else if (swizzleIn[i] == PIPE_SWIZZLE_1) {
1752bf215546Sopenharmony_ci         srcSwizzle[i] = TGSI_SWIZZLE_X + i;
1753bf215546Sopenharmony_ci         oneWritemask |= (1 << i);
1754bf215546Sopenharmony_ci      }
1755bf215546Sopenharmony_ci      else {
1756bf215546Sopenharmony_ci         srcSwizzle[i] = swizzleIn[i];
1757bf215546Sopenharmony_ci         srcWritemask |= (1 << i);
1758bf215546Sopenharmony_ci      }
1759bf215546Sopenharmony_ci   }
1760bf215546Sopenharmony_ci
1761bf215546Sopenharmony_ci   /* write x/y/z/w comps */
1762bf215546Sopenharmony_ci   if (dst.mask & srcWritemask) {
1763bf215546Sopenharmony_ci      if (!submit_op1(emit,
1764bf215546Sopenharmony_ci                      inst_token(SVGA3DOP_MOV),
1765bf215546Sopenharmony_ci                      writemask(dst, srcWritemask),
1766bf215546Sopenharmony_ci                      swizzle(src,
1767bf215546Sopenharmony_ci                              srcSwizzle[0],
1768bf215546Sopenharmony_ci                              srcSwizzle[1],
1769bf215546Sopenharmony_ci                              srcSwizzle[2],
1770bf215546Sopenharmony_ci                              srcSwizzle[3])))
1771bf215546Sopenharmony_ci         return FALSE;
1772bf215546Sopenharmony_ci   }
1773bf215546Sopenharmony_ci
1774bf215546Sopenharmony_ci   /* write 0 comps */
1775bf215546Sopenharmony_ci   if (dst.mask & zeroWritemask) {
1776bf215546Sopenharmony_ci      if (!submit_op1(emit,
1777bf215546Sopenharmony_ci                      inst_token(SVGA3DOP_MOV),
1778bf215546Sopenharmony_ci                      writemask(dst, zeroWritemask),
1779bf215546Sopenharmony_ci                      get_zero_immediate(emit)))
1780bf215546Sopenharmony_ci         return FALSE;
1781bf215546Sopenharmony_ci   }
1782bf215546Sopenharmony_ci
1783bf215546Sopenharmony_ci   /* write 1 comps */
1784bf215546Sopenharmony_ci   if (dst.mask & oneWritemask) {
1785bf215546Sopenharmony_ci      if (!submit_op1(emit,
1786bf215546Sopenharmony_ci                      inst_token(SVGA3DOP_MOV),
1787bf215546Sopenharmony_ci                      writemask(dst, oneWritemask),
1788bf215546Sopenharmony_ci                      get_one_immediate(emit)))
1789bf215546Sopenharmony_ci         return FALSE;
1790bf215546Sopenharmony_ci   }
1791bf215546Sopenharmony_ci
1792bf215546Sopenharmony_ci   return TRUE;
1793bf215546Sopenharmony_ci}
1794bf215546Sopenharmony_ci
1795bf215546Sopenharmony_ci
1796bf215546Sopenharmony_ci/**
1797bf215546Sopenharmony_ci * Translate/emit a TGSI texture sample instruction.
1798bf215546Sopenharmony_ci */
1799bf215546Sopenharmony_cistatic boolean
1800bf215546Sopenharmony_ciemit_tex(struct svga_shader_emitter *emit,
1801bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
1802bf215546Sopenharmony_ci{
1803bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst =
1804bf215546Sopenharmony_ci      translate_dst_register( emit, insn, 0 );
1805bf215546Sopenharmony_ci   struct src_register src0 =
1806bf215546Sopenharmony_ci      translate_src_register( emit, &insn->Src[0] );
1807bf215546Sopenharmony_ci   struct src_register src1 =
1808bf215546Sopenharmony_ci      translate_src_register( emit, &insn->Src[1] );
1809bf215546Sopenharmony_ci
1810bf215546Sopenharmony_ci   SVGA3dShaderDestToken tex_result;
1811bf215546Sopenharmony_ci   const unsigned unit = src1.base.num;
1812bf215546Sopenharmony_ci
1813bf215546Sopenharmony_ci   /* check for shadow samplers */
1814bf215546Sopenharmony_ci   boolean compare = (emit->key.tex[unit].compare_mode ==
1815bf215546Sopenharmony_ci                      PIPE_TEX_COMPARE_R_TO_TEXTURE);
1816bf215546Sopenharmony_ci
1817bf215546Sopenharmony_ci   /* texture swizzle */
1818bf215546Sopenharmony_ci   boolean swizzle = (emit->key.tex[unit].swizzle_r != PIPE_SWIZZLE_X ||
1819bf215546Sopenharmony_ci                      emit->key.tex[unit].swizzle_g != PIPE_SWIZZLE_Y ||
1820bf215546Sopenharmony_ci                      emit->key.tex[unit].swizzle_b != PIPE_SWIZZLE_Z ||
1821bf215546Sopenharmony_ci                      emit->key.tex[unit].swizzle_a != PIPE_SWIZZLE_W);
1822bf215546Sopenharmony_ci
1823bf215546Sopenharmony_ci   boolean saturate = insn->Instruction.Saturate;
1824bf215546Sopenharmony_ci
1825bf215546Sopenharmony_ci   /* If doing compare processing or tex swizzle or saturation, we need to put
1826bf215546Sopenharmony_ci    * the fetched color into a temporary so it can be used as a source later on.
1827bf215546Sopenharmony_ci    */
1828bf215546Sopenharmony_ci   if (compare || swizzle || saturate) {
1829bf215546Sopenharmony_ci      tex_result = get_temp( emit );
1830bf215546Sopenharmony_ci   }
1831bf215546Sopenharmony_ci   else {
1832bf215546Sopenharmony_ci      tex_result = dst;
1833bf215546Sopenharmony_ci   }
1834bf215546Sopenharmony_ci
1835bf215546Sopenharmony_ci   switch(insn->Instruction.Opcode) {
1836bf215546Sopenharmony_ci   case TGSI_OPCODE_TEX:
1837bf215546Sopenharmony_ci   case TGSI_OPCODE_TXB:
1838bf215546Sopenharmony_ci   case TGSI_OPCODE_TXP:
1839bf215546Sopenharmony_ci   case TGSI_OPCODE_TXL:
1840bf215546Sopenharmony_ci      if (!emit_tex2( emit, insn, tex_result ))
1841bf215546Sopenharmony_ci         return FALSE;
1842bf215546Sopenharmony_ci      break;
1843bf215546Sopenharmony_ci   case TGSI_OPCODE_TXD:
1844bf215546Sopenharmony_ci      if (!emit_tex4( emit, insn, tex_result ))
1845bf215546Sopenharmony_ci         return FALSE;
1846bf215546Sopenharmony_ci      break;
1847bf215546Sopenharmony_ci   default:
1848bf215546Sopenharmony_ci      assert(0);
1849bf215546Sopenharmony_ci   }
1850bf215546Sopenharmony_ci
1851bf215546Sopenharmony_ci   if (compare) {
1852bf215546Sopenharmony_ci      SVGA3dShaderDestToken dst2;
1853bf215546Sopenharmony_ci
1854bf215546Sopenharmony_ci      if (swizzle || saturate)
1855bf215546Sopenharmony_ci         dst2 = tex_result;
1856bf215546Sopenharmony_ci      else
1857bf215546Sopenharmony_ci         dst2 = dst;
1858bf215546Sopenharmony_ci
1859bf215546Sopenharmony_ci      if (dst.mask & TGSI_WRITEMASK_XYZ) {
1860bf215546Sopenharmony_ci         SVGA3dShaderDestToken src0_zdivw = get_temp( emit );
1861bf215546Sopenharmony_ci         /* When sampling a depth texture, the result of the comparison is in
1862bf215546Sopenharmony_ci          * the Y component.
1863bf215546Sopenharmony_ci          */
1864bf215546Sopenharmony_ci         struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y);
1865bf215546Sopenharmony_ci         struct src_register r_coord;
1866bf215546Sopenharmony_ci
1867bf215546Sopenharmony_ci         if (insn->Instruction.Opcode == TGSI_OPCODE_TXP) {
1868bf215546Sopenharmony_ci            /* Divide texcoord R by Q */
1869bf215546Sopenharmony_ci            if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ),
1870bf215546Sopenharmony_ci                             writemask(src0_zdivw, TGSI_WRITEMASK_X),
1871bf215546Sopenharmony_ci                             scalar(src0, TGSI_SWIZZLE_W) ))
1872bf215546Sopenharmony_ci               return FALSE;
1873bf215546Sopenharmony_ci
1874bf215546Sopenharmony_ci            if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ),
1875bf215546Sopenharmony_ci                             writemask(src0_zdivw, TGSI_WRITEMASK_X),
1876bf215546Sopenharmony_ci                             scalar(src0, TGSI_SWIZZLE_Z),
1877bf215546Sopenharmony_ci                             scalar(src(src0_zdivw), TGSI_SWIZZLE_X) ))
1878bf215546Sopenharmony_ci               return FALSE;
1879bf215546Sopenharmony_ci
1880bf215546Sopenharmony_ci            r_coord = scalar(src(src0_zdivw), TGSI_SWIZZLE_X);
1881bf215546Sopenharmony_ci         }
1882bf215546Sopenharmony_ci         else {
1883bf215546Sopenharmony_ci            r_coord = scalar(src0, TGSI_SWIZZLE_Z);
1884bf215546Sopenharmony_ci         }
1885bf215546Sopenharmony_ci
1886bf215546Sopenharmony_ci         /* Compare texture sample value against R component of texcoord */
1887bf215546Sopenharmony_ci         if (!emit_select(emit,
1888bf215546Sopenharmony_ci                          emit->key.tex[unit].compare_func,
1889bf215546Sopenharmony_ci                          writemask( dst2, TGSI_WRITEMASK_XYZ ),
1890bf215546Sopenharmony_ci                          r_coord,
1891bf215546Sopenharmony_ci                          tex_src_x))
1892bf215546Sopenharmony_ci            return FALSE;
1893bf215546Sopenharmony_ci      }
1894bf215546Sopenharmony_ci
1895bf215546Sopenharmony_ci      if (dst.mask & TGSI_WRITEMASK_W) {
1896bf215546Sopenharmony_ci         struct src_register one = get_one_immediate(emit);
1897bf215546Sopenharmony_ci
1898bf215546Sopenharmony_ci        if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
1899bf215546Sopenharmony_ci                         writemask( dst2, TGSI_WRITEMASK_W ),
1900bf215546Sopenharmony_ci                         one ))
1901bf215546Sopenharmony_ci           return FALSE;
1902bf215546Sopenharmony_ci      }
1903bf215546Sopenharmony_ci   }
1904bf215546Sopenharmony_ci
1905bf215546Sopenharmony_ci   if (saturate && !swizzle) {
1906bf215546Sopenharmony_ci      /* MOV_SAT real_dst, dst */
1907bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src(tex_result) ))
1908bf215546Sopenharmony_ci         return FALSE;
1909bf215546Sopenharmony_ci   }
1910bf215546Sopenharmony_ci   else if (swizzle) {
1911bf215546Sopenharmony_ci      /* swizzle from tex_result to dst (handles saturation too, if any) */
1912bf215546Sopenharmony_ci      emit_tex_swizzle(emit,
1913bf215546Sopenharmony_ci                       dst, src(tex_result),
1914bf215546Sopenharmony_ci                       emit->key.tex[unit].swizzle_r,
1915bf215546Sopenharmony_ci                       emit->key.tex[unit].swizzle_g,
1916bf215546Sopenharmony_ci                       emit->key.tex[unit].swizzle_b,
1917bf215546Sopenharmony_ci                       emit->key.tex[unit].swizzle_a);
1918bf215546Sopenharmony_ci   }
1919bf215546Sopenharmony_ci
1920bf215546Sopenharmony_ci   return TRUE;
1921bf215546Sopenharmony_ci}
1922bf215546Sopenharmony_ci
1923bf215546Sopenharmony_ci
1924bf215546Sopenharmony_cistatic boolean
1925bf215546Sopenharmony_ciemit_bgnloop(struct svga_shader_emitter *emit,
1926bf215546Sopenharmony_ci             const struct tgsi_full_instruction *insn)
1927bf215546Sopenharmony_ci{
1928bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_LOOP );
1929bf215546Sopenharmony_ci   struct src_register loop_reg = src_register( SVGA3DREG_LOOP, 0 );
1930bf215546Sopenharmony_ci   struct src_register const_int = get_loop_const( emit );
1931bf215546Sopenharmony_ci
1932bf215546Sopenharmony_ci   emit->dynamic_branching_level++;
1933bf215546Sopenharmony_ci
1934bf215546Sopenharmony_ci   return (emit_instruction( emit, inst ) &&
1935bf215546Sopenharmony_ci           emit_src( emit, loop_reg ) &&
1936bf215546Sopenharmony_ci           emit_src( emit, const_int ) );
1937bf215546Sopenharmony_ci}
1938bf215546Sopenharmony_ci
1939bf215546Sopenharmony_ci
1940bf215546Sopenharmony_cistatic boolean
1941bf215546Sopenharmony_ciemit_endloop(struct svga_shader_emitter *emit,
1942bf215546Sopenharmony_ci             const struct tgsi_full_instruction *insn)
1943bf215546Sopenharmony_ci{
1944bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_ENDLOOP );
1945bf215546Sopenharmony_ci
1946bf215546Sopenharmony_ci   emit->dynamic_branching_level--;
1947bf215546Sopenharmony_ci
1948bf215546Sopenharmony_ci   return emit_instruction( emit, inst );
1949bf215546Sopenharmony_ci}
1950bf215546Sopenharmony_ci
1951bf215546Sopenharmony_ci
1952bf215546Sopenharmony_ci/**
1953bf215546Sopenharmony_ci * Translate/emit TGSI BREAK (out of loop) instruction.
1954bf215546Sopenharmony_ci */
1955bf215546Sopenharmony_cistatic boolean
1956bf215546Sopenharmony_ciemit_brk(struct svga_shader_emitter *emit,
1957bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
1958bf215546Sopenharmony_ci{
1959bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_BREAK );
1960bf215546Sopenharmony_ci   return emit_instruction( emit, inst );
1961bf215546Sopenharmony_ci}
1962bf215546Sopenharmony_ci
1963bf215546Sopenharmony_ci
1964bf215546Sopenharmony_ci/**
1965bf215546Sopenharmony_ci * Emit simple instruction which operates on one scalar value (not
1966bf215546Sopenharmony_ci * a vector).  Ex: LG2, RCP, RSQ.
1967bf215546Sopenharmony_ci */
1968bf215546Sopenharmony_cistatic boolean
1969bf215546Sopenharmony_ciemit_scalar_op1(struct svga_shader_emitter *emit,
1970bf215546Sopenharmony_ci                SVGA3dShaderOpCodeType opcode,
1971bf215546Sopenharmony_ci                const struct tgsi_full_instruction *insn)
1972bf215546Sopenharmony_ci{
1973bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst;
1974bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst;
1975bf215546Sopenharmony_ci   struct src_register src;
1976bf215546Sopenharmony_ci
1977bf215546Sopenharmony_ci   inst = inst_token( opcode );
1978bf215546Sopenharmony_ci   dst = translate_dst_register( emit, insn, 0 );
1979bf215546Sopenharmony_ci   src = translate_src_register( emit, &insn->Src[0] );
1980bf215546Sopenharmony_ci   src = scalar( src, TGSI_SWIZZLE_X );
1981bf215546Sopenharmony_ci
1982bf215546Sopenharmony_ci   return submit_op1( emit, inst, dst, src );
1983bf215546Sopenharmony_ci}
1984bf215546Sopenharmony_ci
1985bf215546Sopenharmony_ci
1986bf215546Sopenharmony_ci/**
1987bf215546Sopenharmony_ci * Translate/emit a simple instruction (one which has no special-case
1988bf215546Sopenharmony_ci * code) such as ADD, MUL, MIN, MAX.
1989bf215546Sopenharmony_ci */
1990bf215546Sopenharmony_cistatic boolean
1991bf215546Sopenharmony_ciemit_simple_instruction(struct svga_shader_emitter *emit,
1992bf215546Sopenharmony_ci                        SVGA3dShaderOpCodeType opcode,
1993bf215546Sopenharmony_ci                        const struct tgsi_full_instruction *insn)
1994bf215546Sopenharmony_ci{
1995bf215546Sopenharmony_ci   const struct tgsi_full_src_register *src = insn->Src;
1996bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst;
1997bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst;
1998bf215546Sopenharmony_ci
1999bf215546Sopenharmony_ci   inst = inst_token( opcode );
2000bf215546Sopenharmony_ci   dst = translate_dst_register( emit, insn, 0 );
2001bf215546Sopenharmony_ci
2002bf215546Sopenharmony_ci   switch (insn->Instruction.NumSrcRegs) {
2003bf215546Sopenharmony_ci   case 0:
2004bf215546Sopenharmony_ci      return submit_op0( emit, inst, dst );
2005bf215546Sopenharmony_ci   case 1:
2006bf215546Sopenharmony_ci      return submit_op1( emit, inst, dst,
2007bf215546Sopenharmony_ci                         translate_src_register( emit, &src[0] ));
2008bf215546Sopenharmony_ci   case 2:
2009bf215546Sopenharmony_ci      return submit_op2( emit, inst, dst,
2010bf215546Sopenharmony_ci                         translate_src_register( emit, &src[0] ),
2011bf215546Sopenharmony_ci                         translate_src_register( emit, &src[1] ) );
2012bf215546Sopenharmony_ci   case 3:
2013bf215546Sopenharmony_ci      return submit_op3( emit, inst, dst,
2014bf215546Sopenharmony_ci                         translate_src_register( emit, &src[0] ),
2015bf215546Sopenharmony_ci                         translate_src_register( emit, &src[1] ),
2016bf215546Sopenharmony_ci                         translate_src_register( emit, &src[2] ) );
2017bf215546Sopenharmony_ci   default:
2018bf215546Sopenharmony_ci      assert(0);
2019bf215546Sopenharmony_ci      return FALSE;
2020bf215546Sopenharmony_ci   }
2021bf215546Sopenharmony_ci}
2022bf215546Sopenharmony_ci
2023bf215546Sopenharmony_ci
2024bf215546Sopenharmony_ci/**
2025bf215546Sopenharmony_ci * TGSI_OPCODE_MOVE is only special-cased here to detect the
2026bf215546Sopenharmony_ci * svga_fragment_shader::constant_color_output case.
2027bf215546Sopenharmony_ci */
2028bf215546Sopenharmony_cistatic boolean
2029bf215546Sopenharmony_ciemit_mov(struct svga_shader_emitter *emit,
2030bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2031bf215546Sopenharmony_ci{
2032bf215546Sopenharmony_ci   const struct tgsi_full_src_register *src = &insn->Src[0];
2033bf215546Sopenharmony_ci   const struct tgsi_full_dst_register *dst = &insn->Dst[0];
2034bf215546Sopenharmony_ci
2035bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_FRAGMENT &&
2036bf215546Sopenharmony_ci       dst->Register.File == TGSI_FILE_OUTPUT &&
2037bf215546Sopenharmony_ci       dst->Register.Index == 0 &&
2038bf215546Sopenharmony_ci       src->Register.File == TGSI_FILE_CONSTANT &&
2039bf215546Sopenharmony_ci       !src->Register.Indirect) {
2040bf215546Sopenharmony_ci      emit->constant_color_output = TRUE;
2041bf215546Sopenharmony_ci   }
2042bf215546Sopenharmony_ci
2043bf215546Sopenharmony_ci   return emit_simple_instruction(emit, SVGA3DOP_MOV, insn);
2044bf215546Sopenharmony_ci}
2045bf215546Sopenharmony_ci
2046bf215546Sopenharmony_ci
2047bf215546Sopenharmony_ci/**
2048bf215546Sopenharmony_ci * Translate TGSI SQRT instruction
2049bf215546Sopenharmony_ci * if src1 == 0
2050bf215546Sopenharmony_ci *    mov dst, src1
2051bf215546Sopenharmony_ci * else
2052bf215546Sopenharmony_ci *    rsq temp, src1
2053bf215546Sopenharmony_ci *    rcp dst, temp
2054bf215546Sopenharmony_ci * endif
2055bf215546Sopenharmony_ci */
2056bf215546Sopenharmony_cistatic boolean
2057bf215546Sopenharmony_ciemit_sqrt(struct svga_shader_emitter *emit,
2058bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2059bf215546Sopenharmony_ci{
2060bf215546Sopenharmony_ci   const struct src_register src1 = translate_src_register(emit, &insn->Src[0]);
2061bf215546Sopenharmony_ci   const struct src_register zero = get_zero_immediate(emit);
2062bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register(emit, insn, 0);
2063bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp = get_temp(emit);
2064bf215546Sopenharmony_ci   SVGA3dShaderInstToken if_token = inst_token(SVGA3DOP_IFC);
2065bf215546Sopenharmony_ci   boolean ret = TRUE;
2066bf215546Sopenharmony_ci
2067bf215546Sopenharmony_ci   if_token.control = SVGA3DOPCOMP_EQ;
2068bf215546Sopenharmony_ci
2069bf215546Sopenharmony_ci   if (!(emit_instruction(emit, if_token) &&
2070bf215546Sopenharmony_ci         emit_src(emit, src1) &&
2071bf215546Sopenharmony_ci         emit_src(emit, zero))) {
2072bf215546Sopenharmony_ci      ret = FALSE;
2073bf215546Sopenharmony_ci      goto cleanup;
2074bf215546Sopenharmony_ci   }
2075bf215546Sopenharmony_ci
2076bf215546Sopenharmony_ci   if (!submit_op1(emit,
2077bf215546Sopenharmony_ci              inst_token(SVGA3DOP_MOV),
2078bf215546Sopenharmony_ci              dst, src1)) {
2079bf215546Sopenharmony_ci      ret = FALSE;
2080bf215546Sopenharmony_ci      goto cleanup;
2081bf215546Sopenharmony_ci   }
2082bf215546Sopenharmony_ci
2083bf215546Sopenharmony_ci   if (!emit_instruction(emit, inst_token(SVGA3DOP_ELSE))) {
2084bf215546Sopenharmony_ci      ret = FALSE;
2085bf215546Sopenharmony_ci      goto cleanup;
2086bf215546Sopenharmony_ci   }
2087bf215546Sopenharmony_ci
2088bf215546Sopenharmony_ci   if (!submit_op1(emit,
2089bf215546Sopenharmony_ci              inst_token(SVGA3DOP_RSQ),
2090bf215546Sopenharmony_ci              temp, src1)) {
2091bf215546Sopenharmony_ci      ret = FALSE;
2092bf215546Sopenharmony_ci      goto cleanup;
2093bf215546Sopenharmony_ci   }
2094bf215546Sopenharmony_ci
2095bf215546Sopenharmony_ci   if (!submit_op1(emit,
2096bf215546Sopenharmony_ci              inst_token(SVGA3DOP_RCP),
2097bf215546Sopenharmony_ci              dst, src(temp))) {
2098bf215546Sopenharmony_ci      ret = FALSE;
2099bf215546Sopenharmony_ci      goto cleanup;
2100bf215546Sopenharmony_ci   }
2101bf215546Sopenharmony_ci
2102bf215546Sopenharmony_ci   if (!emit_instruction(emit, inst_token(SVGA3DOP_ENDIF))) {
2103bf215546Sopenharmony_ci      ret = FALSE;
2104bf215546Sopenharmony_ci      goto cleanup;
2105bf215546Sopenharmony_ci   }
2106bf215546Sopenharmony_ci
2107bf215546Sopenharmony_cicleanup:
2108bf215546Sopenharmony_ci   release_temp(emit, temp);
2109bf215546Sopenharmony_ci
2110bf215546Sopenharmony_ci   return ret;
2111bf215546Sopenharmony_ci}
2112bf215546Sopenharmony_ci
2113bf215546Sopenharmony_ci
2114bf215546Sopenharmony_ci/**
2115bf215546Sopenharmony_ci * Translate/emit TGSI DDX, DDY instructions.
2116bf215546Sopenharmony_ci */
2117bf215546Sopenharmony_cistatic boolean
2118bf215546Sopenharmony_ciemit_deriv(struct svga_shader_emitter *emit,
2119bf215546Sopenharmony_ci           const struct tgsi_full_instruction *insn )
2120bf215546Sopenharmony_ci{
2121bf215546Sopenharmony_ci   if (emit->dynamic_branching_level > 0 &&
2122bf215546Sopenharmony_ci       insn->Src[0].Register.File == TGSI_FILE_TEMPORARY)
2123bf215546Sopenharmony_ci   {
2124bf215546Sopenharmony_ci      SVGA3dShaderDestToken dst =
2125bf215546Sopenharmony_ci         translate_dst_register( emit, insn, 0 );
2126bf215546Sopenharmony_ci
2127bf215546Sopenharmony_ci      /* Deriv opcodes not valid inside dynamic branching, workaround
2128bf215546Sopenharmony_ci       * by zeroing out the destination.
2129bf215546Sopenharmony_ci       */
2130bf215546Sopenharmony_ci      if (!submit_op1(emit,
2131bf215546Sopenharmony_ci                      inst_token( SVGA3DOP_MOV ),
2132bf215546Sopenharmony_ci                      dst,
2133bf215546Sopenharmony_ci                      get_zero_immediate(emit)))
2134bf215546Sopenharmony_ci         return FALSE;
2135bf215546Sopenharmony_ci
2136bf215546Sopenharmony_ci      return TRUE;
2137bf215546Sopenharmony_ci   }
2138bf215546Sopenharmony_ci   else {
2139bf215546Sopenharmony_ci      SVGA3dShaderOpCodeType opcode;
2140bf215546Sopenharmony_ci      const struct tgsi_full_src_register *reg = &insn->Src[0];
2141bf215546Sopenharmony_ci      SVGA3dShaderInstToken inst;
2142bf215546Sopenharmony_ci      SVGA3dShaderDestToken dst;
2143bf215546Sopenharmony_ci      struct src_register src0;
2144bf215546Sopenharmony_ci
2145bf215546Sopenharmony_ci      switch (insn->Instruction.Opcode) {
2146bf215546Sopenharmony_ci      case TGSI_OPCODE_DDX:
2147bf215546Sopenharmony_ci         opcode = SVGA3DOP_DSX;
2148bf215546Sopenharmony_ci         break;
2149bf215546Sopenharmony_ci      case TGSI_OPCODE_DDY:
2150bf215546Sopenharmony_ci         opcode = SVGA3DOP_DSY;
2151bf215546Sopenharmony_ci         break;
2152bf215546Sopenharmony_ci      default:
2153bf215546Sopenharmony_ci         return FALSE;
2154bf215546Sopenharmony_ci      }
2155bf215546Sopenharmony_ci
2156bf215546Sopenharmony_ci      inst = inst_token( opcode );
2157bf215546Sopenharmony_ci      dst = translate_dst_register( emit, insn, 0 );
2158bf215546Sopenharmony_ci      src0 = translate_src_register( emit, reg );
2159bf215546Sopenharmony_ci
2160bf215546Sopenharmony_ci      /* We cannot use negate or abs on source to dsx/dsy instruction.
2161bf215546Sopenharmony_ci       */
2162bf215546Sopenharmony_ci      if (reg->Register.Absolute ||
2163bf215546Sopenharmony_ci          reg->Register.Negate) {
2164bf215546Sopenharmony_ci         SVGA3dShaderDestToken temp = get_temp( emit );
2165bf215546Sopenharmony_ci
2166bf215546Sopenharmony_ci         if (!emit_repl( emit, temp, &src0 ))
2167bf215546Sopenharmony_ci            return FALSE;
2168bf215546Sopenharmony_ci      }
2169bf215546Sopenharmony_ci
2170bf215546Sopenharmony_ci      return submit_op1( emit, inst, dst, src0 );
2171bf215546Sopenharmony_ci   }
2172bf215546Sopenharmony_ci}
2173bf215546Sopenharmony_ci
2174bf215546Sopenharmony_ci
2175bf215546Sopenharmony_ci/**
2176bf215546Sopenharmony_ci * Translate/emit ARL (Address Register Load) instruction.  Used to
2177bf215546Sopenharmony_ci * move a value into the special 'address' register.  Used to implement
2178bf215546Sopenharmony_ci * indirect/variable indexing into arrays.
2179bf215546Sopenharmony_ci */
2180bf215546Sopenharmony_cistatic boolean
2181bf215546Sopenharmony_ciemit_arl(struct svga_shader_emitter *emit,
2182bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2183bf215546Sopenharmony_ci{
2184bf215546Sopenharmony_ci   ++emit->current_arl;
2185bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_FRAGMENT) {
2186bf215546Sopenharmony_ci      /* MOVA not present in pixel shader instruction set.
2187bf215546Sopenharmony_ci       * Ignore this instruction altogether since it is
2188bf215546Sopenharmony_ci       * only used for loop counters -- and for that
2189bf215546Sopenharmony_ci       * we reference aL directly.
2190bf215546Sopenharmony_ci       */
2191bf215546Sopenharmony_ci      return TRUE;
2192bf215546Sopenharmony_ci   }
2193bf215546Sopenharmony_ci   if (svga_arl_needs_adjustment( emit )) {
2194bf215546Sopenharmony_ci      return emit_fake_arl( emit, insn );
2195bf215546Sopenharmony_ci   } else {
2196bf215546Sopenharmony_ci      /* no need to adjust, just emit straight arl */
2197bf215546Sopenharmony_ci      return emit_simple_instruction(emit, SVGA3DOP_MOVA, insn);
2198bf215546Sopenharmony_ci   }
2199bf215546Sopenharmony_ci}
2200bf215546Sopenharmony_ci
2201bf215546Sopenharmony_ci
2202bf215546Sopenharmony_cistatic boolean
2203bf215546Sopenharmony_ciemit_pow(struct svga_shader_emitter *emit,
2204bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2205bf215546Sopenharmony_ci{
2206bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
2207bf215546Sopenharmony_ci   struct src_register src0 = translate_src_register(
2208bf215546Sopenharmony_ci      emit, &insn->Src[0] );
2209bf215546Sopenharmony_ci   struct src_register src1 = translate_src_register(
2210bf215546Sopenharmony_ci      emit, &insn->Src[1] );
2211bf215546Sopenharmony_ci   boolean need_tmp = FALSE;
2212bf215546Sopenharmony_ci
2213bf215546Sopenharmony_ci   /* POW can only output to a temporary */
2214bf215546Sopenharmony_ci   if (insn->Dst[0].Register.File != TGSI_FILE_TEMPORARY)
2215bf215546Sopenharmony_ci      need_tmp = TRUE;
2216bf215546Sopenharmony_ci
2217bf215546Sopenharmony_ci   /* POW src1 must not be the same register as dst */
2218bf215546Sopenharmony_ci   if (alias_src_dst( src1, dst ))
2219bf215546Sopenharmony_ci      need_tmp = TRUE;
2220bf215546Sopenharmony_ci
2221bf215546Sopenharmony_ci   /* it's a scalar op */
2222bf215546Sopenharmony_ci   src0 = scalar( src0, TGSI_SWIZZLE_X );
2223bf215546Sopenharmony_ci   src1 = scalar( src1, TGSI_SWIZZLE_X );
2224bf215546Sopenharmony_ci
2225bf215546Sopenharmony_ci   if (need_tmp) {
2226bf215546Sopenharmony_ci      SVGA3dShaderDestToken tmp =
2227bf215546Sopenharmony_ci         writemask(get_temp( emit ), TGSI_WRITEMASK_X );
2228bf215546Sopenharmony_ci
2229bf215546Sopenharmony_ci      if (!submit_op2(emit, inst_token( SVGA3DOP_POW ), tmp, src0, src1))
2230bf215546Sopenharmony_ci         return FALSE;
2231bf215546Sopenharmony_ci
2232bf215546Sopenharmony_ci      return submit_op1(emit, inst_token( SVGA3DOP_MOV ),
2233bf215546Sopenharmony_ci                        dst, scalar(src(tmp), 0) );
2234bf215546Sopenharmony_ci   }
2235bf215546Sopenharmony_ci   else {
2236bf215546Sopenharmony_ci      return submit_op2(emit, inst_token( SVGA3DOP_POW ), dst, src0, src1);
2237bf215546Sopenharmony_ci   }
2238bf215546Sopenharmony_ci}
2239bf215546Sopenharmony_ci
2240bf215546Sopenharmony_ci
2241bf215546Sopenharmony_ci/**
2242bf215546Sopenharmony_ci * Emit a LRP (linear interpolation) instruction.
2243bf215546Sopenharmony_ci */
2244bf215546Sopenharmony_cistatic boolean
2245bf215546Sopenharmony_cisubmit_lrp(struct svga_shader_emitter *emit,
2246bf215546Sopenharmony_ci           SVGA3dShaderDestToken dst,
2247bf215546Sopenharmony_ci           struct src_register src0,
2248bf215546Sopenharmony_ci           struct src_register src1,
2249bf215546Sopenharmony_ci           struct src_register src2)
2250bf215546Sopenharmony_ci{
2251bf215546Sopenharmony_ci   SVGA3dShaderDestToken tmp;
2252bf215546Sopenharmony_ci   boolean need_dst_tmp = FALSE;
2253bf215546Sopenharmony_ci
2254bf215546Sopenharmony_ci   /* The dst reg must be a temporary, and not be the same as src0 or src2 */
2255bf215546Sopenharmony_ci   if (SVGA3dShaderGetRegType(dst.value) != SVGA3DREG_TEMP ||
2256bf215546Sopenharmony_ci       alias_src_dst(src0, dst) ||
2257bf215546Sopenharmony_ci       alias_src_dst(src2, dst))
2258bf215546Sopenharmony_ci      need_dst_tmp = TRUE;
2259bf215546Sopenharmony_ci
2260bf215546Sopenharmony_ci   if (need_dst_tmp) {
2261bf215546Sopenharmony_ci      tmp = get_temp( emit );
2262bf215546Sopenharmony_ci      tmp.mask = dst.mask;
2263bf215546Sopenharmony_ci   }
2264bf215546Sopenharmony_ci   else {
2265bf215546Sopenharmony_ci      tmp = dst;
2266bf215546Sopenharmony_ci   }
2267bf215546Sopenharmony_ci
2268bf215546Sopenharmony_ci   if (!submit_op3(emit, inst_token( SVGA3DOP_LRP ), tmp, src0, src1, src2))
2269bf215546Sopenharmony_ci      return FALSE;
2270bf215546Sopenharmony_ci
2271bf215546Sopenharmony_ci   if (need_dst_tmp) {
2272bf215546Sopenharmony_ci      if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), dst, src( tmp )))
2273bf215546Sopenharmony_ci         return FALSE;
2274bf215546Sopenharmony_ci   }
2275bf215546Sopenharmony_ci
2276bf215546Sopenharmony_ci   return TRUE;
2277bf215546Sopenharmony_ci}
2278bf215546Sopenharmony_ci
2279bf215546Sopenharmony_ci
2280bf215546Sopenharmony_ci/**
2281bf215546Sopenharmony_ci * Translate/emit LRP (Linear Interpolation) instruction.
2282bf215546Sopenharmony_ci */
2283bf215546Sopenharmony_cistatic boolean
2284bf215546Sopenharmony_ciemit_lrp(struct svga_shader_emitter *emit,
2285bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2286bf215546Sopenharmony_ci{
2287bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
2288bf215546Sopenharmony_ci   const struct src_register src0 = translate_src_register(
2289bf215546Sopenharmony_ci      emit, &insn->Src[0] );
2290bf215546Sopenharmony_ci   const struct src_register src1 = translate_src_register(
2291bf215546Sopenharmony_ci      emit, &insn->Src[1] );
2292bf215546Sopenharmony_ci   const struct src_register src2 = translate_src_register(
2293bf215546Sopenharmony_ci      emit, &insn->Src[2] );
2294bf215546Sopenharmony_ci
2295bf215546Sopenharmony_ci   return submit_lrp(emit, dst, src0, src1, src2);
2296bf215546Sopenharmony_ci}
2297bf215546Sopenharmony_ci
2298bf215546Sopenharmony_ci/**
2299bf215546Sopenharmony_ci * Translate/emit DST (Distance function) instruction.
2300bf215546Sopenharmony_ci */
2301bf215546Sopenharmony_cistatic boolean
2302bf215546Sopenharmony_ciemit_dst_insn(struct svga_shader_emitter *emit,
2303bf215546Sopenharmony_ci              const struct tgsi_full_instruction *insn)
2304bf215546Sopenharmony_ci{
2305bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
2306bf215546Sopenharmony_ci      /* SVGA/DX9 has a DST instruction, but only for vertex shaders:
2307bf215546Sopenharmony_ci       */
2308bf215546Sopenharmony_ci      return emit_simple_instruction(emit, SVGA3DOP_DST, insn);
2309bf215546Sopenharmony_ci   }
2310bf215546Sopenharmony_ci   else {
2311bf215546Sopenharmony_ci      /* result[0] = 1    * 1;
2312bf215546Sopenharmony_ci       * result[1] = a[1] * b[1];
2313bf215546Sopenharmony_ci       * result[2] = a[2] * 1;
2314bf215546Sopenharmony_ci       * result[3] = 1    * b[3];
2315bf215546Sopenharmony_ci       */
2316bf215546Sopenharmony_ci      SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
2317bf215546Sopenharmony_ci      SVGA3dShaderDestToken tmp;
2318bf215546Sopenharmony_ci      const struct src_register src0 = translate_src_register(
2319bf215546Sopenharmony_ci         emit, &insn->Src[0] );
2320bf215546Sopenharmony_ci      const struct src_register src1 = translate_src_register(
2321bf215546Sopenharmony_ci         emit, &insn->Src[1] );
2322bf215546Sopenharmony_ci      boolean need_tmp = FALSE;
2323bf215546Sopenharmony_ci
2324bf215546Sopenharmony_ci      if (SVGA3dShaderGetRegType(dst.value) != SVGA3DREG_TEMP ||
2325bf215546Sopenharmony_ci          alias_src_dst(src0, dst) ||
2326bf215546Sopenharmony_ci          alias_src_dst(src1, dst))
2327bf215546Sopenharmony_ci         need_tmp = TRUE;
2328bf215546Sopenharmony_ci
2329bf215546Sopenharmony_ci      if (need_tmp) {
2330bf215546Sopenharmony_ci         tmp = get_temp( emit );
2331bf215546Sopenharmony_ci      }
2332bf215546Sopenharmony_ci      else {
2333bf215546Sopenharmony_ci         tmp = dst;
2334bf215546Sopenharmony_ci      }
2335bf215546Sopenharmony_ci
2336bf215546Sopenharmony_ci      /* tmp.xw = 1.0
2337bf215546Sopenharmony_ci       */
2338bf215546Sopenharmony_ci      if (tmp.mask & TGSI_WRITEMASK_XW) {
2339bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2340bf215546Sopenharmony_ci                          writemask(tmp, TGSI_WRITEMASK_XW ),
2341bf215546Sopenharmony_ci                          get_one_immediate(emit)))
2342bf215546Sopenharmony_ci            return FALSE;
2343bf215546Sopenharmony_ci      }
2344bf215546Sopenharmony_ci
2345bf215546Sopenharmony_ci      /* tmp.yz = src0
2346bf215546Sopenharmony_ci       */
2347bf215546Sopenharmony_ci      if (tmp.mask & TGSI_WRITEMASK_YZ) {
2348bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2349bf215546Sopenharmony_ci                          writemask(tmp, TGSI_WRITEMASK_YZ ),
2350bf215546Sopenharmony_ci                          src0))
2351bf215546Sopenharmony_ci            return FALSE;
2352bf215546Sopenharmony_ci      }
2353bf215546Sopenharmony_ci
2354bf215546Sopenharmony_ci      /* tmp.yw = tmp * src1
2355bf215546Sopenharmony_ci       */
2356bf215546Sopenharmony_ci      if (tmp.mask & TGSI_WRITEMASK_YW) {
2357bf215546Sopenharmony_ci         if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ),
2358bf215546Sopenharmony_ci                          writemask(tmp, TGSI_WRITEMASK_YW ),
2359bf215546Sopenharmony_ci                          src(tmp),
2360bf215546Sopenharmony_ci                          src1))
2361bf215546Sopenharmony_ci            return FALSE;
2362bf215546Sopenharmony_ci      }
2363bf215546Sopenharmony_ci
2364bf215546Sopenharmony_ci      /* dst = tmp
2365bf215546Sopenharmony_ci       */
2366bf215546Sopenharmony_ci      if (need_tmp) {
2367bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2368bf215546Sopenharmony_ci                          dst,
2369bf215546Sopenharmony_ci                          src(tmp)))
2370bf215546Sopenharmony_ci            return FALSE;
2371bf215546Sopenharmony_ci      }
2372bf215546Sopenharmony_ci   }
2373bf215546Sopenharmony_ci
2374bf215546Sopenharmony_ci   return TRUE;
2375bf215546Sopenharmony_ci}
2376bf215546Sopenharmony_ci
2377bf215546Sopenharmony_ci
2378bf215546Sopenharmony_cistatic boolean
2379bf215546Sopenharmony_ciemit_exp(struct svga_shader_emitter *emit,
2380bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2381bf215546Sopenharmony_ci{
2382bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
2383bf215546Sopenharmony_ci   struct src_register src0 =
2384bf215546Sopenharmony_ci      translate_src_register( emit, &insn->Src[0] );
2385bf215546Sopenharmony_ci   SVGA3dShaderDestToken fraction;
2386bf215546Sopenharmony_ci
2387bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_Y)
2388bf215546Sopenharmony_ci      fraction = dst;
2389bf215546Sopenharmony_ci   else if (dst.mask & TGSI_WRITEMASK_X)
2390bf215546Sopenharmony_ci      fraction = get_temp( emit );
2391bf215546Sopenharmony_ci   else
2392bf215546Sopenharmony_ci      fraction.value = 0;
2393bf215546Sopenharmony_ci
2394bf215546Sopenharmony_ci   /* If y is being written, fill it with src0 - floor(src0).
2395bf215546Sopenharmony_ci    */
2396bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_XY) {
2397bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_FRC ),
2398bf215546Sopenharmony_ci                       writemask( fraction, TGSI_WRITEMASK_Y ),
2399bf215546Sopenharmony_ci                       src0 ))
2400bf215546Sopenharmony_ci         return FALSE;
2401bf215546Sopenharmony_ci   }
2402bf215546Sopenharmony_ci
2403bf215546Sopenharmony_ci   /* If x is being written, fill it with 2 ^ floor(src0).
2404bf215546Sopenharmony_ci    */
2405bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_X) {
2406bf215546Sopenharmony_ci      if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ),
2407bf215546Sopenharmony_ci                       writemask( dst, TGSI_WRITEMASK_X ),
2408bf215546Sopenharmony_ci                       src0,
2409bf215546Sopenharmony_ci                       scalar( negate( src( fraction ) ), TGSI_SWIZZLE_Y ) ) )
2410bf215546Sopenharmony_ci         return FALSE;
2411bf215546Sopenharmony_ci
2412bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_EXP ),
2413bf215546Sopenharmony_ci                       writemask( dst, TGSI_WRITEMASK_X ),
2414bf215546Sopenharmony_ci                       scalar( src( dst ), TGSI_SWIZZLE_X ) ) )
2415bf215546Sopenharmony_ci         return FALSE;
2416bf215546Sopenharmony_ci
2417bf215546Sopenharmony_ci      if (!(dst.mask & TGSI_WRITEMASK_Y))
2418bf215546Sopenharmony_ci         release_temp( emit, fraction );
2419bf215546Sopenharmony_ci   }
2420bf215546Sopenharmony_ci
2421bf215546Sopenharmony_ci   /* If z is being written, fill it with 2 ^ src0 (partial precision).
2422bf215546Sopenharmony_ci    */
2423bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_Z) {
2424bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_EXPP ),
2425bf215546Sopenharmony_ci                       writemask( dst, TGSI_WRITEMASK_Z ),
2426bf215546Sopenharmony_ci                       src0 ) )
2427bf215546Sopenharmony_ci         return FALSE;
2428bf215546Sopenharmony_ci   }
2429bf215546Sopenharmony_ci
2430bf215546Sopenharmony_ci   /* If w is being written, fill it with one.
2431bf215546Sopenharmony_ci    */
2432bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_W) {
2433bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2434bf215546Sopenharmony_ci                       writemask(dst, TGSI_WRITEMASK_W),
2435bf215546Sopenharmony_ci                       get_one_immediate(emit)))
2436bf215546Sopenharmony_ci         return FALSE;
2437bf215546Sopenharmony_ci   }
2438bf215546Sopenharmony_ci
2439bf215546Sopenharmony_ci   return TRUE;
2440bf215546Sopenharmony_ci}
2441bf215546Sopenharmony_ci
2442bf215546Sopenharmony_ci
2443bf215546Sopenharmony_ci/**
2444bf215546Sopenharmony_ci * Translate/emit LIT (Lighting helper) instruction.
2445bf215546Sopenharmony_ci */
2446bf215546Sopenharmony_cistatic boolean
2447bf215546Sopenharmony_ciemit_lit(struct svga_shader_emitter *emit,
2448bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2449bf215546Sopenharmony_ci{
2450bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
2451bf215546Sopenharmony_ci      /* SVGA/DX9 has a LIT instruction, but only for vertex shaders:
2452bf215546Sopenharmony_ci       */
2453bf215546Sopenharmony_ci      return emit_simple_instruction(emit, SVGA3DOP_LIT, insn);
2454bf215546Sopenharmony_ci   }
2455bf215546Sopenharmony_ci   else {
2456bf215546Sopenharmony_ci      /* D3D vs. GL semantics can be fairly easily accommodated by
2457bf215546Sopenharmony_ci       * variations on this sequence.
2458bf215546Sopenharmony_ci       *
2459bf215546Sopenharmony_ci       * GL:
2460bf215546Sopenharmony_ci       *   tmp.y = src.x
2461bf215546Sopenharmony_ci       *   tmp.z = pow(src.y,src.w)
2462bf215546Sopenharmony_ci       *   p0 = src0.xxxx > 0
2463bf215546Sopenharmony_ci       *   result = zero.wxxw
2464bf215546Sopenharmony_ci       *   (p0) result.yz = tmp
2465bf215546Sopenharmony_ci       *
2466bf215546Sopenharmony_ci       * D3D:
2467bf215546Sopenharmony_ci       *   tmp.y = src.x
2468bf215546Sopenharmony_ci       *   tmp.z = pow(src.y,src.w)
2469bf215546Sopenharmony_ci       *   p0 = src0.xxyy > 0
2470bf215546Sopenharmony_ci       *   result = zero.wxxw
2471bf215546Sopenharmony_ci       *   (p0) result.yz = tmp
2472bf215546Sopenharmony_ci       *
2473bf215546Sopenharmony_ci       * Will implement the GL version for now.
2474bf215546Sopenharmony_ci       */
2475bf215546Sopenharmony_ci      SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
2476bf215546Sopenharmony_ci      SVGA3dShaderDestToken tmp = get_temp( emit );
2477bf215546Sopenharmony_ci      const struct src_register src0 = translate_src_register(
2478bf215546Sopenharmony_ci         emit, &insn->Src[0] );
2479bf215546Sopenharmony_ci
2480bf215546Sopenharmony_ci      /* tmp = pow(src.y, src.w)
2481bf215546Sopenharmony_ci       */
2482bf215546Sopenharmony_ci      if (dst.mask & TGSI_WRITEMASK_Z) {
2483bf215546Sopenharmony_ci         if (!submit_op2(emit, inst_token( SVGA3DOP_POW ),
2484bf215546Sopenharmony_ci                         tmp,
2485bf215546Sopenharmony_ci                         scalar(src0, 1),
2486bf215546Sopenharmony_ci                         scalar(src0, 3)))
2487bf215546Sopenharmony_ci            return FALSE;
2488bf215546Sopenharmony_ci      }
2489bf215546Sopenharmony_ci
2490bf215546Sopenharmony_ci      /* tmp.y = src.x
2491bf215546Sopenharmony_ci       */
2492bf215546Sopenharmony_ci      if (dst.mask & TGSI_WRITEMASK_Y) {
2493bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2494bf215546Sopenharmony_ci                          writemask(tmp, TGSI_WRITEMASK_Y ),
2495bf215546Sopenharmony_ci                          scalar(src0, 0)))
2496bf215546Sopenharmony_ci            return FALSE;
2497bf215546Sopenharmony_ci      }
2498bf215546Sopenharmony_ci
2499bf215546Sopenharmony_ci      /* Can't quite do this with emit conditional due to the extra
2500bf215546Sopenharmony_ci       * writemask on the predicated mov:
2501bf215546Sopenharmony_ci       */
2502bf215546Sopenharmony_ci      {
2503bf215546Sopenharmony_ci         SVGA3dShaderDestToken pred_reg = dst_register( SVGA3DREG_PREDICATE, 0 );
2504bf215546Sopenharmony_ci         struct src_register predsrc;
2505bf215546Sopenharmony_ci
2506bf215546Sopenharmony_ci         /* D3D vs GL semantics:
2507bf215546Sopenharmony_ci          */
2508bf215546Sopenharmony_ci         if (0)
2509bf215546Sopenharmony_ci            predsrc = swizzle(src0, 0, 0, 1, 1); /* D3D */
2510bf215546Sopenharmony_ci         else
2511bf215546Sopenharmony_ci            predsrc = swizzle(src0, 0, 0, 0, 0); /* GL */
2512bf215546Sopenharmony_ci
2513bf215546Sopenharmony_ci         /* SETP src0.xxyy, GT, {0}.x */
2514bf215546Sopenharmony_ci         if (!submit_op2( emit,
2515bf215546Sopenharmony_ci                          inst_token_setp(SVGA3DOPCOMP_GT),
2516bf215546Sopenharmony_ci                          pred_reg,
2517bf215546Sopenharmony_ci                          predsrc,
2518bf215546Sopenharmony_ci                          get_zero_immediate(emit)))
2519bf215546Sopenharmony_ci            return FALSE;
2520bf215546Sopenharmony_ci
2521bf215546Sopenharmony_ci         /* MOV dst, fail */
2522bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst,
2523bf215546Sopenharmony_ci                          get_immediate(emit, 1.0f, 0.0f, 0.0f, 1.0f)))
2524bf215546Sopenharmony_ci             return FALSE;
2525bf215546Sopenharmony_ci
2526bf215546Sopenharmony_ci         /* MOV dst.yz, tmp (predicated)
2527bf215546Sopenharmony_ci          *
2528bf215546Sopenharmony_ci          * Note that the predicate reg (and possible modifiers) is passed
2529bf215546Sopenharmony_ci          * as the first source argument.
2530bf215546Sopenharmony_ci          */
2531bf215546Sopenharmony_ci         if (dst.mask & TGSI_WRITEMASK_YZ) {
2532bf215546Sopenharmony_ci            if (!submit_op2( emit,
2533bf215546Sopenharmony_ci                             inst_token_predicated(SVGA3DOP_MOV),
2534bf215546Sopenharmony_ci                             writemask(dst, TGSI_WRITEMASK_YZ),
2535bf215546Sopenharmony_ci                             src( pred_reg ), src( tmp ) ))
2536bf215546Sopenharmony_ci               return FALSE;
2537bf215546Sopenharmony_ci         }
2538bf215546Sopenharmony_ci      }
2539bf215546Sopenharmony_ci   }
2540bf215546Sopenharmony_ci
2541bf215546Sopenharmony_ci   return TRUE;
2542bf215546Sopenharmony_ci}
2543bf215546Sopenharmony_ci
2544bf215546Sopenharmony_ci
2545bf215546Sopenharmony_cistatic boolean
2546bf215546Sopenharmony_ciemit_ex2(struct svga_shader_emitter *emit,
2547bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2548bf215546Sopenharmony_ci{
2549bf215546Sopenharmony_ci   SVGA3dShaderInstToken inst;
2550bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst;
2551bf215546Sopenharmony_ci   struct src_register src0;
2552bf215546Sopenharmony_ci
2553bf215546Sopenharmony_ci   inst = inst_token( SVGA3DOP_EXP );
2554bf215546Sopenharmony_ci   dst = translate_dst_register( emit, insn, 0 );
2555bf215546Sopenharmony_ci   src0 = translate_src_register( emit, &insn->Src[0] );
2556bf215546Sopenharmony_ci   src0 = scalar( src0, TGSI_SWIZZLE_X );
2557bf215546Sopenharmony_ci
2558bf215546Sopenharmony_ci   if (dst.mask != TGSI_WRITEMASK_XYZW) {
2559bf215546Sopenharmony_ci      SVGA3dShaderDestToken tmp = get_temp( emit );
2560bf215546Sopenharmony_ci
2561bf215546Sopenharmony_ci      if (!submit_op1( emit, inst, tmp, src0 ))
2562bf215546Sopenharmony_ci         return FALSE;
2563bf215546Sopenharmony_ci
2564bf215546Sopenharmony_ci      return submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2565bf215546Sopenharmony_ci                         dst,
2566bf215546Sopenharmony_ci                         scalar( src( tmp ), TGSI_SWIZZLE_X ) );
2567bf215546Sopenharmony_ci   }
2568bf215546Sopenharmony_ci
2569bf215546Sopenharmony_ci   return submit_op1( emit, inst, dst, src0 );
2570bf215546Sopenharmony_ci}
2571bf215546Sopenharmony_ci
2572bf215546Sopenharmony_ci
2573bf215546Sopenharmony_cistatic boolean
2574bf215546Sopenharmony_ciemit_log(struct svga_shader_emitter *emit,
2575bf215546Sopenharmony_ci         const struct tgsi_full_instruction *insn)
2576bf215546Sopenharmony_ci{
2577bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
2578bf215546Sopenharmony_ci   struct src_register src0 =
2579bf215546Sopenharmony_ci      translate_src_register( emit, &insn->Src[0] );
2580bf215546Sopenharmony_ci   SVGA3dShaderDestToken abs_tmp;
2581bf215546Sopenharmony_ci   struct src_register abs_src0;
2582bf215546Sopenharmony_ci   SVGA3dShaderDestToken log2_abs;
2583bf215546Sopenharmony_ci
2584bf215546Sopenharmony_ci   abs_tmp.value = 0;
2585bf215546Sopenharmony_ci
2586bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_Z)
2587bf215546Sopenharmony_ci      log2_abs = dst;
2588bf215546Sopenharmony_ci   else if (dst.mask & TGSI_WRITEMASK_XY)
2589bf215546Sopenharmony_ci      log2_abs = get_temp( emit );
2590bf215546Sopenharmony_ci   else
2591bf215546Sopenharmony_ci      log2_abs.value = 0;
2592bf215546Sopenharmony_ci
2593bf215546Sopenharmony_ci   /* If z is being written, fill it with log2( abs( src0 ) ).
2594bf215546Sopenharmony_ci    */
2595bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_XYZ) {
2596bf215546Sopenharmony_ci      if (!src0.base.srcMod || src0.base.srcMod == SVGA3DSRCMOD_ABS)
2597bf215546Sopenharmony_ci         abs_src0 = src0;
2598bf215546Sopenharmony_ci      else {
2599bf215546Sopenharmony_ci         abs_tmp = get_temp( emit );
2600bf215546Sopenharmony_ci
2601bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2602bf215546Sopenharmony_ci                          abs_tmp,
2603bf215546Sopenharmony_ci                          src0 ) )
2604bf215546Sopenharmony_ci            return FALSE;
2605bf215546Sopenharmony_ci
2606bf215546Sopenharmony_ci         abs_src0 = src( abs_tmp );
2607bf215546Sopenharmony_ci      }
2608bf215546Sopenharmony_ci
2609bf215546Sopenharmony_ci      abs_src0 = absolute( scalar( abs_src0, TGSI_SWIZZLE_X ) );
2610bf215546Sopenharmony_ci
2611bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_LOG ),
2612bf215546Sopenharmony_ci                       writemask( log2_abs, TGSI_WRITEMASK_Z ),
2613bf215546Sopenharmony_ci                       abs_src0 ) )
2614bf215546Sopenharmony_ci         return FALSE;
2615bf215546Sopenharmony_ci   }
2616bf215546Sopenharmony_ci
2617bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_XY) {
2618bf215546Sopenharmony_ci      SVGA3dShaderDestToken floor_log2;
2619bf215546Sopenharmony_ci
2620bf215546Sopenharmony_ci      if (dst.mask & TGSI_WRITEMASK_X)
2621bf215546Sopenharmony_ci         floor_log2 = dst;
2622bf215546Sopenharmony_ci      else
2623bf215546Sopenharmony_ci         floor_log2 = get_temp( emit );
2624bf215546Sopenharmony_ci
2625bf215546Sopenharmony_ci      /* If x is being written, fill it with floor( log2( abs( src0 ) ) ).
2626bf215546Sopenharmony_ci       */
2627bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_FRC ),
2628bf215546Sopenharmony_ci                       writemask( floor_log2, TGSI_WRITEMASK_X ),
2629bf215546Sopenharmony_ci                       scalar( src( log2_abs ), TGSI_SWIZZLE_Z ) ) )
2630bf215546Sopenharmony_ci         return FALSE;
2631bf215546Sopenharmony_ci
2632bf215546Sopenharmony_ci      if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ),
2633bf215546Sopenharmony_ci                       writemask( floor_log2, TGSI_WRITEMASK_X ),
2634bf215546Sopenharmony_ci                       scalar( src( log2_abs ), TGSI_SWIZZLE_Z ),
2635bf215546Sopenharmony_ci                       negate( src( floor_log2 ) ) ) )
2636bf215546Sopenharmony_ci         return FALSE;
2637bf215546Sopenharmony_ci
2638bf215546Sopenharmony_ci      /* If y is being written, fill it with
2639bf215546Sopenharmony_ci       * abs ( src0 ) / ( 2 ^ floor( log2( abs( src0 ) ) ) ).
2640bf215546Sopenharmony_ci       */
2641bf215546Sopenharmony_ci      if (dst.mask & TGSI_WRITEMASK_Y) {
2642bf215546Sopenharmony_ci         if (!submit_op1( emit, inst_token( SVGA3DOP_EXP ),
2643bf215546Sopenharmony_ci                          writemask( dst, TGSI_WRITEMASK_Y ),
2644bf215546Sopenharmony_ci                          negate( scalar( src( floor_log2 ),
2645bf215546Sopenharmony_ci                                          TGSI_SWIZZLE_X ) ) ) )
2646bf215546Sopenharmony_ci            return FALSE;
2647bf215546Sopenharmony_ci
2648bf215546Sopenharmony_ci         if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ),
2649bf215546Sopenharmony_ci                          writemask( dst, TGSI_WRITEMASK_Y ),
2650bf215546Sopenharmony_ci                          src( dst ),
2651bf215546Sopenharmony_ci                          abs_src0 ) )
2652bf215546Sopenharmony_ci            return FALSE;
2653bf215546Sopenharmony_ci      }
2654bf215546Sopenharmony_ci
2655bf215546Sopenharmony_ci      if (!(dst.mask & TGSI_WRITEMASK_X))
2656bf215546Sopenharmony_ci         release_temp( emit, floor_log2 );
2657bf215546Sopenharmony_ci
2658bf215546Sopenharmony_ci      if (!(dst.mask & TGSI_WRITEMASK_Z))
2659bf215546Sopenharmony_ci         release_temp( emit, log2_abs );
2660bf215546Sopenharmony_ci   }
2661bf215546Sopenharmony_ci
2662bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_XYZ && src0.base.srcMod &&
2663bf215546Sopenharmony_ci       src0.base.srcMod != SVGA3DSRCMOD_ABS)
2664bf215546Sopenharmony_ci      release_temp( emit, abs_tmp );
2665bf215546Sopenharmony_ci
2666bf215546Sopenharmony_ci   /* If w is being written, fill it with one.
2667bf215546Sopenharmony_ci    */
2668bf215546Sopenharmony_ci   if (dst.mask & TGSI_WRITEMASK_W) {
2669bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
2670bf215546Sopenharmony_ci                       writemask(dst, TGSI_WRITEMASK_W),
2671bf215546Sopenharmony_ci                       get_one_immediate(emit)))
2672bf215546Sopenharmony_ci         return FALSE;
2673bf215546Sopenharmony_ci   }
2674bf215546Sopenharmony_ci
2675bf215546Sopenharmony_ci   return TRUE;
2676bf215546Sopenharmony_ci}
2677bf215546Sopenharmony_ci
2678bf215546Sopenharmony_ci
2679bf215546Sopenharmony_ci/**
2680bf215546Sopenharmony_ci * Translate TGSI TRUNC or ROUND instruction.
2681bf215546Sopenharmony_ci * We need to truncate toward zero. Ex: trunc(-1.9) = -1
2682bf215546Sopenharmony_ci * Different approaches are needed for VS versus PS.
2683bf215546Sopenharmony_ci */
2684bf215546Sopenharmony_cistatic boolean
2685bf215546Sopenharmony_ciemit_trunc_round(struct svga_shader_emitter *emit,
2686bf215546Sopenharmony_ci                 const struct tgsi_full_instruction *insn,
2687bf215546Sopenharmony_ci                 boolean round)
2688bf215546Sopenharmony_ci{
2689bf215546Sopenharmony_ci   SVGA3dShaderDestToken dst = translate_dst_register(emit, insn, 0);
2690bf215546Sopenharmony_ci   const struct src_register src0 =
2691bf215546Sopenharmony_ci      translate_src_register(emit, &insn->Src[0] );
2692bf215546Sopenharmony_ci   SVGA3dShaderDestToken t1 = get_temp(emit);
2693bf215546Sopenharmony_ci
2694bf215546Sopenharmony_ci   if (round) {
2695bf215546Sopenharmony_ci      SVGA3dShaderDestToken t0 = get_temp(emit);
2696bf215546Sopenharmony_ci      struct src_register half = get_half_immediate(emit);
2697bf215546Sopenharmony_ci
2698bf215546Sopenharmony_ci      /* t0 = abs(src0) + 0.5 */
2699bf215546Sopenharmony_ci      if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), t0,
2700bf215546Sopenharmony_ci                      absolute(src0), half))
2701bf215546Sopenharmony_ci         return FALSE;
2702bf215546Sopenharmony_ci
2703bf215546Sopenharmony_ci      /* t1 = fract(t0) */
2704bf215546Sopenharmony_ci      if (!submit_op1(emit, inst_token(SVGA3DOP_FRC), t1, src(t0)))
2705bf215546Sopenharmony_ci         return FALSE;
2706bf215546Sopenharmony_ci
2707bf215546Sopenharmony_ci      /* t1 = t0 - t1 */
2708bf215546Sopenharmony_ci      if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), t1, src(t0),
2709bf215546Sopenharmony_ci                      negate(src(t1))))
2710bf215546Sopenharmony_ci         return FALSE;
2711bf215546Sopenharmony_ci   }
2712bf215546Sopenharmony_ci   else {
2713bf215546Sopenharmony_ci      /* trunc */
2714bf215546Sopenharmony_ci
2715bf215546Sopenharmony_ci      /* t1 = fract(abs(src0)) */
2716bf215546Sopenharmony_ci      if (!submit_op1(emit, inst_token(SVGA3DOP_FRC), t1, absolute(src0)))
2717bf215546Sopenharmony_ci         return FALSE;
2718bf215546Sopenharmony_ci
2719bf215546Sopenharmony_ci      /* t1 = abs(src0) - t1 */
2720bf215546Sopenharmony_ci      if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), t1, absolute(src0),
2721bf215546Sopenharmony_ci                      negate(src(t1))))
2722bf215546Sopenharmony_ci         return FALSE;
2723bf215546Sopenharmony_ci   }
2724bf215546Sopenharmony_ci
2725bf215546Sopenharmony_ci   /*
2726bf215546Sopenharmony_ci    * Now we need to multiply t1 by the sign of the original value.
2727bf215546Sopenharmony_ci   */
2728bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
2729bf215546Sopenharmony_ci      /* For VS: use SGN instruction */
2730bf215546Sopenharmony_ci      /* Need two extra/dummy registers: */
2731bf215546Sopenharmony_ci      SVGA3dShaderDestToken t2 = get_temp(emit), t3 = get_temp(emit),
2732bf215546Sopenharmony_ci         t4 = get_temp(emit);
2733bf215546Sopenharmony_ci
2734bf215546Sopenharmony_ci      /* t2 = sign(src0) */
2735bf215546Sopenharmony_ci      if (!submit_op3(emit, inst_token(SVGA3DOP_SGN), t2, src0,
2736bf215546Sopenharmony_ci                      src(t3), src(t4)))
2737bf215546Sopenharmony_ci         return FALSE;
2738bf215546Sopenharmony_ci
2739bf215546Sopenharmony_ci      /* dst = t1 * t2 */
2740bf215546Sopenharmony_ci      if (!submit_op2(emit, inst_token(SVGA3DOP_MUL), dst, src(t1), src(t2)))
2741bf215546Sopenharmony_ci         return FALSE;
2742bf215546Sopenharmony_ci   }
2743bf215546Sopenharmony_ci   else {
2744bf215546Sopenharmony_ci      /* For FS: Use CMP instruction */
2745bf215546Sopenharmony_ci      return submit_op3(emit, inst_token( SVGA3DOP_CMP ), dst,
2746bf215546Sopenharmony_ci                        src0, src(t1), negate(src(t1)));
2747bf215546Sopenharmony_ci   }
2748bf215546Sopenharmony_ci
2749bf215546Sopenharmony_ci   return TRUE;
2750bf215546Sopenharmony_ci}
2751bf215546Sopenharmony_ci
2752bf215546Sopenharmony_ci
2753bf215546Sopenharmony_ci/**
2754bf215546Sopenharmony_ci * Translate/emit "begin subroutine" instruction/marker/label.
2755bf215546Sopenharmony_ci */
2756bf215546Sopenharmony_cistatic boolean
2757bf215546Sopenharmony_ciemit_bgnsub(struct svga_shader_emitter *emit,
2758bf215546Sopenharmony_ci            unsigned position,
2759bf215546Sopenharmony_ci            const struct tgsi_full_instruction *insn)
2760bf215546Sopenharmony_ci{
2761bf215546Sopenharmony_ci   unsigned i;
2762bf215546Sopenharmony_ci
2763bf215546Sopenharmony_ci   /* Note that we've finished the main function and are now emitting
2764bf215546Sopenharmony_ci    * subroutines.  This affects how we terminate the generated
2765bf215546Sopenharmony_ci    * shader.
2766bf215546Sopenharmony_ci    */
2767bf215546Sopenharmony_ci   emit->in_main_func = FALSE;
2768bf215546Sopenharmony_ci
2769bf215546Sopenharmony_ci   for (i = 0; i < emit->nr_labels; i++) {
2770bf215546Sopenharmony_ci      if (emit->label[i] == position) {
2771bf215546Sopenharmony_ci         return (emit_instruction( emit, inst_token( SVGA3DOP_RET ) ) &&
2772bf215546Sopenharmony_ci                 emit_instruction( emit, inst_token( SVGA3DOP_LABEL ) ) &&
2773bf215546Sopenharmony_ci                 emit_src( emit, src_register( SVGA3DREG_LABEL, i )));
2774bf215546Sopenharmony_ci      }
2775bf215546Sopenharmony_ci   }
2776bf215546Sopenharmony_ci
2777bf215546Sopenharmony_ci   assert(0);
2778bf215546Sopenharmony_ci   return TRUE;
2779bf215546Sopenharmony_ci}
2780bf215546Sopenharmony_ci
2781bf215546Sopenharmony_ci
2782bf215546Sopenharmony_ci/**
2783bf215546Sopenharmony_ci * Translate/emit subroutine call instruction.
2784bf215546Sopenharmony_ci */
2785bf215546Sopenharmony_cistatic boolean
2786bf215546Sopenharmony_ciemit_call(struct svga_shader_emitter *emit,
2787bf215546Sopenharmony_ci          const struct tgsi_full_instruction *insn)
2788bf215546Sopenharmony_ci{
2789bf215546Sopenharmony_ci   unsigned position = insn->Label.Label;
2790bf215546Sopenharmony_ci   unsigned i;
2791bf215546Sopenharmony_ci
2792bf215546Sopenharmony_ci   for (i = 0; i < emit->nr_labels; i++) {
2793bf215546Sopenharmony_ci      if (emit->label[i] == position)
2794bf215546Sopenharmony_ci         break;
2795bf215546Sopenharmony_ci   }
2796bf215546Sopenharmony_ci
2797bf215546Sopenharmony_ci   if (emit->nr_labels == ARRAY_SIZE(emit->label))
2798bf215546Sopenharmony_ci      return FALSE;
2799bf215546Sopenharmony_ci
2800bf215546Sopenharmony_ci   if (i == emit->nr_labels) {
2801bf215546Sopenharmony_ci      emit->label[i] = position;
2802bf215546Sopenharmony_ci      emit->nr_labels++;
2803bf215546Sopenharmony_ci   }
2804bf215546Sopenharmony_ci
2805bf215546Sopenharmony_ci   return (emit_instruction( emit, inst_token( SVGA3DOP_CALL ) ) &&
2806bf215546Sopenharmony_ci           emit_src( emit, src_register( SVGA3DREG_LABEL, i )));
2807bf215546Sopenharmony_ci}
2808bf215546Sopenharmony_ci
2809bf215546Sopenharmony_ci
2810bf215546Sopenharmony_ci/**
2811bf215546Sopenharmony_ci * Called at the end of the shader.  Actually, emit special "fix-up"
2812bf215546Sopenharmony_ci * code for the vertex/fragment shader.
2813bf215546Sopenharmony_ci */
2814bf215546Sopenharmony_cistatic boolean
2815bf215546Sopenharmony_ciemit_end(struct svga_shader_emitter *emit)
2816bf215546Sopenharmony_ci{
2817bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
2818bf215546Sopenharmony_ci      return emit_vs_postamble( emit );
2819bf215546Sopenharmony_ci   }
2820bf215546Sopenharmony_ci   else {
2821bf215546Sopenharmony_ci      return emit_ps_postamble( emit );
2822bf215546Sopenharmony_ci   }
2823bf215546Sopenharmony_ci}
2824bf215546Sopenharmony_ci
2825bf215546Sopenharmony_ci
2826bf215546Sopenharmony_ci/**
2827bf215546Sopenharmony_ci * Translate any TGSI instruction to SVGA.
2828bf215546Sopenharmony_ci */
2829bf215546Sopenharmony_cistatic boolean
2830bf215546Sopenharmony_cisvga_emit_instruction(struct svga_shader_emitter *emit,
2831bf215546Sopenharmony_ci                      unsigned position,
2832bf215546Sopenharmony_ci                      const struct tgsi_full_instruction *insn)
2833bf215546Sopenharmony_ci{
2834bf215546Sopenharmony_ci   switch (insn->Instruction.Opcode) {
2835bf215546Sopenharmony_ci
2836bf215546Sopenharmony_ci   case TGSI_OPCODE_ARL:
2837bf215546Sopenharmony_ci      return emit_arl( emit, insn );
2838bf215546Sopenharmony_ci
2839bf215546Sopenharmony_ci   case TGSI_OPCODE_TEX:
2840bf215546Sopenharmony_ci   case TGSI_OPCODE_TXB:
2841bf215546Sopenharmony_ci   case TGSI_OPCODE_TXP:
2842bf215546Sopenharmony_ci   case TGSI_OPCODE_TXL:
2843bf215546Sopenharmony_ci   case TGSI_OPCODE_TXD:
2844bf215546Sopenharmony_ci      return emit_tex( emit, insn );
2845bf215546Sopenharmony_ci
2846bf215546Sopenharmony_ci   case TGSI_OPCODE_DDX:
2847bf215546Sopenharmony_ci   case TGSI_OPCODE_DDY:
2848bf215546Sopenharmony_ci      return emit_deriv( emit, insn );
2849bf215546Sopenharmony_ci
2850bf215546Sopenharmony_ci   case TGSI_OPCODE_BGNSUB:
2851bf215546Sopenharmony_ci      return emit_bgnsub( emit, position, insn );
2852bf215546Sopenharmony_ci
2853bf215546Sopenharmony_ci   case TGSI_OPCODE_ENDSUB:
2854bf215546Sopenharmony_ci      return TRUE;
2855bf215546Sopenharmony_ci
2856bf215546Sopenharmony_ci   case TGSI_OPCODE_CAL:
2857bf215546Sopenharmony_ci      return emit_call( emit, insn );
2858bf215546Sopenharmony_ci
2859bf215546Sopenharmony_ci   case TGSI_OPCODE_FLR:
2860bf215546Sopenharmony_ci      return emit_floor( emit, insn );
2861bf215546Sopenharmony_ci
2862bf215546Sopenharmony_ci   case TGSI_OPCODE_TRUNC:
2863bf215546Sopenharmony_ci      return emit_trunc_round( emit, insn, FALSE );
2864bf215546Sopenharmony_ci
2865bf215546Sopenharmony_ci   case TGSI_OPCODE_ROUND:
2866bf215546Sopenharmony_ci      return emit_trunc_round( emit, insn, TRUE );
2867bf215546Sopenharmony_ci
2868bf215546Sopenharmony_ci   case TGSI_OPCODE_CEIL:
2869bf215546Sopenharmony_ci      return emit_ceil( emit, insn );
2870bf215546Sopenharmony_ci
2871bf215546Sopenharmony_ci   case TGSI_OPCODE_CMP:
2872bf215546Sopenharmony_ci      return emit_cmp( emit, insn );
2873bf215546Sopenharmony_ci
2874bf215546Sopenharmony_ci   case TGSI_OPCODE_DIV:
2875bf215546Sopenharmony_ci      return emit_div( emit, insn );
2876bf215546Sopenharmony_ci
2877bf215546Sopenharmony_ci   case TGSI_OPCODE_DP2:
2878bf215546Sopenharmony_ci      return emit_dp2( emit, insn );
2879bf215546Sopenharmony_ci
2880bf215546Sopenharmony_ci   case TGSI_OPCODE_COS:
2881bf215546Sopenharmony_ci      return emit_cos( emit, insn );
2882bf215546Sopenharmony_ci
2883bf215546Sopenharmony_ci   case TGSI_OPCODE_SIN:
2884bf215546Sopenharmony_ci      return emit_sin( emit, insn );
2885bf215546Sopenharmony_ci
2886bf215546Sopenharmony_ci   case TGSI_OPCODE_END:
2887bf215546Sopenharmony_ci      /* TGSI always finishes the main func with an END */
2888bf215546Sopenharmony_ci      return emit_end( emit );
2889bf215546Sopenharmony_ci
2890bf215546Sopenharmony_ci   case TGSI_OPCODE_KILL_IF:
2891bf215546Sopenharmony_ci      return emit_cond_discard( emit, insn );
2892bf215546Sopenharmony_ci
2893bf215546Sopenharmony_ci      /* Selection opcodes.  The underlying language is fairly
2894bf215546Sopenharmony_ci       * non-orthogonal about these.
2895bf215546Sopenharmony_ci       */
2896bf215546Sopenharmony_ci   case TGSI_OPCODE_SEQ:
2897bf215546Sopenharmony_ci      return emit_select_op( emit, PIPE_FUNC_EQUAL, insn );
2898bf215546Sopenharmony_ci
2899bf215546Sopenharmony_ci   case TGSI_OPCODE_SNE:
2900bf215546Sopenharmony_ci      return emit_select_op( emit, PIPE_FUNC_NOTEQUAL, insn );
2901bf215546Sopenharmony_ci
2902bf215546Sopenharmony_ci   case TGSI_OPCODE_SGT:
2903bf215546Sopenharmony_ci      return emit_select_op( emit, PIPE_FUNC_GREATER, insn );
2904bf215546Sopenharmony_ci
2905bf215546Sopenharmony_ci   case TGSI_OPCODE_SGE:
2906bf215546Sopenharmony_ci      return emit_select_op( emit, PIPE_FUNC_GEQUAL, insn );
2907bf215546Sopenharmony_ci
2908bf215546Sopenharmony_ci   case TGSI_OPCODE_SLT:
2909bf215546Sopenharmony_ci      return emit_select_op( emit, PIPE_FUNC_LESS, insn );
2910bf215546Sopenharmony_ci
2911bf215546Sopenharmony_ci   case TGSI_OPCODE_SLE:
2912bf215546Sopenharmony_ci      return emit_select_op( emit, PIPE_FUNC_LEQUAL, insn );
2913bf215546Sopenharmony_ci
2914bf215546Sopenharmony_ci   case TGSI_OPCODE_POW:
2915bf215546Sopenharmony_ci      return emit_pow( emit, insn );
2916bf215546Sopenharmony_ci
2917bf215546Sopenharmony_ci   case TGSI_OPCODE_EX2:
2918bf215546Sopenharmony_ci      return emit_ex2( emit, insn );
2919bf215546Sopenharmony_ci
2920bf215546Sopenharmony_ci   case TGSI_OPCODE_EXP:
2921bf215546Sopenharmony_ci      return emit_exp( emit, insn );
2922bf215546Sopenharmony_ci
2923bf215546Sopenharmony_ci   case TGSI_OPCODE_LOG:
2924bf215546Sopenharmony_ci      return emit_log( emit, insn );
2925bf215546Sopenharmony_ci
2926bf215546Sopenharmony_ci   case TGSI_OPCODE_LG2:
2927bf215546Sopenharmony_ci      return emit_scalar_op1( emit, SVGA3DOP_LOG, insn );
2928bf215546Sopenharmony_ci
2929bf215546Sopenharmony_ci   case TGSI_OPCODE_RSQ:
2930bf215546Sopenharmony_ci      return emit_scalar_op1( emit, SVGA3DOP_RSQ, insn );
2931bf215546Sopenharmony_ci
2932bf215546Sopenharmony_ci   case TGSI_OPCODE_RCP:
2933bf215546Sopenharmony_ci      return emit_scalar_op1( emit, SVGA3DOP_RCP, insn );
2934bf215546Sopenharmony_ci
2935bf215546Sopenharmony_ci   case TGSI_OPCODE_CONT:
2936bf215546Sopenharmony_ci      /* not expected (we return PIPE_SHADER_CAP_CONT_SUPPORTED = 0) */
2937bf215546Sopenharmony_ci      return FALSE;
2938bf215546Sopenharmony_ci
2939bf215546Sopenharmony_ci   case TGSI_OPCODE_RET:
2940bf215546Sopenharmony_ci      /* This is a noop -- we tell mesa that we can't support RET
2941bf215546Sopenharmony_ci       * within a function (early return), so this will always be
2942bf215546Sopenharmony_ci       * followed by an ENDSUB.
2943bf215546Sopenharmony_ci       */
2944bf215546Sopenharmony_ci      return TRUE;
2945bf215546Sopenharmony_ci
2946bf215546Sopenharmony_ci      /* These aren't actually used by any of the frontends we care
2947bf215546Sopenharmony_ci       * about:
2948bf215546Sopenharmony_ci       */
2949bf215546Sopenharmony_ci   case TGSI_OPCODE_AND:
2950bf215546Sopenharmony_ci   case TGSI_OPCODE_OR:
2951bf215546Sopenharmony_ci   case TGSI_OPCODE_I2F:
2952bf215546Sopenharmony_ci   case TGSI_OPCODE_NOT:
2953bf215546Sopenharmony_ci   case TGSI_OPCODE_SHL:
2954bf215546Sopenharmony_ci   case TGSI_OPCODE_ISHR:
2955bf215546Sopenharmony_ci   case TGSI_OPCODE_XOR:
2956bf215546Sopenharmony_ci      return FALSE;
2957bf215546Sopenharmony_ci
2958bf215546Sopenharmony_ci   case TGSI_OPCODE_IF:
2959bf215546Sopenharmony_ci      return emit_if( emit, insn );
2960bf215546Sopenharmony_ci   case TGSI_OPCODE_ELSE:
2961bf215546Sopenharmony_ci      return emit_else( emit, insn );
2962bf215546Sopenharmony_ci   case TGSI_OPCODE_ENDIF:
2963bf215546Sopenharmony_ci      return emit_endif( emit, insn );
2964bf215546Sopenharmony_ci
2965bf215546Sopenharmony_ci   case TGSI_OPCODE_BGNLOOP:
2966bf215546Sopenharmony_ci      return emit_bgnloop( emit, insn );
2967bf215546Sopenharmony_ci   case TGSI_OPCODE_ENDLOOP:
2968bf215546Sopenharmony_ci      return emit_endloop( emit, insn );
2969bf215546Sopenharmony_ci   case TGSI_OPCODE_BRK:
2970bf215546Sopenharmony_ci      return emit_brk( emit, insn );
2971bf215546Sopenharmony_ci
2972bf215546Sopenharmony_ci   case TGSI_OPCODE_KILL:
2973bf215546Sopenharmony_ci      return emit_discard( emit, insn );
2974bf215546Sopenharmony_ci
2975bf215546Sopenharmony_ci   case TGSI_OPCODE_DST:
2976bf215546Sopenharmony_ci      return emit_dst_insn( emit, insn );
2977bf215546Sopenharmony_ci
2978bf215546Sopenharmony_ci   case TGSI_OPCODE_LIT:
2979bf215546Sopenharmony_ci      return emit_lit( emit, insn );
2980bf215546Sopenharmony_ci
2981bf215546Sopenharmony_ci   case TGSI_OPCODE_LRP:
2982bf215546Sopenharmony_ci      return emit_lrp( emit, insn );
2983bf215546Sopenharmony_ci
2984bf215546Sopenharmony_ci   case TGSI_OPCODE_SSG:
2985bf215546Sopenharmony_ci      return emit_ssg( emit, insn );
2986bf215546Sopenharmony_ci
2987bf215546Sopenharmony_ci   case TGSI_OPCODE_MOV:
2988bf215546Sopenharmony_ci      return emit_mov( emit, insn );
2989bf215546Sopenharmony_ci
2990bf215546Sopenharmony_ci   case TGSI_OPCODE_SQRT:
2991bf215546Sopenharmony_ci      return emit_sqrt( emit, insn );
2992bf215546Sopenharmony_ci
2993bf215546Sopenharmony_ci   default:
2994bf215546Sopenharmony_ci      {
2995bf215546Sopenharmony_ci         SVGA3dShaderOpCodeType opcode =
2996bf215546Sopenharmony_ci            translate_opcode(insn->Instruction.Opcode);
2997bf215546Sopenharmony_ci
2998bf215546Sopenharmony_ci         if (opcode == SVGA3DOP_LAST_INST)
2999bf215546Sopenharmony_ci            return FALSE;
3000bf215546Sopenharmony_ci
3001bf215546Sopenharmony_ci         if (!emit_simple_instruction( emit, opcode, insn ))
3002bf215546Sopenharmony_ci            return FALSE;
3003bf215546Sopenharmony_ci      }
3004bf215546Sopenharmony_ci   }
3005bf215546Sopenharmony_ci
3006bf215546Sopenharmony_ci   return TRUE;
3007bf215546Sopenharmony_ci}
3008bf215546Sopenharmony_ci
3009bf215546Sopenharmony_ci
3010bf215546Sopenharmony_ci/**
3011bf215546Sopenharmony_ci * Translate/emit a TGSI IMMEDIATE declaration.
3012bf215546Sopenharmony_ci * An immediate vector is a constant that's hard-coded into the shader.
3013bf215546Sopenharmony_ci */
3014bf215546Sopenharmony_cistatic boolean
3015bf215546Sopenharmony_cisvga_emit_immediate(struct svga_shader_emitter *emit,
3016bf215546Sopenharmony_ci                    const struct tgsi_full_immediate *imm)
3017bf215546Sopenharmony_ci{
3018bf215546Sopenharmony_ci   static const float id[4] = {0,0,0,1};
3019bf215546Sopenharmony_ci   float value[4];
3020bf215546Sopenharmony_ci   unsigned i;
3021bf215546Sopenharmony_ci
3022bf215546Sopenharmony_ci   assert(1 <= imm->Immediate.NrTokens && imm->Immediate.NrTokens <= 5);
3023bf215546Sopenharmony_ci   for (i = 0; i < 4 && i < imm->Immediate.NrTokens - 1; i++) {
3024bf215546Sopenharmony_ci      float f = imm->u[i].Float;
3025bf215546Sopenharmony_ci      value[i] = util_is_inf_or_nan(f) ? 0.0f : f;
3026bf215546Sopenharmony_ci   }
3027bf215546Sopenharmony_ci
3028bf215546Sopenharmony_ci   /* If the immediate has less than four values, fill in the remaining
3029bf215546Sopenharmony_ci    * positions from id={0,0,0,1}.
3030bf215546Sopenharmony_ci    */
3031bf215546Sopenharmony_ci   for ( ; i < 4; i++ )
3032bf215546Sopenharmony_ci      value[i] = id[i];
3033bf215546Sopenharmony_ci
3034bf215546Sopenharmony_ci   return emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT,
3035bf215546Sopenharmony_ci                          emit->imm_start + emit->internal_imm_count++,
3036bf215546Sopenharmony_ci                          value[0], value[1], value[2], value[3]);
3037bf215546Sopenharmony_ci}
3038bf215546Sopenharmony_ci
3039bf215546Sopenharmony_ci
3040bf215546Sopenharmony_cistatic boolean
3041bf215546Sopenharmony_cimake_immediate(struct svga_shader_emitter *emit,
3042bf215546Sopenharmony_ci               float a, float b, float c, float d,
3043bf215546Sopenharmony_ci               struct src_register *out )
3044bf215546Sopenharmony_ci{
3045bf215546Sopenharmony_ci   unsigned idx = emit->nr_hw_float_const++;
3046bf215546Sopenharmony_ci
3047bf215546Sopenharmony_ci   if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT,
3048bf215546Sopenharmony_ci                        idx, a, b, c, d ))
3049bf215546Sopenharmony_ci      return FALSE;
3050bf215546Sopenharmony_ci
3051bf215546Sopenharmony_ci   *out = src_register( SVGA3DREG_CONST, idx );
3052bf215546Sopenharmony_ci
3053bf215546Sopenharmony_ci   return TRUE;
3054bf215546Sopenharmony_ci}
3055bf215546Sopenharmony_ci
3056bf215546Sopenharmony_ci
3057bf215546Sopenharmony_ci/**
3058bf215546Sopenharmony_ci * Emit special VS instructions at top of shader.
3059bf215546Sopenharmony_ci */
3060bf215546Sopenharmony_cistatic boolean
3061bf215546Sopenharmony_ciemit_vs_preamble(struct svga_shader_emitter *emit)
3062bf215546Sopenharmony_ci{
3063bf215546Sopenharmony_ci   if (!emit->key.vs.need_prescale) {
3064bf215546Sopenharmony_ci      if (!make_immediate( emit, 0, 0, .5, .5,
3065bf215546Sopenharmony_ci                           &emit->imm_0055))
3066bf215546Sopenharmony_ci         return FALSE;
3067bf215546Sopenharmony_ci   }
3068bf215546Sopenharmony_ci
3069bf215546Sopenharmony_ci   return TRUE;
3070bf215546Sopenharmony_ci}
3071bf215546Sopenharmony_ci
3072bf215546Sopenharmony_ci
3073bf215546Sopenharmony_ci/**
3074bf215546Sopenharmony_ci * Emit special PS instructions at top of shader.
3075bf215546Sopenharmony_ci */
3076bf215546Sopenharmony_cistatic boolean
3077bf215546Sopenharmony_ciemit_ps_preamble(struct svga_shader_emitter *emit)
3078bf215546Sopenharmony_ci{
3079bf215546Sopenharmony_ci   if (emit->ps_reads_pos && emit->info.reads_z) {
3080bf215546Sopenharmony_ci      /*
3081bf215546Sopenharmony_ci       * Assemble the position from various bits of inputs. Depth and W are
3082bf215546Sopenharmony_ci       * passed in a texcoord this is due to D3D's vPos not hold Z or W.
3083bf215546Sopenharmony_ci       * Also fixup the perspective interpolation.
3084bf215546Sopenharmony_ci       *
3085bf215546Sopenharmony_ci       * temp_pos.xy = vPos.xy
3086bf215546Sopenharmony_ci       * temp_pos.w = rcp(texcoord1.w);
3087bf215546Sopenharmony_ci       * temp_pos.z = texcoord1.z * temp_pos.w;
3088bf215546Sopenharmony_ci       */
3089bf215546Sopenharmony_ci      if (!submit_op1( emit,
3090bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MOV),
3091bf215546Sopenharmony_ci                       writemask( emit->ps_temp_pos, TGSI_WRITEMASK_XY ),
3092bf215546Sopenharmony_ci                       emit->ps_true_pos ))
3093bf215546Sopenharmony_ci         return FALSE;
3094bf215546Sopenharmony_ci
3095bf215546Sopenharmony_ci      if (!submit_op1( emit,
3096bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_RCP),
3097bf215546Sopenharmony_ci                       writemask( emit->ps_temp_pos, TGSI_WRITEMASK_W ),
3098bf215546Sopenharmony_ci                       scalar( emit->ps_depth_pos, TGSI_SWIZZLE_W ) ))
3099bf215546Sopenharmony_ci         return FALSE;
3100bf215546Sopenharmony_ci
3101bf215546Sopenharmony_ci      if (!submit_op2( emit,
3102bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MUL),
3103bf215546Sopenharmony_ci                       writemask( emit->ps_temp_pos, TGSI_WRITEMASK_Z ),
3104bf215546Sopenharmony_ci                       scalar( emit->ps_depth_pos, TGSI_SWIZZLE_Z ),
3105bf215546Sopenharmony_ci                       scalar( src(emit->ps_temp_pos), TGSI_SWIZZLE_W ) ))
3106bf215546Sopenharmony_ci         return FALSE;
3107bf215546Sopenharmony_ci   }
3108bf215546Sopenharmony_ci
3109bf215546Sopenharmony_ci   return TRUE;
3110bf215546Sopenharmony_ci}
3111bf215546Sopenharmony_ci
3112bf215546Sopenharmony_ci
3113bf215546Sopenharmony_ci/**
3114bf215546Sopenharmony_ci * Emit special PS instructions at end of shader.
3115bf215546Sopenharmony_ci */
3116bf215546Sopenharmony_cistatic boolean
3117bf215546Sopenharmony_ciemit_ps_postamble(struct svga_shader_emitter *emit)
3118bf215546Sopenharmony_ci{
3119bf215546Sopenharmony_ci   unsigned i;
3120bf215546Sopenharmony_ci
3121bf215546Sopenharmony_ci   /* PS oDepth is incredibly fragile and it's very hard to catch the
3122bf215546Sopenharmony_ci    * types of usage that break it during shader emit.  Easier just to
3123bf215546Sopenharmony_ci    * redirect the main program to a temporary and then only touch
3124bf215546Sopenharmony_ci    * oDepth with a hand-crafted MOV below.
3125bf215546Sopenharmony_ci    */
3126bf215546Sopenharmony_ci   if (SVGA3dShaderGetRegType(emit->true_pos.value) != 0) {
3127bf215546Sopenharmony_ci      if (!submit_op1( emit,
3128bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MOV),
3129bf215546Sopenharmony_ci                       emit->true_pos,
3130bf215546Sopenharmony_ci                       scalar(src(emit->temp_pos), TGSI_SWIZZLE_Z) ))
3131bf215546Sopenharmony_ci         return FALSE;
3132bf215546Sopenharmony_ci   }
3133bf215546Sopenharmony_ci
3134bf215546Sopenharmony_ci   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
3135bf215546Sopenharmony_ci      if (SVGA3dShaderGetRegType(emit->true_color_output[i].value) != 0) {
3136bf215546Sopenharmony_ci         /* Potentially override output colors with white for XOR
3137bf215546Sopenharmony_ci          * logicop workaround.
3138bf215546Sopenharmony_ci          */
3139bf215546Sopenharmony_ci         if (emit->unit == PIPE_SHADER_FRAGMENT &&
3140bf215546Sopenharmony_ci             emit->key.fs.white_fragments) {
3141bf215546Sopenharmony_ci            struct src_register one = get_one_immediate(emit);
3142bf215546Sopenharmony_ci
3143bf215546Sopenharmony_ci            if (!submit_op1( emit,
3144bf215546Sopenharmony_ci                             inst_token(SVGA3DOP_MOV),
3145bf215546Sopenharmony_ci                             emit->true_color_output[i],
3146bf215546Sopenharmony_ci                             one ))
3147bf215546Sopenharmony_ci               return FALSE;
3148bf215546Sopenharmony_ci         }
3149bf215546Sopenharmony_ci         else if (emit->unit == PIPE_SHADER_FRAGMENT &&
3150bf215546Sopenharmony_ci                  i < emit->key.fs.write_color0_to_n_cbufs) {
3151bf215546Sopenharmony_ci            /* Write temp color output [0] to true output [i] */
3152bf215546Sopenharmony_ci            if (!submit_op1(emit, inst_token(SVGA3DOP_MOV),
3153bf215546Sopenharmony_ci                            emit->true_color_output[i],
3154bf215546Sopenharmony_ci                            src(emit->temp_color_output[0]))) {
3155bf215546Sopenharmony_ci               return FALSE;
3156bf215546Sopenharmony_ci            }
3157bf215546Sopenharmony_ci         }
3158bf215546Sopenharmony_ci         else {
3159bf215546Sopenharmony_ci            if (!submit_op1( emit,
3160bf215546Sopenharmony_ci                             inst_token(SVGA3DOP_MOV),
3161bf215546Sopenharmony_ci                             emit->true_color_output[i],
3162bf215546Sopenharmony_ci                             src(emit->temp_color_output[i]) ))
3163bf215546Sopenharmony_ci               return FALSE;
3164bf215546Sopenharmony_ci         }
3165bf215546Sopenharmony_ci      }
3166bf215546Sopenharmony_ci   }
3167bf215546Sopenharmony_ci
3168bf215546Sopenharmony_ci   return TRUE;
3169bf215546Sopenharmony_ci}
3170bf215546Sopenharmony_ci
3171bf215546Sopenharmony_ci
3172bf215546Sopenharmony_ci/**
3173bf215546Sopenharmony_ci * Emit special VS instructions at end of shader.
3174bf215546Sopenharmony_ci */
3175bf215546Sopenharmony_cistatic boolean
3176bf215546Sopenharmony_ciemit_vs_postamble(struct svga_shader_emitter *emit)
3177bf215546Sopenharmony_ci{
3178bf215546Sopenharmony_ci   /* PSIZ output is incredibly fragile and it's very hard to catch
3179bf215546Sopenharmony_ci    * the types of usage that break it during shader emit.  Easier
3180bf215546Sopenharmony_ci    * just to redirect the main program to a temporary and then only
3181bf215546Sopenharmony_ci    * touch PSIZ with a hand-crafted MOV below.
3182bf215546Sopenharmony_ci    */
3183bf215546Sopenharmony_ci   if (SVGA3dShaderGetRegType(emit->true_psiz.value) != 0) {
3184bf215546Sopenharmony_ci      if (!submit_op1( emit,
3185bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MOV),
3186bf215546Sopenharmony_ci                       emit->true_psiz,
3187bf215546Sopenharmony_ci                       scalar(src(emit->temp_psiz), TGSI_SWIZZLE_X) ))
3188bf215546Sopenharmony_ci         return FALSE;
3189bf215546Sopenharmony_ci   }
3190bf215546Sopenharmony_ci
3191bf215546Sopenharmony_ci   /* Need to perform various manipulations on vertex position to cope
3192bf215546Sopenharmony_ci    * with the different GL and D3D clip spaces.
3193bf215546Sopenharmony_ci    */
3194bf215546Sopenharmony_ci   if (emit->key.vs.need_prescale) {
3195bf215546Sopenharmony_ci      SVGA3dShaderDestToken temp_pos = emit->temp_pos;
3196bf215546Sopenharmony_ci      SVGA3dShaderDestToken depth = emit->depth_pos;
3197bf215546Sopenharmony_ci      SVGA3dShaderDestToken pos = emit->true_pos;
3198bf215546Sopenharmony_ci      unsigned offset = emit->info.file_max[TGSI_FILE_CONSTANT] + 1;
3199bf215546Sopenharmony_ci      struct src_register prescale_scale = src_register( SVGA3DREG_CONST,
3200bf215546Sopenharmony_ci                                                         offset + 0 );
3201bf215546Sopenharmony_ci      struct src_register prescale_trans = src_register( SVGA3DREG_CONST,
3202bf215546Sopenharmony_ci                                                         offset + 1 );
3203bf215546Sopenharmony_ci
3204bf215546Sopenharmony_ci      if (!submit_op1( emit,
3205bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MOV),
3206bf215546Sopenharmony_ci                       writemask(depth, TGSI_WRITEMASK_W),
3207bf215546Sopenharmony_ci                       scalar(src(temp_pos), TGSI_SWIZZLE_W) ))
3208bf215546Sopenharmony_ci         return FALSE;
3209bf215546Sopenharmony_ci
3210bf215546Sopenharmony_ci      /* MUL temp_pos.xyz,    temp_pos,      prescale.scale
3211bf215546Sopenharmony_ci       * MAD result.position, temp_pos.wwww, prescale.trans, temp_pos
3212bf215546Sopenharmony_ci       *   --> Note that prescale.trans.w == 0
3213bf215546Sopenharmony_ci       */
3214bf215546Sopenharmony_ci      if (!submit_op2( emit,
3215bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MUL),
3216bf215546Sopenharmony_ci                       writemask(temp_pos, TGSI_WRITEMASK_XYZ),
3217bf215546Sopenharmony_ci                       src(temp_pos),
3218bf215546Sopenharmony_ci                       prescale_scale ))
3219bf215546Sopenharmony_ci         return FALSE;
3220bf215546Sopenharmony_ci
3221bf215546Sopenharmony_ci      if (!submit_op3( emit,
3222bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MAD),
3223bf215546Sopenharmony_ci                       pos,
3224bf215546Sopenharmony_ci                       swizzle(src(temp_pos), 3, 3, 3, 3),
3225bf215546Sopenharmony_ci                       prescale_trans,
3226bf215546Sopenharmony_ci                       src(temp_pos)))
3227bf215546Sopenharmony_ci         return FALSE;
3228bf215546Sopenharmony_ci
3229bf215546Sopenharmony_ci      /* Also write to depth value */
3230bf215546Sopenharmony_ci      if (!submit_op3( emit,
3231bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MAD),
3232bf215546Sopenharmony_ci                       writemask(depth, TGSI_WRITEMASK_Z),
3233bf215546Sopenharmony_ci                       swizzle(src(temp_pos), 3, 3, 3, 3),
3234bf215546Sopenharmony_ci                       prescale_trans,
3235bf215546Sopenharmony_ci                       src(temp_pos) ))
3236bf215546Sopenharmony_ci         return FALSE;
3237bf215546Sopenharmony_ci   }
3238bf215546Sopenharmony_ci   else {
3239bf215546Sopenharmony_ci      SVGA3dShaderDestToken temp_pos = emit->temp_pos;
3240bf215546Sopenharmony_ci      SVGA3dShaderDestToken depth = emit->depth_pos;
3241bf215546Sopenharmony_ci      SVGA3dShaderDestToken pos = emit->true_pos;
3242bf215546Sopenharmony_ci      struct src_register imm_0055 = emit->imm_0055;
3243bf215546Sopenharmony_ci
3244bf215546Sopenharmony_ci      /* Adjust GL clipping coordinate space to hardware (D3D-style):
3245bf215546Sopenharmony_ci       *
3246bf215546Sopenharmony_ci       * DP4 temp_pos.z, {0,0,.5,.5}, temp_pos
3247bf215546Sopenharmony_ci       * MOV result.position, temp_pos
3248bf215546Sopenharmony_ci       */
3249bf215546Sopenharmony_ci      if (!submit_op2( emit,
3250bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_DP4),
3251bf215546Sopenharmony_ci                       writemask(temp_pos, TGSI_WRITEMASK_Z),
3252bf215546Sopenharmony_ci                       imm_0055,
3253bf215546Sopenharmony_ci                       src(temp_pos) ))
3254bf215546Sopenharmony_ci         return FALSE;
3255bf215546Sopenharmony_ci
3256bf215546Sopenharmony_ci      if (!submit_op1( emit,
3257bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MOV),
3258bf215546Sopenharmony_ci                       pos,
3259bf215546Sopenharmony_ci                       src(temp_pos) ))
3260bf215546Sopenharmony_ci         return FALSE;
3261bf215546Sopenharmony_ci
3262bf215546Sopenharmony_ci      /* Move the manipulated depth into the extra texcoord reg */
3263bf215546Sopenharmony_ci      if (!submit_op1( emit,
3264bf215546Sopenharmony_ci                       inst_token(SVGA3DOP_MOV),
3265bf215546Sopenharmony_ci                       writemask(depth, TGSI_WRITEMASK_ZW),
3266bf215546Sopenharmony_ci                       src(temp_pos) ))
3267bf215546Sopenharmony_ci         return FALSE;
3268bf215546Sopenharmony_ci   }
3269bf215546Sopenharmony_ci
3270bf215546Sopenharmony_ci   return TRUE;
3271bf215546Sopenharmony_ci}
3272bf215546Sopenharmony_ci
3273bf215546Sopenharmony_ci
3274bf215546Sopenharmony_ci/**
3275bf215546Sopenharmony_ci * For the pixel shader: emit the code which chooses the front
3276bf215546Sopenharmony_ci * or back face color depending on triangle orientation.
3277bf215546Sopenharmony_ci * This happens at the top of the fragment shader.
3278bf215546Sopenharmony_ci *
3279bf215546Sopenharmony_ci *  0: IF VFACE :4
3280bf215546Sopenharmony_ci *  1:   COLOR = FrontColor;
3281bf215546Sopenharmony_ci *  2: ELSE
3282bf215546Sopenharmony_ci *  3:   COLOR = BackColor;
3283bf215546Sopenharmony_ci *  4: ENDIF
3284bf215546Sopenharmony_ci */
3285bf215546Sopenharmony_cistatic boolean
3286bf215546Sopenharmony_ciemit_light_twoside(struct svga_shader_emitter *emit)
3287bf215546Sopenharmony_ci{
3288bf215546Sopenharmony_ci   struct src_register vface, zero;
3289bf215546Sopenharmony_ci   struct src_register front[2];
3290bf215546Sopenharmony_ci   struct src_register back[2];
3291bf215546Sopenharmony_ci   SVGA3dShaderDestToken color[2];
3292bf215546Sopenharmony_ci   int count = emit->internal_color_count;
3293bf215546Sopenharmony_ci   unsigned i;
3294bf215546Sopenharmony_ci   SVGA3dShaderInstToken if_token;
3295bf215546Sopenharmony_ci
3296bf215546Sopenharmony_ci   if (count == 0)
3297bf215546Sopenharmony_ci      return TRUE;
3298bf215546Sopenharmony_ci
3299bf215546Sopenharmony_ci   vface = get_vface( emit );
3300bf215546Sopenharmony_ci   zero = get_zero_immediate(emit);
3301bf215546Sopenharmony_ci
3302bf215546Sopenharmony_ci   /* Can't use get_temp() to allocate the color reg as such
3303bf215546Sopenharmony_ci    * temporaries will be reclaimed after each instruction by the call
3304bf215546Sopenharmony_ci    * to reset_temp_regs().
3305bf215546Sopenharmony_ci    */
3306bf215546Sopenharmony_ci   for (i = 0; i < count; i++) {
3307bf215546Sopenharmony_ci      color[i] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ );
3308bf215546Sopenharmony_ci      front[i] = emit->input_map[emit->internal_color_idx[i]];
3309bf215546Sopenharmony_ci
3310bf215546Sopenharmony_ci      /* Back is always the next input:
3311bf215546Sopenharmony_ci       */
3312bf215546Sopenharmony_ci      back[i] = front[i];
3313bf215546Sopenharmony_ci      back[i].base.num = front[i].base.num + 1;
3314bf215546Sopenharmony_ci
3315bf215546Sopenharmony_ci      /* Reassign the input_map to the actual front-face color:
3316bf215546Sopenharmony_ci       */
3317bf215546Sopenharmony_ci      emit->input_map[emit->internal_color_idx[i]] = src(color[i]);
3318bf215546Sopenharmony_ci   }
3319bf215546Sopenharmony_ci
3320bf215546Sopenharmony_ci   if_token = inst_token( SVGA3DOP_IFC );
3321bf215546Sopenharmony_ci
3322bf215546Sopenharmony_ci   if (emit->key.fs.front_ccw)
3323bf215546Sopenharmony_ci      if_token.control = SVGA3DOPCOMP_LT;
3324bf215546Sopenharmony_ci   else
3325bf215546Sopenharmony_ci      if_token.control = SVGA3DOPCOMP_GT;
3326bf215546Sopenharmony_ci
3327bf215546Sopenharmony_ci   if (!(emit_instruction( emit, if_token ) &&
3328bf215546Sopenharmony_ci         emit_src( emit, vface ) &&
3329bf215546Sopenharmony_ci         emit_src( emit, zero ) ))
3330bf215546Sopenharmony_ci      return FALSE;
3331bf215546Sopenharmony_ci
3332bf215546Sopenharmony_ci   for (i = 0; i < count; i++) {
3333bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), color[i], front[i] ))
3334bf215546Sopenharmony_ci         return FALSE;
3335bf215546Sopenharmony_ci   }
3336bf215546Sopenharmony_ci
3337bf215546Sopenharmony_ci   if (!(emit_instruction( emit, inst_token( SVGA3DOP_ELSE))))
3338bf215546Sopenharmony_ci      return FALSE;
3339bf215546Sopenharmony_ci
3340bf215546Sopenharmony_ci   for (i = 0; i < count; i++) {
3341bf215546Sopenharmony_ci      if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), color[i], back[i] ))
3342bf215546Sopenharmony_ci         return FALSE;
3343bf215546Sopenharmony_ci   }
3344bf215546Sopenharmony_ci
3345bf215546Sopenharmony_ci   if (!emit_instruction( emit, inst_token( SVGA3DOP_ENDIF ) ))
3346bf215546Sopenharmony_ci      return FALSE;
3347bf215546Sopenharmony_ci
3348bf215546Sopenharmony_ci   return TRUE;
3349bf215546Sopenharmony_ci}
3350bf215546Sopenharmony_ci
3351bf215546Sopenharmony_ci
3352bf215546Sopenharmony_ci/**
3353bf215546Sopenharmony_ci * Emit special setup code for the front/back face register in the FS.
3354bf215546Sopenharmony_ci *  0: SETP_GT TEMP, VFACE, 0
3355bf215546Sopenharmony_ci *  where TEMP is a fake frontface register
3356bf215546Sopenharmony_ci */
3357bf215546Sopenharmony_cistatic boolean
3358bf215546Sopenharmony_ciemit_frontface(struct svga_shader_emitter *emit)
3359bf215546Sopenharmony_ci{
3360bf215546Sopenharmony_ci   struct src_register vface;
3361bf215546Sopenharmony_ci   SVGA3dShaderDestToken temp;
3362bf215546Sopenharmony_ci   struct src_register pass, fail;
3363bf215546Sopenharmony_ci
3364bf215546Sopenharmony_ci   vface = get_vface( emit );
3365bf215546Sopenharmony_ci
3366bf215546Sopenharmony_ci   /* Can't use get_temp() to allocate the fake frontface reg as such
3367bf215546Sopenharmony_ci    * temporaries will be reclaimed after each instruction by the call
3368bf215546Sopenharmony_ci    * to reset_temp_regs().
3369bf215546Sopenharmony_ci    */
3370bf215546Sopenharmony_ci   temp = dst_register( SVGA3DREG_TEMP,
3371bf215546Sopenharmony_ci                        emit->nr_hw_temp++ );
3372bf215546Sopenharmony_ci
3373bf215546Sopenharmony_ci   if (emit->key.fs.front_ccw) {
3374bf215546Sopenharmony_ci      pass = get_zero_immediate(emit);
3375bf215546Sopenharmony_ci      fail = get_one_immediate(emit);
3376bf215546Sopenharmony_ci   } else {
3377bf215546Sopenharmony_ci      pass = get_one_immediate(emit);
3378bf215546Sopenharmony_ci      fail = get_zero_immediate(emit);
3379bf215546Sopenharmony_ci   }
3380bf215546Sopenharmony_ci
3381bf215546Sopenharmony_ci   if (!emit_conditional(emit, PIPE_FUNC_GREATER,
3382bf215546Sopenharmony_ci                         temp, vface, get_zero_immediate(emit),
3383bf215546Sopenharmony_ci                         pass, fail))
3384bf215546Sopenharmony_ci      return FALSE;
3385bf215546Sopenharmony_ci
3386bf215546Sopenharmony_ci   /* Reassign the input_map to the actual front-face color:
3387bf215546Sopenharmony_ci    */
3388bf215546Sopenharmony_ci   emit->input_map[emit->internal_frontface_idx] = src(temp);
3389bf215546Sopenharmony_ci
3390bf215546Sopenharmony_ci   return TRUE;
3391bf215546Sopenharmony_ci}
3392bf215546Sopenharmony_ci
3393bf215546Sopenharmony_ci
3394bf215546Sopenharmony_ci/**
3395bf215546Sopenharmony_ci * Emit code to invert the T component of the incoming texture coordinate.
3396bf215546Sopenharmony_ci * This is used for drawing point sprites when
3397bf215546Sopenharmony_ci * pipe_rasterizer_state::sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT.
3398bf215546Sopenharmony_ci */
3399bf215546Sopenharmony_cistatic boolean
3400bf215546Sopenharmony_ciemit_inverted_texcoords(struct svga_shader_emitter *emit)
3401bf215546Sopenharmony_ci{
3402bf215546Sopenharmony_ci   unsigned inverted_texcoords = emit->inverted_texcoords;
3403bf215546Sopenharmony_ci
3404bf215546Sopenharmony_ci   while (inverted_texcoords) {
3405bf215546Sopenharmony_ci      const unsigned unit = ffs(inverted_texcoords) - 1;
3406bf215546Sopenharmony_ci
3407bf215546Sopenharmony_ci      assert(emit->inverted_texcoords & (1 << unit));
3408bf215546Sopenharmony_ci
3409bf215546Sopenharmony_ci      assert(unit < ARRAY_SIZE(emit->ps_true_texcoord));
3410bf215546Sopenharmony_ci
3411bf215546Sopenharmony_ci      assert(unit < ARRAY_SIZE(emit->ps_inverted_texcoord_input));
3412bf215546Sopenharmony_ci
3413bf215546Sopenharmony_ci      assert(emit->ps_inverted_texcoord_input[unit]
3414bf215546Sopenharmony_ci             < ARRAY_SIZE(emit->input_map));
3415bf215546Sopenharmony_ci
3416bf215546Sopenharmony_ci      /* inverted = coord * (1, -1, 1, 1) + (0, 1, 0, 0) */
3417bf215546Sopenharmony_ci      if (!submit_op3(emit,
3418bf215546Sopenharmony_ci                      inst_token(SVGA3DOP_MAD),
3419bf215546Sopenharmony_ci                      dst(emit->ps_inverted_texcoord[unit]),
3420bf215546Sopenharmony_ci                      emit->ps_true_texcoord[unit],
3421bf215546Sopenharmony_ci                      get_immediate(emit, 1.0f, -1.0f, 1.0f, 1.0f),
3422bf215546Sopenharmony_ci                      get_immediate(emit, 0.0f, 1.0f, 0.0f, 0.0f)))
3423bf215546Sopenharmony_ci         return FALSE;
3424bf215546Sopenharmony_ci
3425bf215546Sopenharmony_ci      /* Reassign the input_map entry to the new texcoord register */
3426bf215546Sopenharmony_ci      emit->input_map[emit->ps_inverted_texcoord_input[unit]] =
3427bf215546Sopenharmony_ci         emit->ps_inverted_texcoord[unit];
3428bf215546Sopenharmony_ci
3429bf215546Sopenharmony_ci      inverted_texcoords &= ~(1 << unit);
3430bf215546Sopenharmony_ci   }
3431bf215546Sopenharmony_ci
3432bf215546Sopenharmony_ci   return TRUE;
3433bf215546Sopenharmony_ci}
3434bf215546Sopenharmony_ci
3435bf215546Sopenharmony_ci
3436bf215546Sopenharmony_ci/**
3437bf215546Sopenharmony_ci * Emit code to adjust vertex shader inputs/attributes:
3438bf215546Sopenharmony_ci * - Change range from [0,1] to [-1,1] (for normalized byte/short attribs).
3439bf215546Sopenharmony_ci * - Set attrib W component = 1.
3440bf215546Sopenharmony_ci */
3441bf215546Sopenharmony_cistatic boolean
3442bf215546Sopenharmony_ciemit_adjusted_vertex_attribs(struct svga_shader_emitter *emit)
3443bf215546Sopenharmony_ci{
3444bf215546Sopenharmony_ci   unsigned adjust_mask = (emit->key.vs.adjust_attrib_range |
3445bf215546Sopenharmony_ci                           emit->key.vs.adjust_attrib_w_1);
3446bf215546Sopenharmony_ci
3447bf215546Sopenharmony_ci   while (adjust_mask) {
3448bf215546Sopenharmony_ci      /* Adjust vertex attrib range and/or set W component = 1 */
3449bf215546Sopenharmony_ci      const unsigned index = u_bit_scan(&adjust_mask);
3450bf215546Sopenharmony_ci      struct src_register tmp;
3451bf215546Sopenharmony_ci
3452bf215546Sopenharmony_ci      /* allocate a temp reg */
3453bf215546Sopenharmony_ci      tmp = src_register(SVGA3DREG_TEMP, emit->nr_hw_temp);
3454bf215546Sopenharmony_ci      emit->nr_hw_temp++;
3455bf215546Sopenharmony_ci
3456bf215546Sopenharmony_ci      if (emit->key.vs.adjust_attrib_range & (1 << index)) {
3457bf215546Sopenharmony_ci         /* The vertex input/attribute is supposed to be a signed value in
3458bf215546Sopenharmony_ci          * the range [-1,1] but we actually fetched/converted it to the
3459bf215546Sopenharmony_ci          * range [0,1].  This most likely happens when the app specifies a
3460bf215546Sopenharmony_ci          * signed byte attribute but we interpreted it as unsigned bytes.
3461bf215546Sopenharmony_ci          * See also svga_translate_vertex_format().
3462bf215546Sopenharmony_ci          *
3463bf215546Sopenharmony_ci          * Here, we emit some extra instructions to adjust
3464bf215546Sopenharmony_ci          * the attribute values from [0,1] to [-1,1].
3465bf215546Sopenharmony_ci          *
3466bf215546Sopenharmony_ci          * The adjustment we implement is:
3467bf215546Sopenharmony_ci          *   new_attrib = attrib * 2.0;
3468bf215546Sopenharmony_ci          *   if (attrib >= 0.5)
3469bf215546Sopenharmony_ci          *      new_attrib = new_attrib - 2.0;
3470bf215546Sopenharmony_ci          * This isn't exactly right (it's off by a bit or so) but close enough.
3471bf215546Sopenharmony_ci          */
3472bf215546Sopenharmony_ci         SVGA3dShaderDestToken pred_reg = dst_register(SVGA3DREG_PREDICATE, 0);
3473bf215546Sopenharmony_ci
3474bf215546Sopenharmony_ci         /* tmp = attrib * 2.0 */
3475bf215546Sopenharmony_ci         if (!submit_op2(emit,
3476bf215546Sopenharmony_ci                         inst_token(SVGA3DOP_MUL),
3477bf215546Sopenharmony_ci                         dst(tmp),
3478bf215546Sopenharmony_ci                         emit->input_map[index],
3479bf215546Sopenharmony_ci                         get_two_immediate(emit)))
3480bf215546Sopenharmony_ci            return FALSE;
3481bf215546Sopenharmony_ci
3482bf215546Sopenharmony_ci         /* pred = (attrib >= 0.5) */
3483bf215546Sopenharmony_ci         if (!submit_op2(emit,
3484bf215546Sopenharmony_ci                         inst_token_setp(SVGA3DOPCOMP_GE),
3485bf215546Sopenharmony_ci                         pred_reg,
3486bf215546Sopenharmony_ci                         emit->input_map[index],  /* vert attrib */
3487bf215546Sopenharmony_ci                         get_half_immediate(emit)))  /* 0.5 */
3488bf215546Sopenharmony_ci            return FALSE;
3489bf215546Sopenharmony_ci
3490bf215546Sopenharmony_ci         /* sub(pred) tmp, tmp, 2.0 */
3491bf215546Sopenharmony_ci         if (!submit_op3(emit,
3492bf215546Sopenharmony_ci                         inst_token_predicated(SVGA3DOP_SUB),
3493bf215546Sopenharmony_ci                         dst(tmp),
3494bf215546Sopenharmony_ci                         src(pred_reg),
3495bf215546Sopenharmony_ci                         tmp,
3496bf215546Sopenharmony_ci                         get_two_immediate(emit)))
3497bf215546Sopenharmony_ci            return FALSE;
3498bf215546Sopenharmony_ci      }
3499bf215546Sopenharmony_ci      else {
3500bf215546Sopenharmony_ci         /* just copy the vertex input attrib to the temp register */
3501bf215546Sopenharmony_ci         if (!submit_op1(emit,
3502bf215546Sopenharmony_ci                         inst_token(SVGA3DOP_MOV),
3503bf215546Sopenharmony_ci                         dst(tmp),
3504bf215546Sopenharmony_ci                         emit->input_map[index]))
3505bf215546Sopenharmony_ci            return FALSE;
3506bf215546Sopenharmony_ci      }
3507bf215546Sopenharmony_ci
3508bf215546Sopenharmony_ci      if (emit->key.vs.adjust_attrib_w_1 & (1 << index)) {
3509bf215546Sopenharmony_ci         /* move 1 into W position of tmp */
3510bf215546Sopenharmony_ci         if (!submit_op1(emit,
3511bf215546Sopenharmony_ci                         inst_token(SVGA3DOP_MOV),
3512bf215546Sopenharmony_ci                         writemask(dst(tmp), TGSI_WRITEMASK_W),
3513bf215546Sopenharmony_ci                         get_one_immediate(emit)))
3514bf215546Sopenharmony_ci            return FALSE;
3515bf215546Sopenharmony_ci      }
3516bf215546Sopenharmony_ci
3517bf215546Sopenharmony_ci      /* Reassign the input_map entry to the new tmp register */
3518bf215546Sopenharmony_ci      emit->input_map[index] = tmp;
3519bf215546Sopenharmony_ci   }
3520bf215546Sopenharmony_ci
3521bf215546Sopenharmony_ci   return TRUE;
3522bf215546Sopenharmony_ci}
3523bf215546Sopenharmony_ci
3524bf215546Sopenharmony_ci
3525bf215546Sopenharmony_ci/**
3526bf215546Sopenharmony_ci * Determine if we need to create the "common" immediate value which is
3527bf215546Sopenharmony_ci * used for generating useful vector constants such as {0,0,0,0} and
3528bf215546Sopenharmony_ci * {1,1,1,1}.
3529bf215546Sopenharmony_ci * We could just do this all the time except that we want to conserve
3530bf215546Sopenharmony_ci * registers whenever possible.
3531bf215546Sopenharmony_ci */
3532bf215546Sopenharmony_cistatic boolean
3533bf215546Sopenharmony_cineeds_to_create_common_immediate(const struct svga_shader_emitter *emit)
3534bf215546Sopenharmony_ci{
3535bf215546Sopenharmony_ci   unsigned i;
3536bf215546Sopenharmony_ci
3537bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_FRAGMENT) {
3538bf215546Sopenharmony_ci      if (emit->key.fs.light_twoside)
3539bf215546Sopenharmony_ci         return TRUE;
3540bf215546Sopenharmony_ci
3541bf215546Sopenharmony_ci      if (emit->key.fs.white_fragments)
3542bf215546Sopenharmony_ci         return TRUE;
3543bf215546Sopenharmony_ci
3544bf215546Sopenharmony_ci      if (emit->emit_frontface)
3545bf215546Sopenharmony_ci         return TRUE;
3546bf215546Sopenharmony_ci
3547bf215546Sopenharmony_ci      if (emit->info.opcode_count[TGSI_OPCODE_DST] >= 1 ||
3548bf215546Sopenharmony_ci          emit->info.opcode_count[TGSI_OPCODE_SSG] >= 1 ||
3549bf215546Sopenharmony_ci          emit->info.opcode_count[TGSI_OPCODE_LIT] >= 1)
3550bf215546Sopenharmony_ci         return TRUE;
3551bf215546Sopenharmony_ci
3552bf215546Sopenharmony_ci      if (emit->inverted_texcoords)
3553bf215546Sopenharmony_ci         return TRUE;
3554bf215546Sopenharmony_ci
3555bf215546Sopenharmony_ci      /* look for any PIPE_SWIZZLE_0/ONE terms */
3556bf215546Sopenharmony_ci      for (i = 0; i < emit->key.num_textures; i++) {
3557bf215546Sopenharmony_ci         if (emit->key.tex[i].swizzle_r > PIPE_SWIZZLE_W ||
3558bf215546Sopenharmony_ci             emit->key.tex[i].swizzle_g > PIPE_SWIZZLE_W ||
3559bf215546Sopenharmony_ci             emit->key.tex[i].swizzle_b > PIPE_SWIZZLE_W ||
3560bf215546Sopenharmony_ci             emit->key.tex[i].swizzle_a > PIPE_SWIZZLE_W)
3561bf215546Sopenharmony_ci            return TRUE;
3562bf215546Sopenharmony_ci      }
3563bf215546Sopenharmony_ci
3564bf215546Sopenharmony_ci      for (i = 0; i < emit->key.num_textures; i++) {
3565bf215546Sopenharmony_ci         if (emit->key.tex[i].compare_mode
3566bf215546Sopenharmony_ci             == PIPE_TEX_COMPARE_R_TO_TEXTURE)
3567bf215546Sopenharmony_ci            return TRUE;
3568bf215546Sopenharmony_ci      }
3569bf215546Sopenharmony_ci   }
3570bf215546Sopenharmony_ci   else if (emit->unit == PIPE_SHADER_VERTEX) {
3571bf215546Sopenharmony_ci      if (emit->info.opcode_count[TGSI_OPCODE_CMP] >= 1)
3572bf215546Sopenharmony_ci         return TRUE;
3573bf215546Sopenharmony_ci      if (emit->key.vs.adjust_attrib_range ||
3574bf215546Sopenharmony_ci          emit->key.vs.adjust_attrib_w_1)
3575bf215546Sopenharmony_ci         return TRUE;
3576bf215546Sopenharmony_ci   }
3577bf215546Sopenharmony_ci
3578bf215546Sopenharmony_ci   if (emit->info.opcode_count[TGSI_OPCODE_IF] >= 1 ||
3579bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1 ||
3580bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_DDX] >= 1 ||
3581bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_DDY] >= 1 ||
3582bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_ROUND] >= 1 ||
3583bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_SGE] >= 1 ||
3584bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_SGT] >= 1 ||
3585bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_SLE] >= 1 ||
3586bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_SLT] >= 1 ||
3587bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_SNE] >= 1 ||
3588bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_SEQ] >= 1 ||
3589bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_EXP] >= 1 ||
3590bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_LOG] >= 1 ||
3591bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_KILL] >= 1 ||
3592bf215546Sopenharmony_ci       emit->info.opcode_count[TGSI_OPCODE_SQRT] >= 1)
3593bf215546Sopenharmony_ci      return TRUE;
3594bf215546Sopenharmony_ci
3595bf215546Sopenharmony_ci   return FALSE;
3596bf215546Sopenharmony_ci}
3597bf215546Sopenharmony_ci
3598bf215546Sopenharmony_ci
3599bf215546Sopenharmony_ci/**
3600bf215546Sopenharmony_ci * Do we need to create a looping constant?
3601bf215546Sopenharmony_ci */
3602bf215546Sopenharmony_cistatic boolean
3603bf215546Sopenharmony_cineeds_to_create_loop_const(const struct svga_shader_emitter *emit)
3604bf215546Sopenharmony_ci{
3605bf215546Sopenharmony_ci   return (emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1);
3606bf215546Sopenharmony_ci}
3607bf215546Sopenharmony_ci
3608bf215546Sopenharmony_ci
3609bf215546Sopenharmony_cistatic boolean
3610bf215546Sopenharmony_cineeds_to_create_arl_consts(const struct svga_shader_emitter *emit)
3611bf215546Sopenharmony_ci{
3612bf215546Sopenharmony_ci   return (emit->num_arl_consts > 0);
3613bf215546Sopenharmony_ci}
3614bf215546Sopenharmony_ci
3615bf215546Sopenharmony_ci
3616bf215546Sopenharmony_cistatic boolean
3617bf215546Sopenharmony_cipre_parse_add_indirect( struct svga_shader_emitter *emit,
3618bf215546Sopenharmony_ci                        int num, int current_arl)
3619bf215546Sopenharmony_ci{
3620bf215546Sopenharmony_ci   unsigned i;
3621bf215546Sopenharmony_ci   assert(num < 0);
3622bf215546Sopenharmony_ci
3623bf215546Sopenharmony_ci   for (i = 0; i < emit->num_arl_consts; ++i) {
3624bf215546Sopenharmony_ci      if (emit->arl_consts[i].arl_num == current_arl)
3625bf215546Sopenharmony_ci         break;
3626bf215546Sopenharmony_ci   }
3627bf215546Sopenharmony_ci   /* new entry */
3628bf215546Sopenharmony_ci   if (emit->num_arl_consts == i) {
3629bf215546Sopenharmony_ci      ++emit->num_arl_consts;
3630bf215546Sopenharmony_ci   }
3631bf215546Sopenharmony_ci   emit->arl_consts[i].number = (emit->arl_consts[i].number > num) ?
3632bf215546Sopenharmony_ci                                num :
3633bf215546Sopenharmony_ci                                emit->arl_consts[i].number;
3634bf215546Sopenharmony_ci   emit->arl_consts[i].arl_num = current_arl;
3635bf215546Sopenharmony_ci   return TRUE;
3636bf215546Sopenharmony_ci}
3637bf215546Sopenharmony_ci
3638bf215546Sopenharmony_ci
3639bf215546Sopenharmony_cistatic boolean
3640bf215546Sopenharmony_cipre_parse_instruction( struct svga_shader_emitter *emit,
3641bf215546Sopenharmony_ci                       const struct tgsi_full_instruction *insn,
3642bf215546Sopenharmony_ci                       int current_arl)
3643bf215546Sopenharmony_ci{
3644bf215546Sopenharmony_ci   if (insn->Src[0].Register.Indirect &&
3645bf215546Sopenharmony_ci       insn->Src[0].Indirect.File == TGSI_FILE_ADDRESS) {
3646bf215546Sopenharmony_ci      const struct tgsi_full_src_register *reg = &insn->Src[0];
3647bf215546Sopenharmony_ci      if (reg->Register.Index < 0) {
3648bf215546Sopenharmony_ci         pre_parse_add_indirect(emit, reg->Register.Index, current_arl);
3649bf215546Sopenharmony_ci      }
3650bf215546Sopenharmony_ci   }
3651bf215546Sopenharmony_ci
3652bf215546Sopenharmony_ci   if (insn->Src[1].Register.Indirect &&
3653bf215546Sopenharmony_ci       insn->Src[1].Indirect.File == TGSI_FILE_ADDRESS) {
3654bf215546Sopenharmony_ci      const struct tgsi_full_src_register *reg = &insn->Src[1];
3655bf215546Sopenharmony_ci      if (reg->Register.Index < 0) {
3656bf215546Sopenharmony_ci         pre_parse_add_indirect(emit, reg->Register.Index, current_arl);
3657bf215546Sopenharmony_ci      }
3658bf215546Sopenharmony_ci   }
3659bf215546Sopenharmony_ci
3660bf215546Sopenharmony_ci   if (insn->Src[2].Register.Indirect &&
3661bf215546Sopenharmony_ci       insn->Src[2].Indirect.File == TGSI_FILE_ADDRESS) {
3662bf215546Sopenharmony_ci      const struct tgsi_full_src_register *reg = &insn->Src[2];
3663bf215546Sopenharmony_ci      if (reg->Register.Index < 0) {
3664bf215546Sopenharmony_ci         pre_parse_add_indirect(emit, reg->Register.Index, current_arl);
3665bf215546Sopenharmony_ci      }
3666bf215546Sopenharmony_ci   }
3667bf215546Sopenharmony_ci
3668bf215546Sopenharmony_ci   return TRUE;
3669bf215546Sopenharmony_ci}
3670bf215546Sopenharmony_ci
3671bf215546Sopenharmony_ci
3672bf215546Sopenharmony_cistatic boolean
3673bf215546Sopenharmony_cipre_parse_tokens( struct svga_shader_emitter *emit,
3674bf215546Sopenharmony_ci                  const struct tgsi_token *tokens )
3675bf215546Sopenharmony_ci{
3676bf215546Sopenharmony_ci   struct tgsi_parse_context parse;
3677bf215546Sopenharmony_ci   int current_arl = 0;
3678bf215546Sopenharmony_ci
3679bf215546Sopenharmony_ci   tgsi_parse_init( &parse, tokens );
3680bf215546Sopenharmony_ci
3681bf215546Sopenharmony_ci   while (!tgsi_parse_end_of_tokens( &parse )) {
3682bf215546Sopenharmony_ci      tgsi_parse_token( &parse );
3683bf215546Sopenharmony_ci      switch (parse.FullToken.Token.Type) {
3684bf215546Sopenharmony_ci      case TGSI_TOKEN_TYPE_IMMEDIATE:
3685bf215546Sopenharmony_ci      case TGSI_TOKEN_TYPE_DECLARATION:
3686bf215546Sopenharmony_ci         break;
3687bf215546Sopenharmony_ci      case TGSI_TOKEN_TYPE_INSTRUCTION:
3688bf215546Sopenharmony_ci         if (parse.FullToken.FullInstruction.Instruction.Opcode ==
3689bf215546Sopenharmony_ci             TGSI_OPCODE_ARL) {
3690bf215546Sopenharmony_ci            ++current_arl;
3691bf215546Sopenharmony_ci         }
3692bf215546Sopenharmony_ci         if (!pre_parse_instruction( emit, &parse.FullToken.FullInstruction,
3693bf215546Sopenharmony_ci                                     current_arl ))
3694bf215546Sopenharmony_ci            return FALSE;
3695bf215546Sopenharmony_ci         break;
3696bf215546Sopenharmony_ci      default:
3697bf215546Sopenharmony_ci         break;
3698bf215546Sopenharmony_ci      }
3699bf215546Sopenharmony_ci
3700bf215546Sopenharmony_ci   }
3701bf215546Sopenharmony_ci   return TRUE;
3702bf215546Sopenharmony_ci}
3703bf215546Sopenharmony_ci
3704bf215546Sopenharmony_ci
3705bf215546Sopenharmony_cistatic boolean
3706bf215546Sopenharmony_cisvga_shader_emit_helpers(struct svga_shader_emitter *emit)
3707bf215546Sopenharmony_ci{
3708bf215546Sopenharmony_ci   if (needs_to_create_common_immediate( emit )) {
3709bf215546Sopenharmony_ci      create_common_immediate( emit );
3710bf215546Sopenharmony_ci   }
3711bf215546Sopenharmony_ci   if (needs_to_create_loop_const( emit )) {
3712bf215546Sopenharmony_ci      create_loop_const( emit );
3713bf215546Sopenharmony_ci   }
3714bf215546Sopenharmony_ci   if (needs_to_create_arl_consts( emit )) {
3715bf215546Sopenharmony_ci      create_arl_consts( emit );
3716bf215546Sopenharmony_ci   }
3717bf215546Sopenharmony_ci
3718bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_FRAGMENT) {
3719bf215546Sopenharmony_ci      if (!svga_shader_emit_samplers_decl( emit ))
3720bf215546Sopenharmony_ci         return FALSE;
3721bf215546Sopenharmony_ci
3722bf215546Sopenharmony_ci      if (!emit_ps_preamble( emit ))
3723bf215546Sopenharmony_ci         return FALSE;
3724bf215546Sopenharmony_ci
3725bf215546Sopenharmony_ci      if (emit->key.fs.light_twoside) {
3726bf215546Sopenharmony_ci         if (!emit_light_twoside( emit ))
3727bf215546Sopenharmony_ci            return FALSE;
3728bf215546Sopenharmony_ci      }
3729bf215546Sopenharmony_ci      if (emit->emit_frontface) {
3730bf215546Sopenharmony_ci         if (!emit_frontface( emit ))
3731bf215546Sopenharmony_ci            return FALSE;
3732bf215546Sopenharmony_ci      }
3733bf215546Sopenharmony_ci      if (emit->inverted_texcoords) {
3734bf215546Sopenharmony_ci         if (!emit_inverted_texcoords( emit ))
3735bf215546Sopenharmony_ci            return FALSE;
3736bf215546Sopenharmony_ci      }
3737bf215546Sopenharmony_ci   }
3738bf215546Sopenharmony_ci   else {
3739bf215546Sopenharmony_ci      assert(emit->unit == PIPE_SHADER_VERTEX);
3740bf215546Sopenharmony_ci      if (emit->key.vs.adjust_attrib_range) {
3741bf215546Sopenharmony_ci         if (!emit_adjusted_vertex_attribs(emit) ||
3742bf215546Sopenharmony_ci             emit->key.vs.adjust_attrib_w_1) {
3743bf215546Sopenharmony_ci            return FALSE;
3744bf215546Sopenharmony_ci         }
3745bf215546Sopenharmony_ci      }
3746bf215546Sopenharmony_ci   }
3747bf215546Sopenharmony_ci
3748bf215546Sopenharmony_ci   return TRUE;
3749bf215546Sopenharmony_ci}
3750bf215546Sopenharmony_ci
3751bf215546Sopenharmony_ci
3752bf215546Sopenharmony_ci/**
3753bf215546Sopenharmony_ci * This is the main entrypoint into the TGSI instruction translater.
3754bf215546Sopenharmony_ci * Translate TGSI shader tokens into an SVGA shader.
3755bf215546Sopenharmony_ci */
3756bf215546Sopenharmony_ciboolean
3757bf215546Sopenharmony_cisvga_shader_emit_instructions(struct svga_shader_emitter *emit,
3758bf215546Sopenharmony_ci                              const struct tgsi_token *tokens)
3759bf215546Sopenharmony_ci{
3760bf215546Sopenharmony_ci   struct tgsi_parse_context parse;
3761bf215546Sopenharmony_ci   const struct tgsi_token *new_tokens = NULL;
3762bf215546Sopenharmony_ci   boolean ret = TRUE;
3763bf215546Sopenharmony_ci   boolean helpers_emitted = FALSE;
3764bf215546Sopenharmony_ci   unsigned line_nr = 0;
3765bf215546Sopenharmony_ci
3766bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_FRAGMENT && emit->key.fs.pstipple) {
3767bf215546Sopenharmony_ci      unsigned unit;
3768bf215546Sopenharmony_ci
3769bf215546Sopenharmony_ci      new_tokens = util_pstipple_create_fragment_shader(tokens, &unit, 0,
3770bf215546Sopenharmony_ci                                                        TGSI_FILE_INPUT);
3771bf215546Sopenharmony_ci
3772bf215546Sopenharmony_ci      if (new_tokens) {
3773bf215546Sopenharmony_ci         /* Setup texture state for stipple */
3774bf215546Sopenharmony_ci         emit->sampler_target[unit] = TGSI_TEXTURE_2D;
3775bf215546Sopenharmony_ci         emit->key.tex[unit].swizzle_r = TGSI_SWIZZLE_X;
3776bf215546Sopenharmony_ci         emit->key.tex[unit].swizzle_g = TGSI_SWIZZLE_Y;
3777bf215546Sopenharmony_ci         emit->key.tex[unit].swizzle_b = TGSI_SWIZZLE_Z;
3778bf215546Sopenharmony_ci         emit->key.tex[unit].swizzle_a = TGSI_SWIZZLE_W;
3779bf215546Sopenharmony_ci
3780bf215546Sopenharmony_ci         emit->pstipple_sampler_unit = unit;
3781bf215546Sopenharmony_ci
3782bf215546Sopenharmony_ci         tokens = new_tokens;
3783bf215546Sopenharmony_ci      }
3784bf215546Sopenharmony_ci   }
3785bf215546Sopenharmony_ci
3786bf215546Sopenharmony_ci   tgsi_parse_init( &parse, tokens );
3787bf215546Sopenharmony_ci   emit->internal_imm_count = 0;
3788bf215546Sopenharmony_ci
3789bf215546Sopenharmony_ci   if (emit->unit == PIPE_SHADER_VERTEX) {
3790bf215546Sopenharmony_ci      ret = emit_vs_preamble( emit );
3791bf215546Sopenharmony_ci      if (!ret)
3792bf215546Sopenharmony_ci         goto done;
3793bf215546Sopenharmony_ci   }
3794bf215546Sopenharmony_ci
3795bf215546Sopenharmony_ci   pre_parse_tokens(emit, tokens);
3796bf215546Sopenharmony_ci
3797bf215546Sopenharmony_ci   while (!tgsi_parse_end_of_tokens( &parse )) {
3798bf215546Sopenharmony_ci      tgsi_parse_token( &parse );
3799bf215546Sopenharmony_ci
3800bf215546Sopenharmony_ci      switch (parse.FullToken.Token.Type) {
3801bf215546Sopenharmony_ci      case TGSI_TOKEN_TYPE_IMMEDIATE:
3802bf215546Sopenharmony_ci         ret = svga_emit_immediate( emit, &parse.FullToken.FullImmediate );
3803bf215546Sopenharmony_ci         if (!ret)
3804bf215546Sopenharmony_ci            goto done;
3805bf215546Sopenharmony_ci         break;
3806bf215546Sopenharmony_ci
3807bf215546Sopenharmony_ci      case TGSI_TOKEN_TYPE_DECLARATION:
3808bf215546Sopenharmony_ci         ret = svga_translate_decl_sm30( emit, &parse.FullToken.FullDeclaration );
3809bf215546Sopenharmony_ci         if (!ret)
3810bf215546Sopenharmony_ci            goto done;
3811bf215546Sopenharmony_ci         break;
3812bf215546Sopenharmony_ci
3813bf215546Sopenharmony_ci      case TGSI_TOKEN_TYPE_INSTRUCTION:
3814bf215546Sopenharmony_ci         if (!helpers_emitted) {
3815bf215546Sopenharmony_ci            if (!svga_shader_emit_helpers( emit ))
3816bf215546Sopenharmony_ci               goto done;
3817bf215546Sopenharmony_ci            helpers_emitted = TRUE;
3818bf215546Sopenharmony_ci         }
3819bf215546Sopenharmony_ci         ret = svga_emit_instruction( emit,
3820bf215546Sopenharmony_ci                                      line_nr++,
3821bf215546Sopenharmony_ci                                      &parse.FullToken.FullInstruction );
3822bf215546Sopenharmony_ci         if (!ret)
3823bf215546Sopenharmony_ci            goto done;
3824bf215546Sopenharmony_ci         break;
3825bf215546Sopenharmony_ci      default:
3826bf215546Sopenharmony_ci         break;
3827bf215546Sopenharmony_ci      }
3828bf215546Sopenharmony_ci
3829bf215546Sopenharmony_ci      reset_temp_regs( emit );
3830bf215546Sopenharmony_ci   }
3831bf215546Sopenharmony_ci
3832bf215546Sopenharmony_ci   /* Need to terminate the current subroutine.  Note that the
3833bf215546Sopenharmony_ci    * hardware doesn't tolerate shaders without sub-routines
3834bf215546Sopenharmony_ci    * terminating with RET+END.
3835bf215546Sopenharmony_ci    */
3836bf215546Sopenharmony_ci   if (!emit->in_main_func) {
3837bf215546Sopenharmony_ci      ret = emit_instruction( emit, inst_token( SVGA3DOP_RET ) );
3838bf215546Sopenharmony_ci      if (!ret)
3839bf215546Sopenharmony_ci         goto done;
3840bf215546Sopenharmony_ci   }
3841bf215546Sopenharmony_ci
3842bf215546Sopenharmony_ci   assert(emit->dynamic_branching_level == 0);
3843bf215546Sopenharmony_ci
3844bf215546Sopenharmony_ci   /* Need to terminate the whole shader:
3845bf215546Sopenharmony_ci    */
3846bf215546Sopenharmony_ci   ret = emit_instruction( emit, inst_token( SVGA3DOP_END ) );
3847bf215546Sopenharmony_ci   if (!ret)
3848bf215546Sopenharmony_ci      goto done;
3849bf215546Sopenharmony_ci
3850bf215546Sopenharmony_cidone:
3851bf215546Sopenharmony_ci   tgsi_parse_free( &parse );
3852bf215546Sopenharmony_ci   if (new_tokens) {
3853bf215546Sopenharmony_ci      tgsi_free_tokens(new_tokens);
3854bf215546Sopenharmony_ci   }
3855bf215546Sopenharmony_ci
3856bf215546Sopenharmony_ci   return ret;
3857bf215546Sopenharmony_ci}
3858