13141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/*
23141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
33141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
43141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * Permission is hereby granted, free of charge, to any person obtaining a
53141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * copy of this software and associated documentation files (the "Software"),
63141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * to deal in the Software without restriction, including without limitation
73141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * and/or sell copies of the Software, and to permit persons to whom the
93141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * Software is furnished to do so, subject to the following conditions:
103141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
113141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * The above copyright notice and this permission notice (including the next
123141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * paragraph) shall be included in all copies or substantial portions of the
133141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * Software.
143141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
153141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
163141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
183141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
193141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
203141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
213141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * SOFTWARE.
223141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
233141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * Authors:
243141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *    Rob Clark <robclark@freedesktop.org>
253141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
263141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
273141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#include "tgsi/tgsi_transform.h"
283141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#include "tgsi/tgsi_scan.h"
293141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#include "tgsi/tgsi_dump.h"
303141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
313141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#include "util/u_debug.h"
323141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#include "util/u_math.h"
333141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
34f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt#include "tgsi_lowering.h"
353141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
36f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholtstruct tgsi_lowering_context {
3719df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_transform_context base;
38f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   const struct tgsi_lowering_config *config;
3919df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_shader_info *info;
4019df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned two_side_colors;
4119df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned two_side_idx[PIPE_MAX_SHADER_INPUTS];
4219df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned color_base;  /* base register for chosen COLOR/BCOLOR's */
4319df602b39ec03f61edec308ad568be118beb3acEric Anholt   int face_idx;
4419df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned numtmp;
4519df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct {
4619df602b39ec03f61edec308ad568be118beb3acEric Anholt      struct tgsi_full_src_register src;
4719df602b39ec03f61edec308ad568be118beb3acEric Anholt      struct tgsi_full_dst_register dst;
4819df602b39ec03f61edec308ad568be118beb3acEric Anholt   } tmp[2];
493141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define A 0
503141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define B 1
5119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register imm;
5219df602b39ec03f61edec308ad568be118beb3acEric Anholt   int emitted_decls;
5319df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned saturate;
543141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt};
553141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
56f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholtstatic inline struct tgsi_lowering_context *
57f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholttgsi_lowering_context(struct tgsi_transform_context *tctx)
583141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
59f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   return (struct tgsi_lowering_context *)tctx;
603141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
613141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
623141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/*
633141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * Utility helpers:
643141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
653141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
663141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
673141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtreg_dst(struct tgsi_full_dst_register *dst,
683141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt	const struct tgsi_full_dst_register *orig_dst, unsigned wrmask)
693141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
7019df602b39ec03f61edec308ad568be118beb3acEric Anholt   *dst = *orig_dst;
7119df602b39ec03f61edec308ad568be118beb3acEric Anholt   dst->Register.WriteMask &= wrmask;
7219df602b39ec03f61edec308ad568be118beb3acEric Anholt   assert(dst->Register.WriteMask);
733141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
753141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic inline void
763141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtget_swiz(unsigned *swiz, const struct tgsi_src_register *src)
773141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
7819df602b39ec03f61edec308ad568be118beb3acEric Anholt   swiz[0] = src->SwizzleX;
7919df602b39ec03f61edec308ad568be118beb3acEric Anholt   swiz[1] = src->SwizzleY;
8019df602b39ec03f61edec308ad568be118beb3acEric Anholt   swiz[2] = src->SwizzleZ;
8119df602b39ec03f61edec308ad568be118beb3acEric Anholt   swiz[3] = src->SwizzleW;
823141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
833141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
843141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
853141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtreg_src(struct tgsi_full_src_register *src,
863141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt	const struct tgsi_full_src_register *orig_src,
873141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt	unsigned sx, unsigned sy, unsigned sz, unsigned sw)
883141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
8919df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned swiz[4];
9019df602b39ec03f61edec308ad568be118beb3acEric Anholt   get_swiz(swiz, &orig_src->Register);
9119df602b39ec03f61edec308ad568be118beb3acEric Anholt   *src = *orig_src;
9219df602b39ec03f61edec308ad568be118beb3acEric Anholt   src->Register.SwizzleX = swiz[sx];
9319df602b39ec03f61edec308ad568be118beb3acEric Anholt   src->Register.SwizzleY = swiz[sy];
9419df602b39ec03f61edec308ad568be118beb3acEric Anholt   src->Register.SwizzleZ = swiz[sz];
9519df602b39ec03f61edec308ad568be118beb3acEric Anholt   src->Register.SwizzleW = swiz[sw];
963141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
973141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
983141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define TGSI_SWIZZLE__ TGSI_SWIZZLE_X  /* don't-care value! */
9919df602b39ec03f61edec308ad568be118beb3acEric Anholt#define SWIZ(x,y,z,w) TGSI_SWIZZLE_ ## x, TGSI_SWIZZLE_ ## y,   \
10019df602b39ec03f61edec308ad568be118beb3acEric Anholt      TGSI_SWIZZLE_ ## z, TGSI_SWIZZLE_ ## w
1013141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
1023141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/*
1033141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * if (dst.x aliases src.x) {
1043141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   MOV tmpA.x, src.x
1053141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   src = tmpA
1063141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * }
1073141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * COS dst.x, src.x
1083141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * SIN dst.y, src.x
1093141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.zw, imm{0.0, 1.0}
1103141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
1113141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic bool
1123141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtaliases(const struct tgsi_full_dst_register *dst, unsigned dst_mask,
1133141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt	const struct tgsi_full_src_register *src, unsigned src_mask)
1143141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
11519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if ((dst->Register.File == src->Register.File) &&
11619df602b39ec03f61edec308ad568be118beb3acEric Anholt       (dst->Register.Index == src->Register.Index)) {
11719df602b39ec03f61edec308ad568be118beb3acEric Anholt      unsigned i, actual_mask = 0;
11819df602b39ec03f61edec308ad568be118beb3acEric Anholt      unsigned swiz[4];
11919df602b39ec03f61edec308ad568be118beb3acEric Anholt      get_swiz(swiz, &src->Register);
12019df602b39ec03f61edec308ad568be118beb3acEric Anholt      for (i = 0; i < 4; i++)
12119df602b39ec03f61edec308ad568be118beb3acEric Anholt         if (src_mask & (1 << i))
12219df602b39ec03f61edec308ad568be118beb3acEric Anholt            actual_mask |= (1 << swiz[i]);
12319df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (actual_mask & dst_mask)
12419df602b39ec03f61edec308ad568be118beb3acEric Anholt         return true;
12519df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
12619df602b39ec03f61edec308ad568be118beb3acEric Anholt   return false;
1273141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
1283141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
1293141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
1303141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtcreate_mov(struct tgsi_transform_context *tctx,
13119df602b39ec03f61edec308ad568be118beb3acEric Anholt           const struct tgsi_full_dst_register *dst,
13219df602b39ec03f61edec308ad568be118beb3acEric Anholt           const struct tgsi_full_src_register *src,
13319df602b39ec03f61edec308ad568be118beb3acEric Anholt           unsigned mask, unsigned saturate)
1343141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
13519df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
13619df602b39ec03f61edec308ad568be118beb3acEric Anholt
13719df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst = tgsi_default_full_instruction();
13819df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
13919df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst.Instruction.Saturate = saturate;
14019df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst.Instruction.NumDstRegs = 1;
14119df602b39ec03f61edec308ad568be118beb3acEric Anholt   reg_dst(&new_inst.Dst[0], dst, mask);
14219df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst.Instruction.NumSrcRegs = 1;
14319df602b39ec03f61edec308ad568be118beb3acEric Anholt   reg_src(&new_inst.Src[0], src, SWIZ(X, Y, Z, W));
14419df602b39ec03f61edec308ad568be118beb3acEric Anholt   tctx->emit_instruction(tctx, &new_inst);
1453141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
1463141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
1473141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* to help calculate # of tgsi tokens for a lowering.. we assume
1483141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * the worst case, ie. removed instructions don't have ADDR[] or
1493141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * anything which increases the # of tokens per src/dst and the
1503141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * inserted instructions do.
1513141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
1523141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * OINST() - old instruction
1533141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *    1         : instruction itself
1543141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *    1         : dst
1553141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *    1 * nargs : srcN
1563141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
1573141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * NINST() - new instruction
1583141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *    1         : instruction itself
1593141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *    2         : dst
1603141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *    2 * nargs : srcN
1613141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
1623141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
1633141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define OINST(nargs)  (1 + 1 + 1 * (nargs))
1643141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define NINST(nargs)  (1 + 2 + 2 * (nargs))
1653141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
1663141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/*
1673141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * Lowering Translators:
1683141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
1693141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
1703141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* DST - Distance Vector
1713141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.x = 1.0
1723141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.y = src0.y \times src1.y
1733141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.z = src0.z
1743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.w = src1.w
1753141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
1763141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; note: could be more clever and use just a single temp
1773141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ;       if I was clever enough to re-write the swizzles.
1783141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 2 tmp, imm{1.0}
1793141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * if (dst.y aliases src0.z) {
1803141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   MOV tmpA.yz, src0.yz
1813141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   src0 = tmpA
1823141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * }
1833141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * if (dst.yz aliases src1.w) {
1843141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   MOV tmpB.yw, src1.yw
1853141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   src1 = tmpB
1863141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * }
1873141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MUL dst.y, src0.y, src1.y
1883141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.z, src0.z
1893141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.w, src1.w
1903141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.x, imm{1.0}
1913141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
1923141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DST_GROW (NINST(1) + NINST(1) + NINST(2) + NINST(1) + \
1933141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt		NINST(1) + NINST(1) - OINST(2))
1943141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DST_TMP  2
1953141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
1963141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_dst(struct tgsi_transform_context *tctx,
19719df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
1983141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
199f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
20019df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst  = &inst->Dst[0];
20119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src0 = &inst->Src[0];
20219df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src1 = &inst->Src[1];
20319df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
20419df602b39ec03f61edec308ad568be118beb3acEric Anholt
20519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (aliases(dst, TGSI_WRITEMASK_Y, src0, TGSI_WRITEMASK_Z)) {
20619df602b39ec03f61edec308ad568be118beb3acEric Anholt      create_mov(tctx, &ctx->tmp[A].dst, src0, TGSI_WRITEMASK_YZ, 0);
20719df602b39ec03f61edec308ad568be118beb3acEric Anholt      src0 = &ctx->tmp[A].src;
20819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
20919df602b39ec03f61edec308ad568be118beb3acEric Anholt
21019df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (aliases(dst, TGSI_WRITEMASK_YZ, src1, TGSI_WRITEMASK_W)) {
21119df602b39ec03f61edec308ad568be118beb3acEric Anholt      create_mov(tctx, &ctx->tmp[B].dst, src1, TGSI_WRITEMASK_YW, 0);
21219df602b39ec03f61edec308ad568be118beb3acEric Anholt      src1 = &ctx->tmp[B].src;
21319df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
21419df602b39ec03f61edec308ad568be118beb3acEric Anholt
21519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_Y) {
21619df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MUL dst.y, src0.y, src1.y */
21719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
21819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MUL;
21919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
22019df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_Y);
22119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
22219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src0, SWIZ(_, Y, _, _));
22319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], src1, SWIZ(_, Y, _, _));
22419df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
22519df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
22619df602b39ec03f61edec308ad568be118beb3acEric Anholt
22719df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_Z) {
22819df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.z, src0.z */
22919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
23019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
23119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
23219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_Z);
23319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
23419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src0, SWIZ(_, _, Z, _));
23519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
23619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
23719df602b39ec03f61edec308ad568be118beb3acEric Anholt
23819df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_W) {
23919df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.w, src1.w */
24019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
24119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
24219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
24319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_W);
24419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
24519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src1, SWIZ(_, _, _, W));
24619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
24719df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
24819df602b39ec03f61edec308ad568be118beb3acEric Anholt
24919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_X) {
25019df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.x, imm{1.0} */
25119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
25219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
25319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
25419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_X);
25519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
25619df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->imm, SWIZ(Y, _, _, _));
25719df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
25819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
2593141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
2603141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
2613141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* XPD - Cross Product
2623141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.x = src0.y \times src1.z - src1.y \times src0.z
2633141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.y = src0.z \times src1.x - src1.z \times src0.x
2643141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.z = src0.x \times src1.y - src1.x \times src0.y
2653141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.w = 1.0
2663141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
26767da7dd98a6253143b80a058d7077666408a688eRussell King * ; needs: 1 tmp, imm{1.0}
26867da7dd98a6253143b80a058d7077666408a688eRussell King * MUL tmpA.xyz, src1.yzx, src0.zxy
26967da7dd98a6253143b80a058d7077666408a688eRussell King * MAD dst.xyz, src0.yzx, src1.zxy, -tmpA.xyz
2703141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.w, imm{1.0}
2713141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
27267da7dd98a6253143b80a058d7077666408a688eRussell King#define XPD_GROW (NINST(2) + NINST(3) + NINST(1) - OINST(2))
27367da7dd98a6253143b80a058d7077666408a688eRussell King#define XPD_TMP  1
2743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
2753141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_xpd(struct tgsi_transform_context *tctx,
27619df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
2773141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
278f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
27919df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst  = &inst->Dst[0];
28019df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src0 = &inst->Src[0];
28119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src1 = &inst->Src[1];
28219df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
28319df602b39ec03f61edec308ad568be118beb3acEric Anholt
28419df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZ) {
28567da7dd98a6253143b80a058d7077666408a688eRussell King      /* MUL tmpA.xyz, src1.yzx, src0.zxy */
28619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
28719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MUL;
28819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
28919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XYZ);
29019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
29119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src1, SWIZ(Y, Z, X, _));
29219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], src0, SWIZ(Z, X, Y, _));
29319df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
29419df602b39ec03f61edec308ad568be118beb3acEric Anholt
29567da7dd98a6253143b80a058d7077666408a688eRussell King      /* MAD dst.xyz, src0.yzx, src1.zxy, -tmpA.xyz */
29619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
29767da7dd98a6253143b80a058d7077666408a688eRussell King      new_inst.Instruction.Opcode = TGSI_OPCODE_MAD;
29819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
29919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XYZ);
30067da7dd98a6253143b80a058d7077666408a688eRussell King      new_inst.Instruction.NumSrcRegs = 3;
30167da7dd98a6253143b80a058d7077666408a688eRussell King      reg_src(&new_inst.Src[0], src0, SWIZ(Y, Z, X, _));
30267da7dd98a6253143b80a058d7077666408a688eRussell King      reg_src(&new_inst.Src[1], src1, SWIZ(Z, X, Y, _));
30367da7dd98a6253143b80a058d7077666408a688eRussell King      reg_src(&new_inst.Src[2], &ctx->tmp[A].src, SWIZ(X, Y, Z, _));
30467da7dd98a6253143b80a058d7077666408a688eRussell King      new_inst.Src[2].Register.Negate = true;
30519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
30619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
30719df602b39ec03f61edec308ad568be118beb3acEric Anholt
30819df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_W) {
30919df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.w, imm{1.0} */
31019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
31119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
31219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
31319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_W);
31419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
31519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->imm, SWIZ(_, _, _, Y));
31619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
31719df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
3183141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
3193141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
3203141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* SCS - Sine Cosine
3213141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.x = \cos{src.x}
3223141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.y = \sin{src.x}
3233141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.z = 0.0
3243141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst.w = 1.0
3253141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
3263141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 1 tmp, imm{0.0, 1.0}
3273141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * if (dst.x aliases src.x) {
3283141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   MOV tmpA.x, src.x
3293141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   src = tmpA
3303141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * }
3313141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * COS dst.x, src.x
3323141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * SIN dst.y, src.x
3333141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.zw, imm{0.0, 1.0}
3343141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
3353141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define SCS_GROW (NINST(1) + NINST(1) + NINST(1) + NINST(1) - OINST(1))
3363141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define SCS_TMP  1
3373141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
3383141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_scs(struct tgsi_transform_context *tctx,
33919df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
3403141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
341f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
34219df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst = &inst->Dst[0];
34319df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src = &inst->Src[0];
34419df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
34519df602b39ec03f61edec308ad568be118beb3acEric Anholt
34619df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (aliases(dst, TGSI_WRITEMASK_X, src, TGSI_WRITEMASK_X)) {
34719df602b39ec03f61edec308ad568be118beb3acEric Anholt      create_mov(tctx, &ctx->tmp[A].dst, src, TGSI_WRITEMASK_X, 0);
34819df602b39ec03f61edec308ad568be118beb3acEric Anholt      src = &ctx->tmp[A].src;
34919df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
35019df602b39ec03f61edec308ad568be118beb3acEric Anholt
35119df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_X) {
35219df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* COS dst.x, src.x */
35319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
35419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_COS;
35519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
35619df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_X);
35719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
35819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(X, _, _, _));
35919df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
36019df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
36119df602b39ec03f61edec308ad568be118beb3acEric Anholt
36219df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_Y) {
36319df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* SIN dst.y, src.x */
36419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
36519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_SIN;
36619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
36719df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_Y);
36819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
36919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(X, _, _, _));
37019df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
37119df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
37219df602b39ec03f61edec308ad568be118beb3acEric Anholt
37319df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_ZW) {
37419df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.zw, imm{0.0, 1.0} */
37519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
37619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
37719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
37819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_ZW);
37919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
38019df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->imm, SWIZ(_, _, X, Y));
38119df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
38219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
3833141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
3843141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
3853141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* LRP - Linear Interpolate
3863141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.x = src0.x \times src1.x + (1.0 - src0.x) \times src2.x
3873141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.y = src0.y \times src1.y + (1.0 - src0.y) \times src2.y
3883141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.z = src0.z \times src1.z + (1.0 - src0.z) \times src2.z
3893141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.w = src0.w \times src1.w + (1.0 - src0.w) \times src2.w
3903141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
391fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King * This becomes: src0 \times src1 + src2 - src0 \times src2, which
392fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King * can then become: src0 \times src1 - (src0 \times src2 - src2)
393fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King *
394fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King * ; needs: 1 tmp
395fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King * MAD tmpA, src0, src2, -src2
396fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King * MAD dst, src0, src1, -tmpA
3973141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
398fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King#define LRP_GROW (NINST(3) + NINST(3) - OINST(3))
399fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King#define LRP_TMP  1
4003141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
4013141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_lrp(struct tgsi_transform_context *tctx,
40219df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
4033141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
404f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
40519df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst  = &inst->Dst[0];
40619df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src0 = &inst->Src[0];
40719df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src1 = &inst->Src[1];
40819df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src2 = &inst->Src[2];
40919df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
41019df602b39ec03f61edec308ad568be118beb3acEric Anholt
41119df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZW) {
412fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      /* MAD tmpA, src0, src2, -src2 */
41319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
414fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      new_inst.Instruction.Opcode = TGSI_OPCODE_MAD;
41519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
41619df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XYZW);
417fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      new_inst.Instruction.NumSrcRegs = 3;
41819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
41919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], src2, SWIZ(X, Y, Z, W));
420fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      reg_src(&new_inst.Src[2], src2, SWIZ(X, Y, Z, W));
421fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      new_inst.Src[2].Register.Negate = !new_inst.Src[2].Register.Negate;
42219df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
42319df602b39ec03f61edec308ad568be118beb3acEric Anholt
424fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      /* MAD dst, src0, src1, -tmpA */
42519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
426fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      new_inst.Instruction.Opcode = TGSI_OPCODE_MAD;
42719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
42819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XYZW);
429fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      new_inst.Instruction.NumSrcRegs = 3;
430fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
431fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      reg_src(&new_inst.Src[1], src1, SWIZ(X, Y, Z, W));
432fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      reg_src(&new_inst.Src[2], &ctx->tmp[A].src, SWIZ(X, Y, Z, W));
433fadfaa82c61a32c74531e1e1aaecfd2b3c5ac6d8Russell King      new_inst.Src[2].Register.Negate = true;
43419df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
43519df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
4363141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
4373141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
4383141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* FRC - Fraction
4393141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.x = src.x - \lfloor src.x\rfloor
4403141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.y = src.y - \lfloor src.y\rfloor
4413141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.z = src.z - \lfloor src.z\rfloor
4423141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.w = src.w - \lfloor src.w\rfloor
4433141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
4443141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 1 tmp
4453141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * FLR tmpA, src
4463141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * SUB dst, src, tmpA
4473141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
4483141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define FRC_GROW (NINST(1) + NINST(2) - OINST(1))
4493141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define FRC_TMP  1
4503141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
4513141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_frc(struct tgsi_transform_context *tctx,
45219df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
4533141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
454f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
45519df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst = &inst->Dst[0];
45619df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src = &inst->Src[0];
45719df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
45819df602b39ec03f61edec308ad568be118beb3acEric Anholt
45919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZW) {
46019df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* FLR tmpA, src */
46119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
46219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_FLR;
46319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
46419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XYZW);
46519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
46619df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(X, Y, Z, W));
46719df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
46819df602b39ec03f61edec308ad568be118beb3acEric Anholt
46919df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* SUB dst, src, tmpA */
47019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
471d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák      new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
47219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
47319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XYZW);
47419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
47519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(X, Y, Z, W));
47619df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, Y, Z, W));
477d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák      new_inst.Src[1].Register.Negate = 1;
47819df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
47919df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
4803141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
4813141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
4823141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* POW - Power
4833141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.x = src0.x^{src1.x}
4843141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.y = src0.x^{src1.x}
4853141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.z = src0.x^{src1.x}
4863141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.w = src0.x^{src1.x}
4873141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
4883141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 1 tmp
4893141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * LG2 tmpA.x, src0.x
4903141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MUL tmpA.x, src1.x, tmpA.x
4913141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * EX2 dst, tmpA.x
4923141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
4933141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define POW_GROW (NINST(1) + NINST(2) + NINST(1) - OINST(2))
4943141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define POW_TMP  1
4953141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
4963141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_pow(struct tgsi_transform_context *tctx,
49719df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
4983141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
499f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
50019df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst  = &inst->Dst[0];
50119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src0 = &inst->Src[0];
50219df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src1 = &inst->Src[1];
50319df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
50419df602b39ec03f61edec308ad568be118beb3acEric Anholt
50519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZW) {
50619df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* LG2 tmpA.x, src0.x */
50719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
50819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_LG2;
50919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
51019df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
51119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
51219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src0, SWIZ(X, _, _, _));
51319df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
51419df602b39ec03f61edec308ad568be118beb3acEric Anholt
51519df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MUL tmpA.x, src1.x, tmpA.x */
51619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
51719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MUL;
51819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
51919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
52019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
52119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src1, SWIZ(X, _, _, _));
52219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, _, _, _));
52319df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
52419df602b39ec03f61edec308ad568be118beb3acEric Anholt
52519df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* EX2 dst, tmpA.x */
52619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
52719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_EX2;
52819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
52919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XYZW);
53019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
53119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(X, _, _, _));
53219df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
53319df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
5343141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
5353141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
5363141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* LIT - Light Coefficients
5373141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.x = 1.0
5383141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.y = max(src.x, 0.0)
5393141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.z = (src.x > 0.0) ? max(src.y, 0.0)^{clamp(src.w, -128.0, 128.0))} : 0
5403141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.w = 1.0
5413141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
5423141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 1 tmp, imm{0.0}, imm{1.0}, imm{128.0}
5433141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MAX tmpA.xy, src.xy, imm{0.0}
5443141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * CLAMP tmpA.z, src.w, -imm{128.0}, imm{128.0}
5453141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * LG2 tmpA.y, tmpA.y
5463141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MUL tmpA.y, tmpA.z, tmpA.y
5473141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * EX2 tmpA.y, tmpA.y
5483141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * CMP tmpA.y, -src.x, tmpA.y, imm{0.0}
5493141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.yz, tmpA.xy
5503141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.xw, imm{1.0}
5513141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
5523141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define LIT_GROW (NINST(1) + NINST(3) + NINST(1) + NINST(2) + \
5533141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt		NINST(1) + NINST(3) + NINST(1) + NINST(1) - OINST(1))
5543141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define LIT_TMP  1
5553141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
5563141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_lit(struct tgsi_transform_context *tctx,
55719df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
5583141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
559f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
56019df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst = &inst->Dst[0];
56119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src = &inst->Src[0];
56219df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
56319df602b39ec03f61edec308ad568be118beb3acEric Anholt
56419df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_YZ) {
56519df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MAX tmpA.xy, src.xy, imm{0.0} */
56619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
56719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MAX;
56819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
56919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XY);
57019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
57119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(X, Y, _, _));
57219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->imm, SWIZ(X, X, _, _));
57319df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
57419df602b39ec03f61edec308ad568be118beb3acEric Anholt
57519df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* CLAMP tmpA.z, src.w, -imm{128.0}, imm{128.0} */
57619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
57719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_CLAMP;
57819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
57919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Z);
58019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 3;
58119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(_, _, W, _));
58219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->imm, SWIZ(_, _, Z, _));
58319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[1].Register.Negate = true;
58419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[2], &ctx->imm, SWIZ(_, _, Z, _));
58519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
58619df602b39ec03f61edec308ad568be118beb3acEric Anholt
58719df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* LG2 tmpA.y, tmpA.y */
58819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
58919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_LG2;
59019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
59119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
59219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
59319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(Y, _, _, _));
59419df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
59519df602b39ec03f61edec308ad568be118beb3acEric Anholt
59619df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MUL tmpA.y, tmpA.z, tmpA.y */
59719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
59819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MUL;
59919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
60019df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
60119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
60219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(_, Z, _, _));
60319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(_, Y, _, _));
60419df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
60519df602b39ec03f61edec308ad568be118beb3acEric Anholt
60619df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* EX2 tmpA.y, tmpA.y */
60719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
60819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_EX2;
60919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
61019df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
61119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
61219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(Y, _, _, _));
61319df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
61419df602b39ec03f61edec308ad568be118beb3acEric Anholt
61519df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* CMP tmpA.y, -src.x, tmpA.y, imm{0.0} */
61619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
61719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_CMP;
61819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
61919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
62019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 3;
62119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(_, X, _, _));
62219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.Negate = true;
62319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(_, Y, _, _));
62419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[2], &ctx->imm, SWIZ(_, X, _, _));
62519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
62619df602b39ec03f61edec308ad568be118beb3acEric Anholt
62719df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.yz, tmpA.xy */
62819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
62919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
63019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
63119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_YZ);
63219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
63319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(_, X, Y, _));
63419df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
63519df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
63619df602b39ec03f61edec308ad568be118beb3acEric Anholt
63719df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XW) {
63819df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.xw, imm{1.0} */
63919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
64019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
64119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
64219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XW);
64319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
64419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->imm, SWIZ(Y, _, _, Y));
64519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
64619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
6473141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
6483141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
6493141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* EXP - Approximate Exponential Base 2
6503141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.x = 2^{\lfloor src.x\rfloor}
6513141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.y = src.x - \lfloor src.x\rfloor
6523141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.z = 2^{src.x}
6533141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.w = 1.0
6543141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
6553141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 1 tmp, imm{1.0}
65623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * if (lowering FLR) {
65723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   FRC tmpA.x, src.x
65823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   SUB tmpA.x, src.x, tmpA.x
65923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * } else {
66023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   FLR tmpA.x, src.x
66123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * }
6623141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * EX2 tmpA.y, src.x
6633141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * SUB dst.y, src.x, tmpA.x
6643141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * EX2 dst.x, tmpA.x
6653141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.z, tmpA.y
6663141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.w, imm{1.0}
6673141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
66823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King#define EXP_GROW (NINST(1) + NINST(2) + NINST(1) + NINST(2) + NINST(1) + \
6693141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt		NINST(1)+ NINST(1) - OINST(1))
6703141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define EXP_TMP  1
6713141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
6723141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_exp(struct tgsi_transform_context *tctx,
67319df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
6743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
675f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
67619df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst = &inst->Dst[0];
67719df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src = &inst->Src[0];
67819df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
67919df602b39ec03f61edec308ad568be118beb3acEric Anholt
68019df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XY) {
68123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      if (ctx->config->lower_FLR) {
68223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         /* FRC tmpA.x, src.x */
68323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst = tgsi_default_full_instruction();
68423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.Opcode = TGSI_OPCODE_FRC;
68523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumDstRegs = 1;
68623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
68723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumSrcRegs = 1;
68823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[0], src, SWIZ(X, _, _, _));
68923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         tctx->emit_instruction(tctx, &new_inst);
69023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King
69123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         /* SUB tmpA.x, src.x, tmpA.x */
69223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst = tgsi_default_full_instruction();
693d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák         new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
69423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumDstRegs = 1;
69523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
69623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumSrcRegs = 2;
69723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[0], src, SWIZ(X, _, _, _));
69823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, _, _, _));
699d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák         new_inst.Src[1].Register.Negate = 1;
70023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         tctx->emit_instruction(tctx, &new_inst);
70123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King     } else {
70223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         /* FLR tmpA.x, src.x */
70323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst = tgsi_default_full_instruction();
70423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.Opcode = TGSI_OPCODE_FLR;
70523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumDstRegs = 1;
70623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
70723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumSrcRegs = 1;
70823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[0], src, SWIZ(X, _, _, _));
70923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         tctx->emit_instruction(tctx, &new_inst);
71023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      }
71119df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
71219df602b39ec03f61edec308ad568be118beb3acEric Anholt
71319df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_Z) {
71419df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* EX2 tmpA.y, src.x */
71519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
71619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_EX2;
71719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
71819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
71919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
72019df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(X, _, _, _));
72119df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
72219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
72319df602b39ec03f61edec308ad568be118beb3acEric Anholt
72419df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_Y) {
72519df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* SUB dst.y, src.x, tmpA.x */
72619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
727d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák      new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
72819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
72919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_Y);
73019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
73119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(_, X, _, _));
73219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(_, X, _, _));
733d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák      new_inst.Src[1].Register.Negate = 1;
73419df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
73519df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
73619df602b39ec03f61edec308ad568be118beb3acEric Anholt
73719df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_X) {
73819df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* EX2 dst.x, tmpA.x */
73919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
74019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_EX2;
74119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
74219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_X);
74319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
74419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(X, _, _, _));
74519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
74619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
74719df602b39ec03f61edec308ad568be118beb3acEric Anholt
74819df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_Z) {
74919df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.z, tmpA.y */
75019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
75119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
75219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
75319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_Z);
75419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
75519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(_, _, Y, _));
75619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
75719df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
75819df602b39ec03f61edec308ad568be118beb3acEric Anholt
75919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_W) {
76019df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.w, imm{1.0} */
76119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
76219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
76319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
76419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_W);
76519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
76619df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->imm, SWIZ(_, _, _, Y));
76719df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
76819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
7693141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
7703141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
7713141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* LOG - Approximate Logarithm Base 2
7723141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.x = \lfloor\log_2{|src.x|}\rfloor
7733141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.y = \frac{|src.x|}{2^{\lfloor\log_2{|src.x|}\rfloor}}
7743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.z = \log_2{|src.x|}
7753141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *  dst.w = 1.0
7763141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
7773141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 1 tmp, imm{1.0}
7783141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * LG2 tmpA.x, |src.x|
77923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * if (lowering FLR) {
78023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   FRC tmpA.y, tmpA.x
78123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   SUB tmpA.y, tmpA.x, tmpA.y
78223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * } else {
78323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   FLR tmpA.y, tmpA.x
78423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * }
7853141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * EX2 tmpA.z, tmpA.y
7863141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * RCP tmpA.z, tmpA.z
7873141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MUL dst.y, |src.x|, tmpA.z
7883141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.xz, tmpA.yx
7893141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MOV dst.w, imm{1.0}
7903141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
79123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King#define LOG_GROW (NINST(1) + NINST(1) + NINST(2) + NINST(1) + NINST(1) + \
7923141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt		NINST(2) + NINST(1) + NINST(1) - OINST(1))
7933141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define LOG_TMP  1
7943141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
7953141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_log(struct tgsi_transform_context *tctx,
79619df602b39ec03f61edec308ad568be118beb3acEric Anholt              struct tgsi_full_instruction *inst)
7973141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
798f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
79919df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst = &inst->Dst[0];
80019df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src = &inst->Src[0];
80119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
80219df602b39ec03f61edec308ad568be118beb3acEric Anholt
80319df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZ) {
80419df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* LG2 tmpA.x, |src.x| */
80519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
80619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_LG2;
80719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
80819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
80919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
81019df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(X, _, _, _));
81119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.Absolute = true;
81219df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
81319df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
81419df602b39ec03f61edec308ad568be118beb3acEric Anholt
81519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XY) {
81623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      if (ctx->config->lower_FLR) {
81723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         /* FRC tmpA.y, tmpA.x */
81823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst = tgsi_default_full_instruction();
81923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.Opcode = TGSI_OPCODE_FRC;
82023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumDstRegs = 1;
82123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
82223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumSrcRegs = 1;
82323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(_, X, _, _));
82423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         tctx->emit_instruction(tctx, &new_inst);
82523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King
82623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         /* SUB tmpA.y, tmpA.x, tmpA.y */
82723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst = tgsi_default_full_instruction();
828d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák         new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
82923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumDstRegs = 1;
83023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
83123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumSrcRegs = 2;
83223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(_, X, _, _));
83323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(_, Y, _, _));
834d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák         new_inst.Src[1].Register.Negate = 1;
83523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         tctx->emit_instruction(tctx, &new_inst);
83623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      } else {
83723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         /* FLR tmpA.y, tmpA.x */
83823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst = tgsi_default_full_instruction();
83923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.Opcode = TGSI_OPCODE_FLR;
84023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumDstRegs = 1;
84123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Y);
84223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Instruction.NumSrcRegs = 1;
84323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(_, X, _, _));
84423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         tctx->emit_instruction(tctx, &new_inst);
84523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      }
84619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
84719df602b39ec03f61edec308ad568be118beb3acEric Anholt
84819df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_Y) {
84919df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* EX2 tmpA.z, tmpA.y */
85019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
85119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_EX2;
85219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
85319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Z);
85419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
85519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(Y, _, _, _));
85619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
85719df602b39ec03f61edec308ad568be118beb3acEric Anholt
85819df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* RCP tmpA.z, tmpA.z */
85919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
86019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_RCP;
86119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
86219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_Z);
86319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
86419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(Z, _, _, _));
86519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
86619df602b39ec03f61edec308ad568be118beb3acEric Anholt
86719df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MUL dst.y, |src.x|, tmpA.z */
86819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
86919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MUL;
87019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
87119df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_Y);
87219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
87319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src, SWIZ(_, X, _, _));
87419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.Absolute = true;
87519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(_, Z, _, _));
87619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
87719df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
87819df602b39ec03f61edec308ad568be118beb3acEric Anholt
87919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XZ) {
88019df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.xz, tmpA.yx */
88119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
88219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
88319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
88419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XZ);
88519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
88619df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(Y, _, X, _));
88719df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
88819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
88919df602b39ec03f61edec308ad568be118beb3acEric Anholt
89019df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_W) {
89119df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MOV dst.w, imm{1.0} */
89219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
89319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
89419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
89519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_W);
89619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
89719df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->imm, SWIZ(_, _, _, Y));
89819df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
89919df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
9003141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
9013141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
9023141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* DP4 - 4-component Dot Product
9033141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src0.w \times src1.w
9043141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
9053141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * DP3 - 3-component Dot Product
9063141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z
9073141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
9083141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * DPH - Homogeneous Dot Product
9093141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src1.w
9103141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
9113141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * DP2 - 2-component Dot Product
9123141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst = src0.x \times src1.x + src0.y \times src1.y
9133141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
9143141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * DP2A - 2-component Dot Product And Add
9153141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   dst = src0.x \times src1.x + src0.y \times src1.y + src2.x
9163141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
9173141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * NOTE: these are translated into sequence of MUL/MAD(/ADD) scalar
9183141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * operations, which is what you'd prefer for a ISA that is natively
9193141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * scalar.  Probably a native vector ISA would at least already have
9203141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * DP4/DP3 instructions, but perhaps there is room for an alternative
9213141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * translation for DPH/DP2/DP2A using vector instructions.
9223141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
9233141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; needs: 1 tmp
9243141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MUL tmpA.x, src0.x, src1.x
9253141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * MAD tmpA.x, src0.y, src1.y, tmpA.x
9263141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * if (DPH || DP3 || DP4) {
9273141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   MAD tmpA.x, src0.z, src1.z, tmpA.x
9283141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   if (DPH) {
9293141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *     ADD tmpA.x, src1.w, tmpA.x
9303141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   } else if (DP4) {
9313141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *     MAD tmpA.x, src0.w, src1.w, tmpA.x
9323141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   }
9333141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * } else if (DP2A) {
9343141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   ADD tmpA.x, src2.x, tmpA.x
9353141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * }
9363141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * ; fixup last instruction to replicate into dst
9373141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
9383141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DP4_GROW  (NINST(2) + NINST(3) + NINST(3) + NINST(3) - OINST(2))
9393141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DP3_GROW  (NINST(2) + NINST(3) + NINST(3) - OINST(2))
9403141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DPH_GROW  (NINST(2) + NINST(3) + NINST(3) + NINST(2) - OINST(2))
9413141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DP2_GROW  (NINST(2) + NINST(3) - OINST(2))
9423141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DP2A_GROW (NINST(2) + NINST(3) + NINST(2) - OINST(3))
9433141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define DOTP_TMP  1
9443141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
9453141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_dotp(struct tgsi_transform_context *tctx,
94619df602b39ec03f61edec308ad568be118beb3acEric Anholt               struct tgsi_full_instruction *inst)
9473141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
948f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
94919df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_dst_register *dst  = &inst->Dst[0];
95019df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src0 = &inst->Src[0];
95119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src1 = &inst->Src[1];
95219df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *src2 = &inst->Src[2]; /* only DP2A */
95319df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
95419df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned opcode = inst->Instruction.Opcode;
95519df602b39ec03f61edec308ad568be118beb3acEric Anholt
95619df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* NOTE: any potential last instruction must replicate src on all
95719df602b39ec03f61edec308ad568be118beb3acEric Anholt    * components (since it could be re-written to write to final dst)
95819df602b39ec03f61edec308ad568be118beb3acEric Anholt    */
95919df602b39ec03f61edec308ad568be118beb3acEric Anholt
96019df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZW) {
96119df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MUL tmpA.x, src0.x, src1.x */
96219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
96319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MUL;
96419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
96519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
96619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
96719df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src0, SWIZ(X, _, _, _));
96819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], src1, SWIZ(X, _, _, _));
96919df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
97019df602b39ec03f61edec308ad568be118beb3acEric Anholt
97119df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MAD tmpA.x, src0.y, src1.y, tmpA.x */
97219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
97319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MAD;
97419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
97519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
97619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 3;
97719df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], src0, SWIZ(Y, Y, Y, Y));
97819df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], src1, SWIZ(Y, Y, Y, Y));
97919df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[2], &ctx->tmp[A].src, SWIZ(X, X, X, X));
98019df602b39ec03f61edec308ad568be118beb3acEric Anholt
98119df602b39ec03f61edec308ad568be118beb3acEric Anholt      if ((opcode == TGSI_OPCODE_DPH) ||
98219df602b39ec03f61edec308ad568be118beb3acEric Anholt          (opcode == TGSI_OPCODE_DP3) ||
98319df602b39ec03f61edec308ad568be118beb3acEric Anholt          (opcode == TGSI_OPCODE_DP4)) {
98419df602b39ec03f61edec308ad568be118beb3acEric Anholt         tctx->emit_instruction(tctx, &new_inst);
98519df602b39ec03f61edec308ad568be118beb3acEric Anholt
98619df602b39ec03f61edec308ad568be118beb3acEric Anholt         /* MAD tmpA.x, src0.z, src1.z, tmpA.x */
98719df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst = tgsi_default_full_instruction();
98819df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst.Instruction.Opcode = TGSI_OPCODE_MAD;
98919df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst.Instruction.NumDstRegs = 1;
99019df602b39ec03f61edec308ad568be118beb3acEric Anholt         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
99119df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst.Instruction.NumSrcRegs = 3;
99219df602b39ec03f61edec308ad568be118beb3acEric Anholt         reg_src(&new_inst.Src[0], src0, SWIZ(Z, Z, Z, Z));
99319df602b39ec03f61edec308ad568be118beb3acEric Anholt         reg_src(&new_inst.Src[1], src1, SWIZ(Z, Z, Z, Z));
99419df602b39ec03f61edec308ad568be118beb3acEric Anholt         reg_src(&new_inst.Src[2], &ctx->tmp[A].src, SWIZ(X, X, X, X));
99519df602b39ec03f61edec308ad568be118beb3acEric Anholt
99619df602b39ec03f61edec308ad568be118beb3acEric Anholt         if (opcode == TGSI_OPCODE_DPH) {
99719df602b39ec03f61edec308ad568be118beb3acEric Anholt            tctx->emit_instruction(tctx, &new_inst);
99819df602b39ec03f61edec308ad568be118beb3acEric Anholt
99919df602b39ec03f61edec308ad568be118beb3acEric Anholt            /* ADD tmpA.x, src1.w, tmpA.x */
100019df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst = tgsi_default_full_instruction();
100119df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
100219df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst.Instruction.NumDstRegs = 1;
100319df602b39ec03f61edec308ad568be118beb3acEric Anholt            reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
100419df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst.Instruction.NumSrcRegs = 2;
100519df602b39ec03f61edec308ad568be118beb3acEric Anholt            reg_src(&new_inst.Src[0], src1, SWIZ(W, W, W, W));
100619df602b39ec03f61edec308ad568be118beb3acEric Anholt            reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, X, X, X));
100719df602b39ec03f61edec308ad568be118beb3acEric Anholt         } else if (opcode == TGSI_OPCODE_DP4) {
100819df602b39ec03f61edec308ad568be118beb3acEric Anholt            tctx->emit_instruction(tctx, &new_inst);
100919df602b39ec03f61edec308ad568be118beb3acEric Anholt
101019df602b39ec03f61edec308ad568be118beb3acEric Anholt            /* MAD tmpA.x, src0.w, src1.w, tmpA.x */
101119df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst = tgsi_default_full_instruction();
101219df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst.Instruction.Opcode = TGSI_OPCODE_MAD;
101319df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst.Instruction.NumDstRegs = 1;
101419df602b39ec03f61edec308ad568be118beb3acEric Anholt            reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
101519df602b39ec03f61edec308ad568be118beb3acEric Anholt            new_inst.Instruction.NumSrcRegs = 3;
101619df602b39ec03f61edec308ad568be118beb3acEric Anholt            reg_src(&new_inst.Src[0], src0, SWIZ(W, W, W, W));
101719df602b39ec03f61edec308ad568be118beb3acEric Anholt            reg_src(&new_inst.Src[1], src1, SWIZ(W, W, W, W));
101819df602b39ec03f61edec308ad568be118beb3acEric Anholt            reg_src(&new_inst.Src[2], &ctx->tmp[A].src, SWIZ(X, X, X, X));
101919df602b39ec03f61edec308ad568be118beb3acEric Anholt         }
102019df602b39ec03f61edec308ad568be118beb3acEric Anholt      } else if (opcode == TGSI_OPCODE_DP2A) {
102119df602b39ec03f61edec308ad568be118beb3acEric Anholt         tctx->emit_instruction(tctx, &new_inst);
102219df602b39ec03f61edec308ad568be118beb3acEric Anholt
102319df602b39ec03f61edec308ad568be118beb3acEric Anholt         /* ADD tmpA.x, src2.x, tmpA.x */
102419df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst = tgsi_default_full_instruction();
102519df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
102619df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst.Instruction.NumDstRegs = 1;
102719df602b39ec03f61edec308ad568be118beb3acEric Anholt         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_X);
102819df602b39ec03f61edec308ad568be118beb3acEric Anholt         new_inst.Instruction.NumSrcRegs = 2;
102919df602b39ec03f61edec308ad568be118beb3acEric Anholt         reg_src(&new_inst.Src[0], src2, SWIZ(X, X, X, X));
103019df602b39ec03f61edec308ad568be118beb3acEric Anholt         reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, X, X, X));
103119df602b39ec03f61edec308ad568be118beb3acEric Anholt      }
103219df602b39ec03f61edec308ad568be118beb3acEric Anholt
103319df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* fixup last instruction to write to dst: */
103419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XYZW);
103519df602b39ec03f61edec308ad568be118beb3acEric Anholt
103619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
103719df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
10383141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
10393141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
104023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King/* FLR - floor, CEIL - ceil
104123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * ; needs: 1 tmp
104223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * if (CEIL) {
104323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   FRC tmpA, -src
104423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   ADD dst, src, tmpA
104523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * } else {
104623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   FRC tmpA, src
104723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King *   SUB dst, src, tmpA
104823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King * }
104923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King */
105023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King#define FLR_GROW (NINST(1) + NINST(2) - OINST(1))
105123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King#define CEIL_GROW (NINST(1) + NINST(2) - OINST(1))
105223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King#define FLR_TMP 1
105323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King#define CEIL_TMP 1
105423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell Kingstatic void
105523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell Kingtransform_flr_ceil(struct tgsi_transform_context *tctx,
105623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King                   struct tgsi_full_instruction *inst)
105723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King{
105823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
105923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   struct tgsi_full_dst_register *dst  = &inst->Dst[0];
106023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   struct tgsi_full_src_register *src0 = &inst->Src[0];
106123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   struct tgsi_full_instruction new_inst;
106223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   unsigned opcode = inst->Instruction.Opcode;
106323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King
106423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZW) {
106523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      /* FLR: FRC tmpA, src  CEIL: FRC tmpA, -src */
106623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      new_inst = tgsi_default_full_instruction();
106723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      new_inst.Instruction.Opcode = TGSI_OPCODE_FRC;
106823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      new_inst.Instruction.NumDstRegs = 1;
106923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XYZW);
107023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      new_inst.Instruction.NumSrcRegs = 1;
107123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
107223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King
107323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      if (opcode == TGSI_OPCODE_CEIL)
107423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         new_inst.Src[0].Register.Negate = !new_inst.Src[0].Register.Negate;
107523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      tctx->emit_instruction(tctx, &new_inst);
107623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King
107723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      /* FLR: SUB dst, src, tmpA  CEIL: ADD dst, src, tmpA */
107823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      new_inst = tgsi_default_full_instruction();
1079d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák      new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
108023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      new_inst.Instruction.NumDstRegs = 1;
108123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XYZW);
108223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      new_inst.Instruction.NumSrcRegs = 2;
108323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
108423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, Y, Z, W));
1085d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák      if (opcode == TGSI_OPCODE_FLR)
1086d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák         new_inst.Src[1].Register.Negate = 1;
108723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      tctx->emit_instruction(tctx, &new_inst);
108823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   }
108923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King}
109023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King
109165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King/* TRUNC - truncate off fractional part
109265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *  dst.x = trunc(src.x)
109365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *  dst.y = trunc(src.y)
109465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *  dst.z = trunc(src.z)
109565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *  dst.w = trunc(src.w)
109665460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *
109765460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King * ; needs: 1 tmp
109865460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King * if (lower FLR) {
109965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *   FRC tmpA, |src|
110065460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *   SUB tmpA, |src|, tmpA
110165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King * } else {
110265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King *   FLR tmpA, |src|
110365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King * }
110465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King * CMP dst, src, -tmpA, tmpA
110565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King */
110665460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King#define TRUNC_GROW (NINST(1) + NINST(2) + NINST(3) - OINST(1))
110765460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King#define TRUNC_TMP 1
110865460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell Kingstatic void
110965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell Kingtransform_trunc(struct tgsi_transform_context *tctx,
111065460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King                struct tgsi_full_instruction *inst)
111165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King{
111265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
111365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   struct tgsi_full_dst_register *dst  = &inst->Dst[0];
111465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   struct tgsi_full_src_register *src0 = &inst->Src[0];
111565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   struct tgsi_full_instruction new_inst;
111665460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King
111765460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   if (dst->Register.WriteMask & TGSI_WRITEMASK_XYZW) {
111865460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      if (ctx->config->lower_FLR) {
111965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst = tgsi_default_full_instruction();
112065460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.Opcode = TGSI_OPCODE_FRC;
112165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.NumDstRegs = 1;
112265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XYZW);
112365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.NumSrcRegs = 1;
112465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
112565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Src[0].Register.Absolute = true;
112665460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Src[0].Register.Negate = false;
112765460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         tctx->emit_instruction(tctx, &new_inst);
112865460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King
112965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst = tgsi_default_full_instruction();
1130d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák         new_inst.Instruction.Opcode = TGSI_OPCODE_ADD;
113165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.NumDstRegs = 1;
113265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XYZW);
113365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.NumSrcRegs = 2;
113465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
113565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Src[0].Register.Absolute = true;
113665460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Src[0].Register.Negate = false;
113765460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, Y, Z, W));
1138d995115b1733ec14182e6bb4653b8f8389b87518Marek Olšák         new_inst.Src[1].Register.Negate = 1;
113965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         tctx->emit_instruction(tctx, &new_inst);
114065460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      } else {
114165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst = tgsi_default_full_instruction();
114265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.Opcode = TGSI_OPCODE_FLR;
114365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.NumDstRegs = 1;
114465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, TGSI_WRITEMASK_XYZW);
114565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Instruction.NumSrcRegs = 1;
114665460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
114765460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Src[0].Register.Absolute = true;
114865460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         new_inst.Src[0].Register.Negate = false;
114965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         tctx->emit_instruction(tctx, &new_inst);
115065460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      }
115165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King
115265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      new_inst = tgsi_default_full_instruction();
115365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      new_inst.Instruction.Opcode = TGSI_OPCODE_CMP;
115465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      new_inst.Instruction.NumDstRegs = 1;
115565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      reg_dst(&new_inst.Dst[0], dst, TGSI_WRITEMASK_XYZW);
115665460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      new_inst.Instruction.NumSrcRegs = 3;
115765460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      reg_src(&new_inst.Src[0], src0, SWIZ(X, Y, Z, W));
115865460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      reg_src(&new_inst.Src[1], &ctx->tmp[A].src, SWIZ(X, Y, Z, W));
115965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      new_inst.Src[1].Register.Negate = true;
116065460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      reg_src(&new_inst.Src[2], &ctx->tmp[A].src, SWIZ(X, Y, Z, W));
116165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      tctx->emit_instruction(tctx, &new_inst);
116265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   }
116365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King}
116465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King
11653141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* Inserts a MOV_SAT for the needed components of tex coord.  Note that
11663141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * in the case of TXP, the clamping must happen *after* projection, so
11673141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * we need to lower TXP to TEX.
11683141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *
11693141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   MOV tmpA, src0
11703141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   if (opc == TXP) {
11713141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *     ; do perspective division manually before clamping:
11723141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *     RCP tmpB, tmpA.w
11733141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *     MUL tmpB.<pmask>, tmpA, tmpB.xxxx
11743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *     opc = TEX;
11753141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   }
11763141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   MOV_SAT tmpA.<mask>, tmpA  ; <mask> is the clamped s/t/r coords
11773141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt *   <opc> dst, tmpA, ...
11783141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
11793141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define SAMP_GROW (NINST(1) + NINST(1) + NINST(2) + NINST(1))
11803141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define SAMP_TMP  2
11813141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic int
11823141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_samp(struct tgsi_transform_context *tctx,
118319df602b39ec03f61edec308ad568be118beb3acEric Anholt               struct tgsi_full_instruction *inst)
11843141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
1185f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
118619df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *coord = &inst->Src[0];
118719df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_src_register *samp;
118819df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
118919df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* mask is clamped coords, pmask is all coords (for projection): */
119019df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned mask = 0, pmask = 0, smask;
1191219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   unsigned tex = inst->Texture.Texture;
119219df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned opcode = inst->Instruction.Opcode;
1193219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   bool lower_txp = (opcode == TGSI_OPCODE_TXP) &&
1194219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark		   (ctx->config->lower_TXP & (1 << tex));
119519df602b39ec03f61edec308ad568be118beb3acEric Anholt
119619df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (opcode == TGSI_OPCODE_TXB2) {
119719df602b39ec03f61edec308ad568be118beb3acEric Anholt      samp = &inst->Src[2];
119819df602b39ec03f61edec308ad568be118beb3acEric Anholt   } else {
119919df602b39ec03f61edec308ad568be118beb3acEric Anholt      samp = &inst->Src[1];
120019df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
120119df602b39ec03f61edec308ad568be118beb3acEric Anholt
120219df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* convert sampler # to bitmask to test: */
120319df602b39ec03f61edec308ad568be118beb3acEric Anholt   smask = 1 << samp->Register.Index;
120419df602b39ec03f61edec308ad568be118beb3acEric Anholt
120519df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* check if we actually need to lower this one: */
1206219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   if (!(ctx->saturate & smask) && !lower_txp)
120719df602b39ec03f61edec308ad568be118beb3acEric Anholt      return -1;
120819df602b39ec03f61edec308ad568be118beb3acEric Anholt
120919df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* figure out which coordinates need saturating:
121019df602b39ec03f61edec308ad568be118beb3acEric Anholt    *   - RECT textures should not get saturated
121119df602b39ec03f61edec308ad568be118beb3acEric Anholt    *   - array index coords should not get saturated
121219df602b39ec03f61edec308ad568be118beb3acEric Anholt    */
1213219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   switch (tex) {
121419df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_3D:
121519df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_CUBE:
121619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_CUBE_ARRAY:
121719df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_SHADOWCUBE:
121819df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
121919df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (ctx->config->saturate_r & smask)
122019df602b39ec03f61edec308ad568be118beb3acEric Anholt         mask |= TGSI_WRITEMASK_Z;
122119df602b39ec03f61edec308ad568be118beb3acEric Anholt      pmask |= TGSI_WRITEMASK_Z;
122219df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* fallthrough */
122319df602b39ec03f61edec308ad568be118beb3acEric Anholt
122419df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_2D:
122519df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_2D_ARRAY:
122619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_SHADOW2D:
122719df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_SHADOW2D_ARRAY:
122819df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_2D_MSAA:
122919df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_2D_ARRAY_MSAA:
123019df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (ctx->config->saturate_t & smask)
123119df602b39ec03f61edec308ad568be118beb3acEric Anholt         mask |= TGSI_WRITEMASK_Y;
123219df602b39ec03f61edec308ad568be118beb3acEric Anholt      pmask |= TGSI_WRITEMASK_Y;
123319df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* fallthrough */
123419df602b39ec03f61edec308ad568be118beb3acEric Anholt
123519df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_1D:
123619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_1D_ARRAY:
123719df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_SHADOW1D:
123819df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_TEXTURE_SHADOW1D_ARRAY:
123919df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (ctx->config->saturate_s & smask)
124019df602b39ec03f61edec308ad568be118beb3acEric Anholt         mask |= TGSI_WRITEMASK_X;
124119df602b39ec03f61edec308ad568be118beb3acEric Anholt      pmask |= TGSI_WRITEMASK_X;
124219df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
124319df602b39ec03f61edec308ad568be118beb3acEric Anholt
1244219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   case TGSI_TEXTURE_RECT:
1245219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   case TGSI_TEXTURE_SHADOWRECT:
1246219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark      /* we don't saturate, but in case of lower_txp we
1247219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark       * still need to do the perspective divide:
1248219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark       */
1249219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark       pmask = TGSI_WRITEMASK_XY;
1250219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark       break;
125119df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
125219df602b39ec03f61edec308ad568be118beb3acEric Anholt
125319df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* sanity check.. driver could be asking to saturate a non-
125419df602b39ec03f61edec308ad568be118beb3acEric Anholt    * existent coordinate component:
125519df602b39ec03f61edec308ad568be118beb3acEric Anholt    */
1256219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   if (!mask && !lower_txp)
125719df602b39ec03f61edec308ad568be118beb3acEric Anholt      return -1;
125819df602b39ec03f61edec308ad568be118beb3acEric Anholt
125919df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* MOV tmpA, src0 */
126019df602b39ec03f61edec308ad568be118beb3acEric Anholt   create_mov(tctx, &ctx->tmp[A].dst, coord, TGSI_WRITEMASK_XYZW, 0);
126119df602b39ec03f61edec308ad568be118beb3acEric Anholt
126219df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* This is a bit sad.. we need to clamp *after* the coords
126319df602b39ec03f61edec308ad568be118beb3acEric Anholt    * are projected, which means lowering TXP to TEX and doing
126419df602b39ec03f61edec308ad568be118beb3acEric Anholt    * the projection ourself.  But since I haven't figured out
126519df602b39ec03f61edec308ad568be118beb3acEric Anholt    * how to make the lowering code deliver an electric shock
126619df602b39ec03f61edec308ad568be118beb3acEric Anholt    * to anyone using GL_CLAMP, we must do this instead:
126719df602b39ec03f61edec308ad568be118beb3acEric Anholt    */
126819df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (opcode == TGSI_OPCODE_TXP) {
126919df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* RCP tmpB.x tmpA.w */
127019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
127119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_RCP;
127219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
127319df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[B].dst, TGSI_WRITEMASK_X);
127419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 1;
127519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(W, _, _, _));
127619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
127719df602b39ec03f61edec308ad568be118beb3acEric Anholt
127819df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* MUL tmpA.mask, tmpA, tmpB.xxxx */
127919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
128019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_MUL;
128119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
128219df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_dst(&new_inst.Dst[0], &ctx->tmp[A].dst, pmask);
128319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 2;
128419df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[0], &ctx->tmp[A].src, SWIZ(X, Y, Z, W));
128519df602b39ec03f61edec308ad568be118beb3acEric Anholt      reg_src(&new_inst.Src[1], &ctx->tmp[B].src, SWIZ(X, X, X, X));
128619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
128719df602b39ec03f61edec308ad568be118beb3acEric Anholt
128819df602b39ec03f61edec308ad568be118beb3acEric Anholt      opcode = TGSI_OPCODE_TEX;
128919df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
129019df602b39ec03f61edec308ad568be118beb3acEric Anholt
129119df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* MOV_SAT tmpA.<mask>, tmpA */
1292219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   if (mask) {
1293e1c4e8aaaafddd0e04cf2a16e28ef8f1e09d8b44Marek Olšák      create_mov(tctx, &ctx->tmp[A].dst, &ctx->tmp[A].src, mask, 1);
1294219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   }
129519df602b39ec03f61edec308ad568be118beb3acEric Anholt
129619df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* modify the texture samp instruction to take fixed up coord: */
129719df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst = *inst;
129819df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst.Instruction.Opcode = opcode;
129919df602b39ec03f61edec308ad568be118beb3acEric Anholt   new_inst.Src[0] = ctx->tmp[A].src;
130019df602b39ec03f61edec308ad568be118beb3acEric Anholt   tctx->emit_instruction(tctx, &new_inst);
130119df602b39ec03f61edec308ad568be118beb3acEric Anholt
130219df602b39ec03f61edec308ad568be118beb3acEric Anholt   return 0;
13033141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
13043141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
13053141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* Two-sided color emulation:
13063141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * For each COLOR input, create a corresponding BCOLOR input, plus
13073141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * CMP instruction to select front or back color based on FACE
13083141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
130919df602b39ec03f61edec308ad568be118beb3acEric Anholt#define TWOSIDE_GROW(n)  (                      \
131019df602b39ec03f61edec308ad568be118beb3acEric Anholt      2 +         /* FACE */                    \
13114abb789bca95e9c23b2339ea7732833203c94639Rob Clark      ((n) * 3) + /* IN[], BCOLOR[n], <intrp> */\
131219df602b39ec03f61edec308ad568be118beb3acEric Anholt      ((n) * 1) + /* TEMP[] */                  \
131319df602b39ec03f61edec308ad568be118beb3acEric Anholt      ((n) * NINST(3))   /* CMP instr */        \
131419df602b39ec03f61edec308ad568be118beb3acEric Anholt      )
13153141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
13163141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
13173141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtemit_twoside(struct tgsi_transform_context *tctx)
13183141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
1319f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
132019df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_shader_info *info = ctx->info;
132119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_declaration decl;
132219df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_instruction new_inst;
132319df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned inbase, tmpbase;
132419df602b39ec03f61edec308ad568be118beb3acEric Anholt   int i;
132519df602b39ec03f61edec308ad568be118beb3acEric Anholt
132619df602b39ec03f61edec308ad568be118beb3acEric Anholt   inbase  = info->file_max[TGSI_FILE_INPUT] + 1;
132719df602b39ec03f61edec308ad568be118beb3acEric Anholt   tmpbase = info->file_max[TGSI_FILE_TEMPORARY] + 1;
132819df602b39ec03f61edec308ad568be118beb3acEric Anholt
132919df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* additional inputs for BCOLOR's */
133019df602b39ec03f61edec308ad568be118beb3acEric Anholt   for (i = 0; i < ctx->two_side_colors; i++) {
13314abb789bca95e9c23b2339ea7732833203c94639Rob Clark      unsigned in_idx = ctx->two_side_idx[i];
133219df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl = tgsi_default_full_declaration();
133319df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Declaration.File = TGSI_FILE_INPUT;
133419df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Declaration.Semantic = true;
133519df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Range.First = decl.Range.Last = inbase + i;
133619df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Semantic.Name = TGSI_SEMANTIC_BCOLOR;
13374abb789bca95e9c23b2339ea7732833203c94639Rob Clark      decl.Semantic.Index = info->input_semantic_index[in_idx];
13384abb789bca95e9c23b2339ea7732833203c94639Rob Clark      decl.Declaration.Interpolate = true;
13394abb789bca95e9c23b2339ea7732833203c94639Rob Clark      decl.Interp.Interpolate = info->input_interpolate[in_idx];
13404abb789bca95e9c23b2339ea7732833203c94639Rob Clark      decl.Interp.Location = info->input_interpolate_loc[in_idx];
13414abb789bca95e9c23b2339ea7732833203c94639Rob Clark      decl.Interp.CylindricalWrap = info->input_cylindrical_wrap[in_idx];
134219df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_declaration(tctx, &decl);
134319df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
134419df602b39ec03f61edec308ad568be118beb3acEric Anholt
134519df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* additional input for FACE */
134619df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (ctx->two_side_colors && (ctx->face_idx == -1)) {
134719df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl = tgsi_default_full_declaration();
134819df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Declaration.File = TGSI_FILE_INPUT;
134919df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Declaration.Semantic = true;
135019df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Range.First = decl.Range.Last = inbase + ctx->two_side_colors;
135119df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Semantic.Name = TGSI_SEMANTIC_FACE;
135219df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Semantic.Index = 0;
135319df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_declaration(tctx, &decl);
135419df602b39ec03f61edec308ad568be118beb3acEric Anholt
135519df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->face_idx = decl.Range.First;
135619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
135719df602b39ec03f61edec308ad568be118beb3acEric Anholt
135819df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* additional temps for COLOR/BCOLOR selection: */
135919df602b39ec03f61edec308ad568be118beb3acEric Anholt   for (i = 0; i < ctx->two_side_colors; i++) {
136019df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl = tgsi_default_full_declaration();
136119df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Declaration.File = TGSI_FILE_TEMPORARY;
136219df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Range.First = decl.Range.Last = tmpbase + ctx->numtmp + i;
136319df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_declaration(tctx, &decl);
136419df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
136519df602b39ec03f61edec308ad568be118beb3acEric Anholt
136619df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* and finally additional instructions to select COLOR/BCOLOR: */
136719df602b39ec03f61edec308ad568be118beb3acEric Anholt   for (i = 0; i < ctx->two_side_colors; i++) {
136819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst = tgsi_default_full_instruction();
136919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.Opcode = TGSI_OPCODE_CMP;
137019df602b39ec03f61edec308ad568be118beb3acEric Anholt
137119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumDstRegs = 1;
137219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Dst[0].Register.File  = TGSI_FILE_TEMPORARY;
137319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Dst[0].Register.Index = tmpbase + ctx->numtmp + i;
137419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
137519df602b39ec03f61edec308ad568be118beb3acEric Anholt
137619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Instruction.NumSrcRegs = 3;
137719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.File  = TGSI_FILE_INPUT;
137819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.Index = ctx->face_idx;
137919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_X;
138019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X;
138119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_X;
138219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_X;
138319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[1].Register.File  = TGSI_FILE_INPUT;
138419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[1].Register.Index = inbase + i;
138519df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[1].Register.SwizzleX = TGSI_SWIZZLE_X;
138619df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_Y;
138719df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[1].Register.SwizzleZ = TGSI_SWIZZLE_Z;
138819df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[1].Register.SwizzleW = TGSI_SWIZZLE_W;
138919df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[2].Register.File  = TGSI_FILE_INPUT;
139019df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[2].Register.Index = ctx->two_side_idx[i];
139119df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[2].Register.SwizzleX = TGSI_SWIZZLE_X;
139219df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[2].Register.SwizzleY = TGSI_SWIZZLE_Y;
139319df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[2].Register.SwizzleZ = TGSI_SWIZZLE_Z;
139419df602b39ec03f61edec308ad568be118beb3acEric Anholt      new_inst.Src[2].Register.SwizzleW = TGSI_SWIZZLE_W;
139519df602b39ec03f61edec308ad568be118beb3acEric Anholt
139619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, &new_inst);
139719df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
13983141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
13993141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
14003141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
14013141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtemit_decls(struct tgsi_transform_context *tctx)
14023141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
1403f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
140419df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_shader_info *info = ctx->info;
140519df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_declaration decl;
140619df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_full_immediate immed;
140719df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned tmpbase;
140819df602b39ec03f61edec308ad568be118beb3acEric Anholt   int i;
140919df602b39ec03f61edec308ad568be118beb3acEric Anholt
141019df602b39ec03f61edec308ad568be118beb3acEric Anholt   tmpbase = info->file_max[TGSI_FILE_TEMPORARY] + 1;
141119df602b39ec03f61edec308ad568be118beb3acEric Anholt
141219df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx->color_base = tmpbase + ctx->numtmp;
141319df602b39ec03f61edec308ad568be118beb3acEric Anholt
141419df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* declare immediate: */
141519df602b39ec03f61edec308ad568be118beb3acEric Anholt   immed = tgsi_default_full_immediate();
141619df602b39ec03f61edec308ad568be118beb3acEric Anholt   immed.Immediate.NrTokens = 1 + 4; /* one for the token itself */
141719df602b39ec03f61edec308ad568be118beb3acEric Anholt   immed.u[0].Float = 0.0;
141819df602b39ec03f61edec308ad568be118beb3acEric Anholt   immed.u[1].Float = 1.0;
141919df602b39ec03f61edec308ad568be118beb3acEric Anholt   immed.u[2].Float = 128.0;
142019df602b39ec03f61edec308ad568be118beb3acEric Anholt   immed.u[3].Float = 0.0;
142119df602b39ec03f61edec308ad568be118beb3acEric Anholt   tctx->emit_immediate(tctx, &immed);
142219df602b39ec03f61edec308ad568be118beb3acEric Anholt
142319df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx->imm.Register.File = TGSI_FILE_IMMEDIATE;
142419df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx->imm.Register.Index = info->immediate_count;
142519df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx->imm.Register.SwizzleX = TGSI_SWIZZLE_X;
142619df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx->imm.Register.SwizzleY = TGSI_SWIZZLE_Y;
142719df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx->imm.Register.SwizzleZ = TGSI_SWIZZLE_Z;
142819df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx->imm.Register.SwizzleW = TGSI_SWIZZLE_W;
142919df602b39ec03f61edec308ad568be118beb3acEric Anholt
143019df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* declare temp regs: */
143119df602b39ec03f61edec308ad568be118beb3acEric Anholt   for (i = 0; i < ctx->numtmp; i++) {
143219df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl = tgsi_default_full_declaration();
143319df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Declaration.File = TGSI_FILE_TEMPORARY;
143419df602b39ec03f61edec308ad568be118beb3acEric Anholt      decl.Range.First = decl.Range.Last = tmpbase + i;
143519df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_declaration(tctx, &decl);
143619df602b39ec03f61edec308ad568be118beb3acEric Anholt
143719df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].src.Register.File  = TGSI_FILE_TEMPORARY;
143819df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].src.Register.Index = tmpbase + i;
143919df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].src.Register.SwizzleX = TGSI_SWIZZLE_X;
144019df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].src.Register.SwizzleY = TGSI_SWIZZLE_Y;
144119df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].src.Register.SwizzleZ = TGSI_SWIZZLE_Z;
144219df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].src.Register.SwizzleW = TGSI_SWIZZLE_W;
144319df602b39ec03f61edec308ad568be118beb3acEric Anholt
144419df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].dst.Register.File  = TGSI_FILE_TEMPORARY;
144519df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].dst.Register.Index = tmpbase + i;
144619df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->tmp[i].dst.Register.WriteMask = TGSI_WRITEMASK_XYZW;
144719df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
144819df602b39ec03f61edec308ad568be118beb3acEric Anholt
144919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (ctx->two_side_colors)
145019df602b39ec03f61edec308ad568be118beb3acEric Anholt      emit_twoside(tctx);
14513141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
14523141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
14533141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
1454f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholtrename_color_inputs(struct tgsi_lowering_context *ctx,
145519df602b39ec03f61edec308ad568be118beb3acEric Anholt                    struct tgsi_full_instruction *inst)
14563141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
145719df602b39ec03f61edec308ad568be118beb3acEric Anholt   unsigned i, j;
145819df602b39ec03f61edec308ad568be118beb3acEric Anholt   for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
145919df602b39ec03f61edec308ad568be118beb3acEric Anholt      struct tgsi_src_register *src = &inst->Src[i].Register;
146019df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (src->File == TGSI_FILE_INPUT) {
146119df602b39ec03f61edec308ad568be118beb3acEric Anholt         for (j = 0; j < ctx->two_side_colors; j++) {
146219df602b39ec03f61edec308ad568be118beb3acEric Anholt            if (src->Index == ctx->two_side_idx[j]) {
146319df602b39ec03f61edec308ad568be118beb3acEric Anholt               src->File = TGSI_FILE_TEMPORARY;
146419df602b39ec03f61edec308ad568be118beb3acEric Anholt               src->Index = ctx->color_base + j;
146519df602b39ec03f61edec308ad568be118beb3acEric Anholt               break;
146619df602b39ec03f61edec308ad568be118beb3acEric Anholt            }
146719df602b39ec03f61edec308ad568be118beb3acEric Anholt         }
146819df602b39ec03f61edec308ad568be118beb3acEric Anholt      }
146919df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
14703141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
14713141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
14723141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
14733141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtstatic void
14743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholttransform_instr(struct tgsi_transform_context *tctx,
14753141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt		struct tgsi_full_instruction *inst)
14763141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
1477f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context *ctx = tgsi_lowering_context(tctx);
147819df602b39ec03f61edec308ad568be118beb3acEric Anholt
147919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (!ctx->emitted_decls) {
148019df602b39ec03f61edec308ad568be118beb3acEric Anholt      emit_decls(tctx);
148119df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx->emitted_decls = 1;
148219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
148319df602b39ec03f61edec308ad568be118beb3acEric Anholt
148419df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* if emulating two-sided-color, we need to re-write some
148519df602b39ec03f61edec308ad568be118beb3acEric Anholt    * src registers:
148619df602b39ec03f61edec308ad568be118beb3acEric Anholt    */
148719df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (ctx->two_side_colors)
148819df602b39ec03f61edec308ad568be118beb3acEric Anholt      rename_color_inputs(ctx, inst);
148919df602b39ec03f61edec308ad568be118beb3acEric Anholt
149019df602b39ec03f61edec308ad568be118beb3acEric Anholt   switch (inst->Instruction.Opcode) {
149119df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_DST:
149219df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_DST)
149319df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
149419df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_dst(tctx, inst);
149519df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
149619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_XPD:
149719df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_XPD)
149819df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
149919df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_xpd(tctx, inst);
150019df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
150119df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_SCS:
150219df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_SCS)
150319df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
150419df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_scs(tctx, inst);
150519df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
150619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_LRP:
150719df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_LRP)
150819df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
150919df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_lrp(tctx, inst);
151019df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
151119df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_FRC:
151219df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_FRC)
151319df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
151419df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_frc(tctx, inst);
151519df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
151619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_POW:
151719df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_POW)
151819df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
151919df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_pow(tctx, inst);
152019df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
152119df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_LIT:
152219df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_LIT)
152319df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
152419df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_lit(tctx, inst);
152519df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
152619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_EXP:
152719df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_EXP)
152819df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
152919df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_exp(tctx, inst);
153019df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
153119df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_LOG:
153219df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_LOG)
153319df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
153419df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_log(tctx, inst);
153519df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
153619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_DP4:
153719df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_DP4)
153819df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
153919df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_dotp(tctx, inst);
154019df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
154119df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_DP3:
154219df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_DP3)
154319df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
154419df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_dotp(tctx, inst);
154519df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
154619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_DPH:
154719df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_DPH)
154819df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
154919df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_dotp(tctx, inst);
155019df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
155119df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_DP2:
155219df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_DP2)
155319df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
155419df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_dotp(tctx, inst);
155519df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
155619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_DP2A:
155719df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (!ctx->config->lower_DP2A)
155819df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
155919df602b39ec03f61edec308ad568be118beb3acEric Anholt      transform_dotp(tctx, inst);
156019df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
156123e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   case TGSI_OPCODE_FLR:
156223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      if (!ctx->config->lower_FLR)
156323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         goto skip;
156423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      transform_flr_ceil(tctx, inst);
156523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      break;
156623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   case TGSI_OPCODE_CEIL:
156723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      if (!ctx->config->lower_CEIL)
156823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         goto skip;
156923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      transform_flr_ceil(tctx, inst);
157023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      break;
157165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   case TGSI_OPCODE_TRUNC:
157265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      if (!ctx->config->lower_TRUNC)
157365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         goto skip;
157465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      transform_trunc(tctx, inst);
157565460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      break;
157619df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_TEX:
157719df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_TXP:
157819df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_TXB:
157919df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_TXB2:
158019df602b39ec03f61edec308ad568be118beb3acEric Anholt   case TGSI_OPCODE_TXL:
158119df602b39ec03f61edec308ad568be118beb3acEric Anholt      if (transform_samp(tctx, inst))
158219df602b39ec03f61edec308ad568be118beb3acEric Anholt         goto skip;
158319df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
158419df602b39ec03f61edec308ad568be118beb3acEric Anholt   default:
158519df602b39ec03f61edec308ad568be118beb3acEric Anholt   skip:
158619df602b39ec03f61edec308ad568be118beb3acEric Anholt      tctx->emit_instruction(tctx, inst);
158719df602b39ec03f61edec308ad568be118beb3acEric Anholt      break;
158819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
15893141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
15903141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
15913141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt/* returns NULL if no lowering required, else returns the new
15923141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * tokens (which caller is required to free()).  In either case
15933141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt * returns the current info.
15943141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt */
15953141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholtconst struct tgsi_token *
1596f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholttgsi_transform_lowering(const struct tgsi_lowering_config *config,
1597f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt                        const struct tgsi_token *tokens,
1598f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt                        struct tgsi_shader_info *info)
15993141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt{
1600f9854e169f54c8a79c7c01733d74979d300d5dbaEric Anholt   struct tgsi_lowering_context ctx;
160119df602b39ec03f61edec308ad568be118beb3acEric Anholt   struct tgsi_token *newtoks;
160219df602b39ec03f61edec308ad568be118beb3acEric Anholt   int newlen, numtmp;
160319df602b39ec03f61edec308ad568be118beb3acEric Anholt
160419df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* sanity check in case limit is ever increased: */
1605b5105e67a860c6c3271ad7d48e2d80e84c3e8adeJosé Fonseca   STATIC_ASSERT((sizeof(config->saturate_s) * 8) >= PIPE_MAX_SAMPLERS);
160619df602b39ec03f61edec308ad568be118beb3acEric Anholt
160723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   /* sanity check the lowering */
160823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   assert(!(config->lower_FRC && (config->lower_FLR || config->lower_CEIL)));
160965460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   assert(!(config->lower_FRC && config->lower_TRUNC));
161023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King
161119df602b39ec03f61edec308ad568be118beb3acEric Anholt   memset(&ctx, 0, sizeof(ctx));
161219df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx.base.transform_instruction = transform_instr;
161319df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx.info = info;
161419df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx.config = config;
161519df602b39ec03f61edec308ad568be118beb3acEric Anholt
161619df602b39ec03f61edec308ad568be118beb3acEric Anholt   tgsi_scan_shader(tokens, info);
161719df602b39ec03f61edec308ad568be118beb3acEric Anholt
161819df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* if we are adding fragment shader support to emulate two-sided
161919df602b39ec03f61edec308ad568be118beb3acEric Anholt    * color, then figure out the number of additional inputs we need
162019df602b39ec03f61edec308ad568be118beb3acEric Anholt    * to create for BCOLOR's..
162119df602b39ec03f61edec308ad568be118beb3acEric Anholt    */
1622af249a7da9bf2621ab836d5074ef692677b11bbfMarek Olšák   if ((info->processor == PIPE_SHADER_FRAGMENT) &&
162319df602b39ec03f61edec308ad568be118beb3acEric Anholt       config->color_two_side) {
162419df602b39ec03f61edec308ad568be118beb3acEric Anholt      int i;
162519df602b39ec03f61edec308ad568be118beb3acEric Anholt      ctx.face_idx = -1;
162619df602b39ec03f61edec308ad568be118beb3acEric Anholt      for (i = 0; i <= info->file_max[TGSI_FILE_INPUT]; i++) {
162719df602b39ec03f61edec308ad568be118beb3acEric Anholt         if (info->input_semantic_name[i] == TGSI_SEMANTIC_COLOR)
162819df602b39ec03f61edec308ad568be118beb3acEric Anholt            ctx.two_side_idx[ctx.two_side_colors++] = i;
162919df602b39ec03f61edec308ad568be118beb3acEric Anholt         if (info->input_semantic_name[i] == TGSI_SEMANTIC_FACE)
163019df602b39ec03f61edec308ad568be118beb3acEric Anholt            ctx.face_idx = i;
163119df602b39ec03f61edec308ad568be118beb3acEric Anholt      }
163219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
163319df602b39ec03f61edec308ad568be118beb3acEric Anholt
163419df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx.saturate = config->saturate_r | config->saturate_s | config->saturate_t;
16353141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
16363141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#define OPCS(x) ((config->lower_ ## x) ? info->opcode_count[TGSI_OPCODE_ ## x] : 0)
163719df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* if there are no instructions to lower, then we are done: */
163819df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (!(OPCS(DST) ||
163919df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(XPD) ||
164019df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(SCS) ||
164119df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(LRP) ||
164219df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(FRC) ||
164319df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(POW) ||
164419df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(LIT) ||
164519df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(EXP) ||
164619df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(LOG) ||
164719df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(DP4) ||
164819df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(DP3) ||
164919df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(DPH) ||
165019df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(DP2) ||
165119df602b39ec03f61edec308ad568be118beb3acEric Anholt         OPCS(DP2A) ||
165223e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         OPCS(FLR) ||
165323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King         OPCS(CEIL) ||
165465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King         OPCS(TRUNC) ||
1655219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark         OPCS(TXP) ||
165619df602b39ec03f61edec308ad568be118beb3acEric Anholt         ctx.two_side_colors ||
165719df602b39ec03f61edec308ad568be118beb3acEric Anholt         ctx.saturate))
165819df602b39ec03f61edec308ad568be118beb3acEric Anholt      return NULL;
16593141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
16603141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#if 0  /* debug */
166119df602b39ec03f61edec308ad568be118beb3acEric Anholt   _debug_printf("BEFORE:");
166219df602b39ec03f61edec308ad568be118beb3acEric Anholt   tgsi_dump(tokens, 0);
16633141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#endif
16643141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
166519df602b39ec03f61edec308ad568be118beb3acEric Anholt   numtmp = 0;
166619df602b39ec03f61edec308ad568be118beb3acEric Anholt   newlen = tgsi_num_tokens(tokens);
166719df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(DST)) {
166819df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += DST_GROW * OPCS(DST);
166919df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, DST_TMP);
167019df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
167119df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(XPD)) {
167219df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += XPD_GROW * OPCS(XPD);
167319df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, XPD_TMP);
167419df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
167519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(SCS)) {
167619df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += SCS_GROW * OPCS(SCS);
167719df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, SCS_TMP);
167819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
167919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(LRP)) {
168019df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += LRP_GROW * OPCS(LRP);
168119df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, LRP_TMP);
168219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
168319df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(FRC)) {
168419df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += FRC_GROW * OPCS(FRC);
168519df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, FRC_TMP);
168619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
168719df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(POW)) {
168819df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += POW_GROW * OPCS(POW);
168919df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, POW_TMP);
169019df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
169119df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(LIT)) {
169219df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += LIT_GROW * OPCS(LIT);
169319df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, LIT_TMP);
169419df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
169519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(EXP)) {
169619df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += EXP_GROW * OPCS(EXP);
169719df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, EXP_TMP);
169819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
169919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(LOG)) {
170019df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += LOG_GROW * OPCS(LOG);
170119df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, LOG_TMP);
170219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
170319df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(DP4)) {
170419df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += DP4_GROW * OPCS(DP4);
170519df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, DOTP_TMP);
170619df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
170719df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(DP3)) {
170819df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += DP3_GROW * OPCS(DP3);
170919df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, DOTP_TMP);
171019df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
171119df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(DPH)) {
171219df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += DPH_GROW * OPCS(DPH);
171319df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, DOTP_TMP);
171419df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
171519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(DP2)) {
171619df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += DP2_GROW * OPCS(DP2);
171719df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, DOTP_TMP);
171819df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
171919df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (OPCS(DP2A)) {
172019df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += DP2A_GROW * OPCS(DP2A);
172119df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, DOTP_TMP);
172219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
172323e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   if (OPCS(FLR)) {
172423e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      newlen += FLR_GROW * OPCS(FLR);
172523e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      numtmp = MAX2(numtmp, FLR_TMP);
172623e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   }
172723e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   if (OPCS(CEIL)) {
172823e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      newlen += CEIL_GROW * OPCS(CEIL);
172923e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King      numtmp = MAX2(numtmp, CEIL_TMP);
173023e870a888e24b25f9b61a9b1e486e3ef2c7a12cRussell King   }
173165460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   if (OPCS(TRUNC)) {
173265460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      newlen += TRUNC_GROW * OPCS(TRUNC);
173365460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King      numtmp = MAX2(numtmp, TRUNC_TMP);
173465460cf4c87b9b0c423db80fbd31fd44fbfde7ceRussell King   }
1735219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark   if (ctx.saturate || config->lower_TXP) {
1736219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark      int n = 0;
1737219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark
1738219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark      if (ctx.saturate) {
1739219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark         n = info->opcode_count[TGSI_OPCODE_TEX] +
1740219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark            info->opcode_count[TGSI_OPCODE_TXP] +
1741219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark            info->opcode_count[TGSI_OPCODE_TXB] +
1742219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark            info->opcode_count[TGSI_OPCODE_TXB2] +
1743219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark            info->opcode_count[TGSI_OPCODE_TXL];
1744219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark      } else if (config->lower_TXP) {
1745219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark          n = info->opcode_count[TGSI_OPCODE_TXP];
1746219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark      }
1747219440ddebcd804d6b8cb0a79c4bbdd7701ea355Rob Clark
174819df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += SAMP_GROW * n;
174919df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp = MAX2(numtmp, SAMP_TMP);
175019df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
175119df602b39ec03f61edec308ad568be118beb3acEric Anholt
175219df602b39ec03f61edec308ad568be118beb3acEric Anholt   /* specifically don't include two_side_colors temps in the count: */
175319df602b39ec03f61edec308ad568be118beb3acEric Anholt   ctx.numtmp = numtmp;
175419df602b39ec03f61edec308ad568be118beb3acEric Anholt
175519df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (ctx.two_side_colors) {
175619df602b39ec03f61edec308ad568be118beb3acEric Anholt      newlen += TWOSIDE_GROW(ctx.two_side_colors);
175719df602b39ec03f61edec308ad568be118beb3acEric Anholt      /* note: we permanently consume temp regs, re-writing references
175819df602b39ec03f61edec308ad568be118beb3acEric Anholt       * to IN.COLOR[n] to TEMP[m] (holding the output of of the CMP
175919df602b39ec03f61edec308ad568be118beb3acEric Anholt       * instruction that selects which varying to use):
176019df602b39ec03f61edec308ad568be118beb3acEric Anholt       */
176119df602b39ec03f61edec308ad568be118beb3acEric Anholt      numtmp += ctx.two_side_colors;
176219df602b39ec03f61edec308ad568be118beb3acEric Anholt   }
176319df602b39ec03f61edec308ad568be118beb3acEric Anholt
176419df602b39ec03f61edec308ad568be118beb3acEric Anholt   newlen += 2 * numtmp;
176519df602b39ec03f61edec308ad568be118beb3acEric Anholt   newlen += 5;        /* immediate */
176619df602b39ec03f61edec308ad568be118beb3acEric Anholt
176719df602b39ec03f61edec308ad568be118beb3acEric Anholt   newtoks = tgsi_alloc_tokens(newlen);
176819df602b39ec03f61edec308ad568be118beb3acEric Anholt   if (!newtoks)
176919df602b39ec03f61edec308ad568be118beb3acEric Anholt      return NULL;
177019df602b39ec03f61edec308ad568be118beb3acEric Anholt
177119df602b39ec03f61edec308ad568be118beb3acEric Anholt   tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base);
177219df602b39ec03f61edec308ad568be118beb3acEric Anholt
177319df602b39ec03f61edec308ad568be118beb3acEric Anholt   tgsi_scan_shader(newtoks, info);
17743141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
17753141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#if 0  /* debug */
177619df602b39ec03f61edec308ad568be118beb3acEric Anholt   _debug_printf("AFTER:");
177719df602b39ec03f61edec308ad568be118beb3acEric Anholt   tgsi_dump(newtoks, 0);
17783141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt#endif
17793141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt
178019df602b39ec03f61edec308ad568be118beb3acEric Anholt   return newtoks;
17813141dc8e8794217e5aec094d3ce2e8a1c4e50e58Eric Anholt}
1782