11c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/*
21c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Copyright (C) 2008 Nicolai Haehnle.
31c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
41c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * All Rights Reserved.
51c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
61c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining
71c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * a copy of this software and associated documentation files (the
81c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * "Software"), to deal in the Software without restriction, including
91c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * without limitation the rights to use, copy, modify, merge, publish,
101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * distribute, sublicense, and/or sell copies of the Software, and to
111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * permit persons to whom the Software is furnished to do so, subject to
121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * the following conditions:
131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The above copyright notice and this permission notice (including the
151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * next paragraph) shall be included in all copies or substantial
161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * portions of the Software.
171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @file
301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Shareable transformations that transform "special" ALU instructions
321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * into ALU instructions that are supported by hardware.
331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_program_alu.h"
371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_compiler.h"
391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_compiler_util.h"
401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_instruction *emit1(
431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c, struct rc_instruction * after,
4473249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	rc_opcode Opcode, struct rc_sub_instruction * base,
4573249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	struct rc_dst_register DstReg, struct rc_src_register SrcReg)
461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *fpi = rc_insert_new_instruction(c, after);
481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4973249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	if (base) {
5073249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard		memcpy(&fpi->U.I, base, sizeof(struct rc_sub_instruction));
5173249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	}
5273249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard
531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.Opcode = Opcode;
541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.DstReg = DstReg;
551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.SrcReg[0] = SrcReg;
561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return fpi;
571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_instruction *emit2(
601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c, struct rc_instruction * after,
6173249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	rc_opcode Opcode, struct rc_sub_instruction * base,
6273249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	struct rc_dst_register DstReg,
631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register SrcReg0, struct rc_src_register SrcReg1)
641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *fpi = rc_insert_new_instruction(c, after);
661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6773249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	if (base) {
6873249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard		memcpy(&fpi->U.I, base, sizeof(struct rc_sub_instruction));
6973249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	}
7073249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard
711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.Opcode = Opcode;
721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.DstReg = DstReg;
731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.SrcReg[0] = SrcReg0;
741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.SrcReg[1] = SrcReg1;
751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return fpi;
761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_instruction *emit3(
791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c, struct rc_instruction * after,
8073249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	rc_opcode Opcode, struct rc_sub_instruction * base,
8173249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	struct rc_dst_register DstReg,
821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register SrcReg0, struct rc_src_register SrcReg1,
831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register SrcReg2)
841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *fpi = rc_insert_new_instruction(c, after);
861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8773249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	if (base) {
8873249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard		memcpy(&fpi->U.I, base, sizeof(struct rc_sub_instruction));
8973249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	}
9073249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard
911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.Opcode = Opcode;
921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.DstReg = DstReg;
931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.SrcReg[0] = SrcReg0;
941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.SrcReg[1] = SrcReg1;
951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	fpi->U.I.SrcReg[2] = SrcReg2;
961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return fpi;
971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_dst_register dstregtmpmask(int index, int mask)
1001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
10132faaea743ca74f4ba29184ef44ebf2c0e962a46Brian Paul	struct rc_dst_register dst = {0, 0, 0};
1021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	dst.File = RC_FILE_TEMPORARY;
1031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	dst.Index = index;
1041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	dst.WriteMask = mask;
1051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return dst;
1061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic const struct rc_src_register builtin_zero = {
1091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.File = RC_FILE_NONE,
1101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.Index = 0,
1111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.Swizzle = RC_SWIZZLE_0000
1121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
1131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic const struct rc_src_register builtin_one = {
1141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.File = RC_FILE_NONE,
1151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.Index = 0,
1161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.Swizzle = RC_SWIZZLE_1111
1171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
1183d32e589879806297258e36ea80aae5044293ca3Tom Stellard
1193d32e589879806297258e36ea80aae5044293ca3Tom Stellardstatic const struct rc_src_register builtin_half = {
1203d32e589879806297258e36ea80aae5044293ca3Tom Stellard	.File = RC_FILE_NONE,
1213d32e589879806297258e36ea80aae5044293ca3Tom Stellard	.Index = 0,
1223d32e589879806297258e36ea80aae5044293ca3Tom Stellard	.Swizzle = RC_SWIZZLE_HHHH
1233d32e589879806297258e36ea80aae5044293ca3Tom Stellard};
1243d32e589879806297258e36ea80aae5044293ca3Tom Stellard
1251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic const struct rc_src_register srcreg_undefined = {
1261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.File = RC_FILE_NONE,
1271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.Index = 0,
1281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	.Swizzle = RC_SWIZZLE_XYZW
1291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
1301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register srcreg(int file, int index)
1321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src = srcreg_undefined;
1341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src.File = file;
1351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src.Index = index;
1361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return src;
1371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register srcregswz(int file, int index, int swz)
1401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src = srcreg_undefined;
1421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src.File = file;
1431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src.Index = index;
1441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src.Swizzle = swz;
1451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return src;
1461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register absolute(struct rc_src_register reg)
1491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register newreg = reg;
1511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	newreg.Abs = 1;
1521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	newreg.Negate = RC_MASK_NONE;
1531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return newreg;
1541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register negate(struct rc_src_register reg)
1571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register newreg = reg;
1591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	newreg.Negate = newreg.Negate ^ RC_MASK_XYZW;
1601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return newreg;
1611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register swizzle(struct rc_src_register reg,
1641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_swizzle x, rc_swizzle y, rc_swizzle z, rc_swizzle w)
1651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register swizzled = reg;
1671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	swizzled.Swizzle = combine_swizzles4(reg.Swizzle, x, y, z, w);
1681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return swizzled;
1691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register swizzle_smear(struct rc_src_register reg,
1721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_swizzle x)
1731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return swizzle(reg, x, x, x, x);
1751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register swizzle_xxxx(struct rc_src_register reg)
1781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return swizzle_smear(reg, RC_SWIZZLE_X);
1801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register swizzle_yyyy(struct rc_src_register reg)
1831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return swizzle_smear(reg, RC_SWIZZLE_Y);
1851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register swizzle_zzzz(struct rc_src_register reg)
1881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return swizzle_smear(reg, RC_SWIZZLE_Z);
1901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_src_register swizzle_wwww(struct rc_src_register reg)
1931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return swizzle_smear(reg, RC_SWIZZLE_W);
1951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic int is_dst_safe_to_reuse(struct rc_instruction *inst)
1981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	const struct rc_opcode_info *info = rc_get_opcode_info(inst->U.I.Opcode);
2001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned i;
2011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	assert(info->HasDstReg);
2031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.DstReg.File != RC_FILE_TEMPORARY)
2051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
2061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (i = 0; i < info->NumSrcRegs; i++) {
2081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY &&
2091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		    inst->U.I.SrcReg[i].Index == inst->U.I.DstReg.Index)
2101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			return 0;
2111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return 1;
2141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_dst_register try_to_reuse_dst(struct radeon_compiler *c,
2171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					       struct rc_instruction *inst)
2181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned tmp;
2201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (is_dst_safe_to_reuse(inst))
2221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		tmp = inst->U.I.DstReg.Index;
2231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	else
2241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		tmp = rc_find_free_temporary(c);
2251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return dstregtmpmask(tmp, inst->U.I.DstReg.WriteMask);
2271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_ABS(struct radeon_compiler* c,
2301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
2311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src = inst->U.I.SrcReg[0];
2331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src.Abs = 1;
2341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src.Negate = RC_MASK_NONE;
23573249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit1(c, inst->Prev, RC_OPCODE_MOV, &inst->U.I, inst->U.I.DstReg, src);
2361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
2371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_CEIL(struct radeon_compiler* c,
2401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
2411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* Assuming:
2431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *     ceil(x) = -floor(-x)
2441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *
2451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * After inlining floor:
2461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *     ceil(x) = -(-x-frac(-x))
2471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *
2481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * After simplification:
2491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *     ceil(x) = x+frac(-x)
2501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 */
2511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
2531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dst, negate(inst->U.I.SrcReg[0]));
25473249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit2(c, inst->Prev, RC_OPCODE_ADD, &inst->U.I, inst->U.I.DstReg,
2551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[0], srcreg(RC_FILE_TEMPORARY, dst.Index));
2561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
2571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_CLAMP(struct radeon_compiler *c,
2601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *inst)
2611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* CLAMP dst, src, min, max
2631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *    into:
2641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * MIN tmp, src, max
2651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * MAX dst, tmp, min
2661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 */
2671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
2681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MIN, 0, dst,
2691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[0], inst->U.I.SrcReg[2]);
27073249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit2(c, inst->Prev, RC_OPCODE_MAX, &inst->U.I, inst->U.I.DstReg,
2711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, dst.Index), inst->U.I.SrcReg[1]);
2721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
2731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_DP2(struct radeon_compiler* c,
2761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
2771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src0 = inst->U.I.SrcReg[0];
2791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src1 = inst->U.I.SrcReg[1];
2801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Negate &= ~(RC_MASK_Z | RC_MASK_W);
2811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Swizzle &= ~(63 << (3 * 2));
2821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Swizzle |= (RC_SWIZZLE_ZERO << (3 * 2)) | (RC_SWIZZLE_ZERO << (3 * 3));
2831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src1.Negate &= ~(RC_MASK_Z | RC_MASK_W);
2841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src1.Swizzle &= ~(63 << (3 * 2));
2851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src1.Swizzle |= (RC_SWIZZLE_ZERO << (3 * 2)) | (RC_SWIZZLE_ZERO << (3 * 3));
28673249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit2(c, inst->Prev, RC_OPCODE_DP3, &inst->U.I, inst->U.I.DstReg, src0, src1);
2871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
2881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_DPH(struct radeon_compiler* c,
2911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
2921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src0 = inst->U.I.SrcReg[0];
2941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Negate &= ~RC_MASK_W;
2951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Swizzle &= ~(7 << (3 * 3));
2961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Swizzle |= RC_SWIZZLE_ONE << (3 * 3);
29773249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit2(c, inst->Prev, RC_OPCODE_DP4, &inst->U.I, inst->U.I.DstReg, src0, inst->U.I.SrcReg[1]);
2981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
2991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
3021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * [1, src0.y*src1.y, src0.z, src1.w]
3031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * So basically MUL with lotsa swizzling.
3041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
3051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_DST(struct radeon_compiler* c,
3061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
3071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
30873249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit2(c, inst->Prev, RC_OPCODE_MUL, &inst->U.I, inst->U.I.DstReg,
3091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(inst->U.I.SrcReg[0], RC_SWIZZLE_ONE, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_ONE),
3101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(inst->U.I.SrcReg[1], RC_SWIZZLE_ONE, RC_SWIZZLE_Y, RC_SWIZZLE_ONE, RC_SWIZZLE_W));
3111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
3121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_FLR(struct radeon_compiler* c,
3151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
3161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
3181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dst, inst->U.I.SrcReg[0]);
31973249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit2(c, inst->Prev, RC_OPCODE_ADD, &inst->U.I, inst->U.I.DstReg,
3201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[0], negate(srcreg(RC_FILE_TEMPORARY, dst.Index)));
3211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
3221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3247f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšákstatic void transform_TRUNC(struct radeon_compiler* c,
3257f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	struct rc_instruction* inst)
3267f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák{
3277f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	/* Definition of trunc:
3287f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	 *   trunc(x) = (abs(x) - fract(abs(x))) * sgn(x)
3297f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	 *
3307f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	 * The multiplication by sgn(x) can be simplified using CMP:
3317f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	 *   y * sgn(x) = (x < 0 ? -y : y)
3327f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	 */
3337f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
3347f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dst, absolute(inst->U.I.SrcReg[0]));
3357f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, absolute(inst->U.I.SrcReg[0]),
3367f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	      negate(srcreg(RC_FILE_TEMPORARY, dst.Index)));
3377f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg, inst->U.I.SrcReg[0],
3387f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	      negate(srcreg(RC_FILE_TEMPORARY, dst.Index)), srcreg(RC_FILE_TEMPORARY, dst.Index));
3397f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	rc_remove_instruction(inst);
3407f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák}
3417f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák
3421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
3431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Definition of LIT (from ARB_fragment_program):
3441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
3451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  tmp = VectorLoad(op0);
3461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  if (tmp.x < 0) tmp.x = 0;
3471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  if (tmp.y < 0) tmp.y = 0;
3481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
3491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
3501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  result.x = 1.0;
3511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  result.y = tmp.x;
3521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
3531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  result.w = 1.0;
3541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
3551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The longest path of computation is the one leading to result.z,
3561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * consisting of 5 operations. This implementation of LIT takes
3571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 5 slots, if the subsequent optimization passes are clever enough
3581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * to pair instructions correctly.
3591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
3601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_LIT(struct radeon_compiler* c,
3611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
3621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int constant;
3641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int constant_swizzle;
3651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int temp;
3661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register srctemp;
3671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	constant = rc_constants_add_immediate_scalar(&c->Program.Constants, -127.999999, &constant_swizzle);
3691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.DstReg.WriteMask != RC_MASK_XYZW || inst->U.I.DstReg.File != RC_FILE_TEMPORARY) {
3711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_instruction * inst_mov;
3721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst_mov = emit1(c, inst,
3741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			RC_OPCODE_MOV, 0, inst->U.I.DstReg,
3751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			srcreg(RC_FILE_TEMPORARY, rc_find_free_temporary(c)));
3761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
3781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.DstReg.Index = inst_mov->U.I.SrcReg[0].Index;
3791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
3801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	temp = inst->U.I.DstReg.Index;
3831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	srctemp = srcreg(RC_FILE_TEMPORARY, temp);
3841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* tmp.x = max(0.0, Src.x); */
3861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* tmp.y = max(0.0, Src.y); */
3871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* tmp.w = clamp(Src.z, -128+eps, 128-eps); */
3881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MAX, 0,
3891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(temp, RC_MASK_XYW),
3901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[0],
3911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(srcreg(RC_FILE_CONSTANT, constant),
3921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			RC_SWIZZLE_ZERO, RC_SWIZZLE_ZERO, RC_SWIZZLE_ZERO, constant_swizzle&3));
3931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MIN, 0,
3941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(temp, RC_MASK_Z),
3951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_wwww(srctemp),
3961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		negate(srcregswz(RC_FILE_CONSTANT, constant, constant_swizzle)));
3971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* tmp.w = Pow(tmp.y, tmp.w) */
3991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_LG2, 0,
4001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(temp, RC_MASK_W),
4011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_yyyy(srctemp));
4021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MUL, 0,
4031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(temp, RC_MASK_W),
4041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_wwww(srctemp),
4051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_zzzz(srctemp));
4061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_EX2, 0,
4071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(temp, RC_MASK_W),
4081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_wwww(srctemp));
4091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* tmp.z = (tmp.x > 0) ? tmp.w : 0.0 */
41173249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I,
4121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(temp, RC_MASK_Z),
4131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		negate(swizzle_xxxx(srctemp)),
4141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_wwww(srctemp),
4151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		builtin_zero);
4161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* tmp.x, tmp.y, tmp.w = 1.0, tmp.x, 1.0 */
41873249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit1(c, inst->Prev, RC_OPCODE_MOV, &inst->U.I,
4191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(temp, RC_MASK_XYW),
4201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(srctemp, RC_SWIZZLE_ONE, RC_SWIZZLE_X, RC_SWIZZLE_ONE, RC_SWIZZLE_ONE));
4211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
4231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_LRP(struct radeon_compiler* c,
4261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
4271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
4291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
4311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dst,
4321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[1], negate(inst->U.I.SrcReg[2]));
43373249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_MAD, &inst->U.I,
4341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.DstReg,
4351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[0], srcreg(RC_FILE_TEMPORARY, dst.Index), inst->U.I.SrcReg[2]);
4361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
4381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_POW(struct radeon_compiler* c,
4411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
4421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register tempdst = try_to_reuse_dst(c, inst);
4441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register tempsrc = srcreg(RC_FILE_TEMPORARY, tempdst.Index);
4451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	tempdst.WriteMask = RC_MASK_W;
4461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	tempsrc.Swizzle = RC_SWIZZLE_WWWW;
4471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_LG2, 0, tempdst, swizzle_xxxx(inst->U.I.SrcReg[0]));
4491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MUL, 0, tempdst, tempsrc, swizzle_xxxx(inst->U.I.SrcReg[1]));
45073249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit1(c, inst->Prev, RC_OPCODE_EX2, &inst->U.I, inst->U.I.DstReg, tempsrc);
4511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
4531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4553d32e589879806297258e36ea80aae5044293ca3Tom Stellard/* dst = ROUND(src) :
4563d32e589879806297258e36ea80aae5044293ca3Tom Stellard *   add = src + .5
4573d32e589879806297258e36ea80aae5044293ca3Tom Stellard *   frac = FRC(add)
4583d32e589879806297258e36ea80aae5044293ca3Tom Stellard *   dst = add - frac
4593d32e589879806297258e36ea80aae5044293ca3Tom Stellard *
4603d32e589879806297258e36ea80aae5044293ca3Tom Stellard * According to the GLSL spec, the implementor can decide which way to round
4613d32e589879806297258e36ea80aae5044293ca3Tom Stellard * when the fraction is .5.  We round down for .5.
4623d32e589879806297258e36ea80aae5044293ca3Tom Stellard *
4633d32e589879806297258e36ea80aae5044293ca3Tom Stellard */
4643d32e589879806297258e36ea80aae5044293ca3Tom Stellardstatic void transform_ROUND(struct radeon_compiler* c,
4653d32e589879806297258e36ea80aae5044293ca3Tom Stellard	struct rc_instruction* inst)
4663d32e589879806297258e36ea80aae5044293ca3Tom Stellard{
4673d32e589879806297258e36ea80aae5044293ca3Tom Stellard	unsigned int mask = inst->U.I.DstReg.WriteMask;
4683d32e589879806297258e36ea80aae5044293ca3Tom Stellard	unsigned int frac_index, add_index;
4693d32e589879806297258e36ea80aae5044293ca3Tom Stellard	struct rc_dst_register frac_dst, add_dst;
4703d32e589879806297258e36ea80aae5044293ca3Tom Stellard	struct rc_src_register frac_src, add_src;
4713d32e589879806297258e36ea80aae5044293ca3Tom Stellard
4723d32e589879806297258e36ea80aae5044293ca3Tom Stellard	/* add = src + .5 */
4733d32e589879806297258e36ea80aae5044293ca3Tom Stellard	add_index = rc_find_free_temporary(c);
4743d32e589879806297258e36ea80aae5044293ca3Tom Stellard	add_dst = dstregtmpmask(add_index, mask);
4753d32e589879806297258e36ea80aae5044293ca3Tom Stellard	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, add_dst, inst->U.I.SrcReg[0],
4763d32e589879806297258e36ea80aae5044293ca3Tom Stellard								builtin_half);
4773d32e589879806297258e36ea80aae5044293ca3Tom Stellard	add_src = srcreg(RC_FILE_TEMPORARY, add_dst.Index);
4783d32e589879806297258e36ea80aae5044293ca3Tom Stellard
4793d32e589879806297258e36ea80aae5044293ca3Tom Stellard
4803d32e589879806297258e36ea80aae5044293ca3Tom Stellard	/* frac = FRC(add) */
4813d32e589879806297258e36ea80aae5044293ca3Tom Stellard	frac_index = rc_find_free_temporary(c);
4823d32e589879806297258e36ea80aae5044293ca3Tom Stellard	frac_dst = dstregtmpmask(frac_index, mask);
4833d32e589879806297258e36ea80aae5044293ca3Tom Stellard	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, frac_dst, add_src);
4843d32e589879806297258e36ea80aae5044293ca3Tom Stellard	frac_src = srcreg(RC_FILE_TEMPORARY, frac_dst.Index);
4853d32e589879806297258e36ea80aae5044293ca3Tom Stellard
4863d32e589879806297258e36ea80aae5044293ca3Tom Stellard	/* dst = add - frac */
4873d32e589879806297258e36ea80aae5044293ca3Tom Stellard	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, inst->U.I.DstReg,
4883d32e589879806297258e36ea80aae5044293ca3Tom Stellard						add_src, negate(frac_src));
4893d32e589879806297258e36ea80aae5044293ca3Tom Stellard	rc_remove_instruction(inst);
4903d32e589879806297258e36ea80aae5044293ca3Tom Stellard}
4913d32e589879806297258e36ea80aae5044293ca3Tom Stellard
4921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_RSQ(struct radeon_compiler* c,
4931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
4941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[0] = absolute(inst->U.I.SrcReg[0]);
4961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SEQ(struct radeon_compiler* c,
4991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
5021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, inst->U.I.SrcReg[0], negate(inst->U.I.SrcReg[1]));
50473249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg,
5051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		negate(absolute(srcreg(RC_FILE_TEMPORARY, dst.Index))), builtin_zero, builtin_one);
5061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
5081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SFL(struct radeon_compiler* c,
5111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
51373249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit1(c, inst->Prev, RC_OPCODE_MOV, &inst->U.I, inst->U.I.DstReg, builtin_zero);
5141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
5151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SGE(struct radeon_compiler* c,
5181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
5211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, inst->U.I.SrcReg[0], negate(inst->U.I.SrcReg[1]));
52373249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg,
5241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, dst.Index), builtin_zero, builtin_one);
5251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
5271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SGT(struct radeon_compiler* c,
5301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
5331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, negate(inst->U.I.SrcReg[0]), inst->U.I.SrcReg[1]);
53573249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg,
5361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, dst.Index), builtin_one, builtin_zero);
5371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
5391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SLE(struct radeon_compiler* c,
5421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
5451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, negate(inst->U.I.SrcReg[0]), inst->U.I.SrcReg[1]);
54773249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg,
5481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, dst.Index), builtin_zero, builtin_one);
5491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
5511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SLT(struct radeon_compiler* c,
5541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
5571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, inst->U.I.SrcReg[0], negate(inst->U.I.SrcReg[1]));
55973249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg,
5601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, dst.Index), builtin_one, builtin_zero);
5611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
5631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SNE(struct radeon_compiler* c,
5661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
5691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, inst->U.I.SrcReg[0], negate(inst->U.I.SrcReg[1]));
57173249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg,
5721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		negate(absolute(srcreg(RC_FILE_TEMPORARY, dst.Index))), builtin_one, builtin_zero);
5731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
5751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SSG(struct radeon_compiler* c,
5781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
5791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* result = sign(x)
5811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *
5821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *   CMP tmp0, -x, 1, 0
5831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *   CMP tmp1, x, 1, 0
5841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *   ADD result, tmp0, -tmp1;
5851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 */
5861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst0;
5871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned tmp1;
5881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* 0 < x */
5901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	dst0 = try_to_reuse_dst(c, inst);
5911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_CMP, 0,
5921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      dst0,
5931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      negate(inst->U.I.SrcReg[0]),
5941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      builtin_one,
5951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      builtin_zero);
5961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x < 0 */
5981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	tmp1 = rc_find_free_temporary(c);
5991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_CMP, 0,
6001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      dstregtmpmask(tmp1, inst->U.I.DstReg.WriteMask),
6011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[0],
6021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      builtin_one,
6031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      builtin_zero);
6041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* Either both are zero, or one of them is one and the other is zero. */
6061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* result = tmp0 - tmp1 */
6071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
6081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.DstReg,
6091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      srcreg(RC_FILE_TEMPORARY, dst0.Index),
6101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      negate(srcreg(RC_FILE_TEMPORARY, tmp1)));
6111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
6131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SUB(struct radeon_compiler* c,
6161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
6171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.Opcode = RC_OPCODE_ADD;
6191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[1] = negate(inst->U.I.SrcReg[1]);
6201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_SWZ(struct radeon_compiler* c,
6231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
6241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.Opcode = RC_OPCODE_MOV;
6261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_XPD(struct radeon_compiler* c,
6291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
6301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
6321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MUL, 0, dst,
6341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(inst->U.I.SrcReg[0], RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_W),
6351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(inst->U.I.SrcReg[1], RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_W));
63673249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit3(c, inst->Prev, RC_OPCODE_MAD, &inst->U.I, inst->U.I.DstReg,
6371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(inst->U.I.SrcReg[0], RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_W),
6381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle(inst->U.I.SrcReg[1], RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_W),
6391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		negate(srcreg(RC_FILE_TEMPORARY, dst.Index)));
6401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
6421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
6461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Can be used as a transformation for @ref radeonClauseLocalTransform,
6471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * no userData necessary.
6481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
6491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Eliminates the following ALU instructions:
6501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  ABS, CEIL, DPH, DST, FLR, LIT, LRP, POW, SEQ, SFL, SGE, SGT, SLE, SLT, SNE, SUB, SWZ, XPD
6511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * using:
6521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  MOV, ADD, MUL, MAD, FRC, DP3, LG2, EX2, CMP
6531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
6541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Transforms RSQ to Radeon's native RSQ by explicitly setting
6551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * absolute value.
6561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
6571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @note should be applicable to R300 and R500 fragment programs.
6581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
6591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákint radeonTransformALU(
6601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c,
6611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst,
6621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void* unused)
6631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	switch(inst->U.I.Opcode) {
6651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_ABS: transform_ABS(c, inst); return 1;
6661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_CEIL: transform_CEIL(c, inst); return 1;
6671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_CLAMP: transform_CLAMP(c, inst); return 1;
6681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_DP2: transform_DP2(c, inst); return 1;
6691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_DPH: transform_DPH(c, inst); return 1;
6701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_DST: transform_DST(c, inst); return 1;
6711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_FLR: transform_FLR(c, inst); return 1;
6721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_LIT: transform_LIT(c, inst); return 1;
6731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_LRP: transform_LRP(c, inst); return 1;
6741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_POW: transform_POW(c, inst); return 1;
6753d32e589879806297258e36ea80aae5044293ca3Tom Stellard	case RC_OPCODE_ROUND: transform_ROUND(c, inst); return 1;
6761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_RSQ: transform_RSQ(c, inst); return 1;
6771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SEQ: transform_SEQ(c, inst); return 1;
6781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SFL: transform_SFL(c, inst); return 1;
6791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SGE: transform_SGE(c, inst); return 1;
6801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SGT: transform_SGT(c, inst); return 1;
6811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SLE: transform_SLE(c, inst); return 1;
6821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SLT: transform_SLT(c, inst); return 1;
6831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SNE: transform_SNE(c, inst); return 1;
6841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SSG: transform_SSG(c, inst); return 1;
6851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SUB: transform_SUB(c, inst); return 1;
6861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SWZ: transform_SWZ(c, inst); return 1;
6877f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	case RC_OPCODE_TRUNC: transform_TRUNC(c, inst); return 1;
6881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_XPD: transform_XPD(c, inst); return 1;
6891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	default:
6901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
6911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
6921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_ABS(struct radeon_compiler* c,
6961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
6971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* Note: r500 can take absolute values, but r300 cannot. */
6991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.Opcode = RC_OPCODE_MAX;
7001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[1] = inst->U.I.SrcReg[0];
7011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[1].Negate ^= RC_MASK_XYZW;
7021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
7031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_CMP(struct radeon_compiler* c,
7051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
7061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
7071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* There is no decent CMP available, so let's rig one up.
7081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * CMP is defined as dst = src0 < 0.0 ? src1 : src2
7091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * The following sequence consumes zero to two temps and two extra slots
7101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * (the second temp and the second slot is consumed by transform_LRP),
7111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * but should be equivalent:
7121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *
7131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * SLT tmp0, src0, 0.0
7141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * LRP dst, tmp0, src1, src2
7151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *
7161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * Yes, I know, I'm a mad scientist. ~ C. & M. */
7171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
7181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* SLT tmp0, src0, 0.0 */
7201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
7211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dst,
7221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[0], builtin_zero);
7231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* LRP dst, tmp0, src1, src2 */
7251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	transform_LRP(c,
7261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit3(c, inst->Prev, RC_OPCODE_LRP, 0,
7271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		      inst->U.I.DstReg,
7281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		      srcreg(RC_FILE_TEMPORARY, dst.Index), inst->U.I.SrcReg[1],  inst->U.I.SrcReg[2]));
7291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
7311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
7321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_DP2(struct radeon_compiler* c,
7341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
7351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
7361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *next_inst = inst->Next;
7371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	transform_DP2(c, inst);
7381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	next_inst->Prev->U.I.Opcode = RC_OPCODE_DP4;
7391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
7401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_DP3(struct radeon_compiler* c,
7421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
7431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
7441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src0 = inst->U.I.SrcReg[0];
7451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register src1 = inst->U.I.SrcReg[1];
7461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Negate &= ~RC_MASK_W;
7471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Swizzle &= ~(7 << (3 * 3));
7481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src0.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
7491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src1.Negate &= ~RC_MASK_W;
7501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src1.Swizzle &= ~(7 << (3 * 3));
7511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	src1.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
75273249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard	emit2(c, inst->Prev, RC_OPCODE_DP4, &inst->U.I, inst->U.I.DstReg, src0, src1);
7531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
7541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
7551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_fix_LIT(struct radeon_compiler* c,
7571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
7581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
7591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
7601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned constant_swizzle;
7611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	int constant = rc_constants_add_immediate_scalar(&c->Program.Constants,
7621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							 0.0000000000000000001,
7631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							 &constant_swizzle);
7641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* MOV dst, src */
7661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	dst.WriteMask = RC_MASK_XYZW;
7671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_MOV, 0,
7681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dst,
7691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.SrcReg[0]);
7701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* MAX dst.y, src, 0.00...001 */
7721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MAX, 0,
7731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dstregtmpmask(dst.Index, RC_MASK_Y),
7741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, dst.Index),
7751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcregswz(RC_FILE_CONSTANT, constant, constant_swizzle));
7761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[0] = srcreg(RC_FILE_TEMPORARY, dst.Index);
7781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
7791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_SEQ(struct radeon_compiler *c,
7811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *inst)
7821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
7831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x = y  <==>  x >= y && y >= x */
7841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	int tmp = rc_find_free_temporary(c);
7851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x <= y */
7871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_SGE, 0,
7881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      dstregtmpmask(tmp, inst->U.I.DstReg.WriteMask),
7891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[0],
7901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[1]);
7911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* y <= x */
7931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_SGE, 0,
7941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.DstReg,
7951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[1],
7961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[0]);
7971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x && y  =  x * y */
7991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MUL, 0,
8001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.DstReg,
8011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      srcreg(RC_FILE_TEMPORARY, tmp),
8021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      srcreg(inst->U.I.DstReg.File, inst->U.I.DstReg.Index));
8031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
8051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
8061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_SNE(struct radeon_compiler *c,
8081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *inst)
8091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
8101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x != y  <==>  x < y || y < x */
8111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	int tmp = rc_find_free_temporary(c);
8121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x < y */
8141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
8151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      dstregtmpmask(tmp, inst->U.I.DstReg.WriteMask),
8161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[0],
8171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[1]);
8181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* y < x */
8201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
8211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.DstReg,
8221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[1],
8231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[0]);
8241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x || y  =  max(x, y) */
8261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MAX, 0,
8271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.DstReg,
8281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      srcreg(RC_FILE_TEMPORARY, tmp),
8291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      srcreg(inst->U.I.DstReg.File, inst->U.I.DstReg.Index));
8301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
8321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
8331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_SGT(struct radeon_compiler* c,
8351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
8361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
8371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x > y  <==>  -x < -y */
8381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.Opcode = RC_OPCODE_SLT;
8391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[0].Negate ^= RC_MASK_XYZW;
8401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[1].Negate ^= RC_MASK_XYZW;
8411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
8421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_SLE(struct radeon_compiler* c,
8441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
8451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
8461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x <= y  <==>  -x >= -y */
8471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.Opcode = RC_OPCODE_SGE;
8481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[0].Negate ^= RC_MASK_XYZW;
8491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[1].Negate ^= RC_MASK_XYZW;
8501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
8511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void transform_r300_vertex_SSG(struct radeon_compiler* c,
8531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst)
8541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
8551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* result = sign(x)
8561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *
8571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *   SLT tmp0, 0, x;
8581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *   SLT tmp1, x, 0;
8591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *   ADD result, tmp0, -tmp1;
8601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 */
8611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst0 = try_to_reuse_dst(c, inst);
8621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned tmp1;
8631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* 0 < x */
8651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	dst0 = try_to_reuse_dst(c, inst);
8661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
8671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      dst0,
8681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      builtin_zero,
8691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[0]);
8701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* x < 0 */
8721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	tmp1 = rc_find_free_temporary(c);
8731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
8741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      dstregtmpmask(tmp1, inst->U.I.DstReg.WriteMask),
8751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.SrcReg[0],
8761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      builtin_zero);
8771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* Either both are zero, or one of them is one and the other is zero. */
8791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* result = tmp0 - tmp1 */
8801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
8811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      inst->U.I.DstReg,
8821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      srcreg(RC_FILE_TEMPORARY, dst0.Index),
8831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	      negate(srcreg(RC_FILE_TEMPORARY, tmp1)));
8841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
8861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
8871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8887f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšákstatic void transform_vertex_TRUNC(struct radeon_compiler* c,
8897f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	struct rc_instruction* inst)
8907f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák{
8917f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	struct rc_instruction *next = inst->Next;
8927f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák
8937f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	/* next->Prev is removed after each transformation and replaced
8947f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	 * by a new instruction. */
8957f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	transform_TRUNC(c, next->Prev);
8967f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	transform_r300_vertex_CMP(c, next->Prev);
8977f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák}
8987f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák
8991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
9001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * For use with rc_local_transform, this transforms non-native ALU
9011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * instructions of the r300 up to r500 vertex engine.
9021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
9031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákint r300_transform_vertex_alu(
9041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c,
9051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst,
9061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void* unused)
9071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
9081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	switch(inst->U.I.Opcode) {
9091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_ABS: transform_r300_vertex_ABS(c, inst); return 1;
9101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_CEIL: transform_CEIL(c, inst); return 1;
9111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_CLAMP: transform_CLAMP(c, inst); return 1;
9121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_CMP: transform_r300_vertex_CMP(c, inst); return 1;
9131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_DP2: transform_r300_vertex_DP2(c, inst); return 1;
9141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_DP3: transform_r300_vertex_DP3(c, inst); return 1;
9151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_DPH: transform_DPH(c, inst); return 1;
9161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_FLR: transform_FLR(c, inst); return 1;
9171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_LIT: transform_r300_vertex_fix_LIT(c, inst); return 1;
9181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_LRP: transform_LRP(c, inst); return 1;
9191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SEQ:
9201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (!c->is_r500) {
9211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			transform_r300_vertex_SEQ(c, inst);
9221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			return 1;
9231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
9241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
9251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SFL: transform_SFL(c, inst); return 1;
9261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SGT: transform_r300_vertex_SGT(c, inst); return 1;
9271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SLE: transform_r300_vertex_SLE(c, inst); return 1;
9281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SNE:
9291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (!c->is_r500) {
9301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			transform_r300_vertex_SNE(c, inst);
9311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			return 1;
9321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
9331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
9341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SSG: transform_r300_vertex_SSG(c, inst); return 1;
9351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SUB: transform_SUB(c, inst); return 1;
9361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_SWZ: transform_SWZ(c, inst); return 1;
9377f0fcf17c342dcb788c2182b20973c48806ee498Marek Olšák	case RC_OPCODE_TRUNC: transform_vertex_TRUNC(c, inst); return 1;
9381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	case RC_OPCODE_XPD: transform_XPD(c, inst); return 1;
9391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	default:
9401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
9411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
9421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
9431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
9441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void sincos_constants(struct radeon_compiler* c, unsigned int *constants)
9451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
9461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	static const float SinCosConsts[2][4] = {
9471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		{
9481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			1.273239545,		/* 4/PI */
9491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			-0.405284735,		/* -4/(PI*PI) */
9501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			3.141592654,		/* PI */
9511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			0.2225			/* weight */
9521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		},
9531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		{
9541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			0.75,
9551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			0.5,
9561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			0.159154943,		/* 1/(2*PI) */
9571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			6.283185307		/* 2*PI */
9581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
9591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	};
9601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	int i;
9611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
9621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(i = 0; i < 2; ++i)
9631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		constants[i] = rc_constants_add_immediate_vec4(&c->Program.Constants, SinCosConsts[i]);
9641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
9651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
9661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
9671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Approximate sin(x), where x is clamped to (-pi/2, pi/2).
9681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
9691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MUL tmp.xy, src, { 4/PI, -4/(PI^2) }
9701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MAD tmp.x, tmp.y, |src|, tmp.x
9711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MAD tmp.y, tmp.x, |tmp.x|, -tmp.x
9721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MAD dest, tmp.y, weight, tmp.x
9731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
9741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void sin_approx(
9751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler* c, struct rc_instruction * inst,
9761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_dst_register dst, struct rc_src_register src, const unsigned int* constants)
9771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
9781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int tempreg = rc_find_free_temporary(c);
9791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
9801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MUL, 0, dstregtmpmask(tempreg, RC_MASK_XY),
9811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_xxxx(src),
9821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_CONSTANT, constants[0]));
9831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_X),
9841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_yyyy(srcreg(RC_FILE_TEMPORARY, tempreg)),
9851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		absolute(swizzle_xxxx(src)),
9861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)));
9871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_Y),
9881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)),
9891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		absolute(swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg))),
9901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		negate(swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg))));
9911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dst,
9921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_yyyy(srcreg(RC_FILE_TEMPORARY, tempreg)),
9931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[0])),
9941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)));
9951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
9961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
9971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
9981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Translate the trigonometric functions COS, SIN, and SCS
9991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * using only the basic instructions
10001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *  MOV, ADD, MUL, MAD, FRC
10011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
10021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákint r300_transform_trig_simple(struct radeon_compiler* c,
10031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst,
10041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void* unused)
10051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
10061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int constants[2];
10071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int tempreg;
10081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.Opcode != RC_OPCODE_COS &&
10101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	    inst->U.I.Opcode != RC_OPCODE_SIN &&
10111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	    inst->U.I.Opcode != RC_OPCODE_SCS)
10121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
10131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	tempreg = rc_find_free_temporary(c);
10151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	sincos_constants(c, constants);
10171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.Opcode == RC_OPCODE_COS) {
10191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		/* MAD tmp.x, src, 1/(2*PI), 0.75 */
10201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		/* FRC tmp.x, tmp.x */
10211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		/* MAD tmp.z, tmp.x, 2*PI, -PI */
10221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
10231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_xxxx(inst->U.I.SrcReg[0]),
10241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[1])),
10251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_xxxx(srcreg(RC_FILE_CONSTANT, constants[1])));
10261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(tempreg, RC_MASK_W),
10271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)));
10281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
10291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
10301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[1])),
10311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			negate(swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[0]))));
10321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		sin_approx(c, inst, inst->U.I.DstReg,
10341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
10351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			constants);
10361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else if (inst->U.I.Opcode == RC_OPCODE_SIN) {
10371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
10381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_xxxx(inst->U.I.SrcReg[0]),
10391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[1])),
10401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_yyyy(srcreg(RC_FILE_CONSTANT, constants[1])));
10411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(tempreg, RC_MASK_W),
10421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)));
10431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
10441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
10451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[1])),
10461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			negate(swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[0]))));
10471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		sin_approx(c, inst, inst->U.I.DstReg,
10491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
10501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			constants);
10511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else {
10521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_dst_register dst;
10531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_XY),
10551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_xxxx(inst->U.I.SrcReg[0]),
10561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[1])),
10571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle(srcreg(RC_FILE_CONSTANT, constants[1]), RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_W));
10581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(tempreg, RC_MASK_XY),
10591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			srcreg(RC_FILE_TEMPORARY, tempreg));
10601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_XY),
10611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			srcreg(RC_FILE_TEMPORARY, tempreg),
10621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[1])),
10631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			negate(swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[0]))));
10641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dst = inst->U.I.DstReg;
10661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dst.WriteMask = inst->U.I.DstReg.WriteMask & RC_MASK_X;
10681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		sin_approx(c, inst, dst,
10691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)),
10701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			constants);
10711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		dst.WriteMask = inst->U.I.DstReg.WriteMask & RC_MASK_Y;
10731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		sin_approx(c, inst, dst,
10741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			swizzle_yyyy(srcreg(RC_FILE_TEMPORARY, tempreg)),
10751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			constants);
10761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
10771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
10791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return 1;
10811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
10821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void r300_transform_SIN_COS_SCS(struct radeon_compiler *c,
10841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *inst,
10851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned srctmp)
10861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
10871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.Opcode == RC_OPCODE_COS) {
108873249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard		emit1(c, inst->Prev, RC_OPCODE_COS, &inst->U.I, inst->U.I.DstReg,
10891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
10901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else if (inst->U.I.Opcode == RC_OPCODE_SIN) {
109173249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard		emit1(c, inst->Prev, RC_OPCODE_SIN, &inst->U.I,
10921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->U.I.DstReg, srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
10931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else if (inst->U.I.Opcode == RC_OPCODE_SCS) {
10941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_dst_register moddst = inst->U.I.DstReg;
10951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
10961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->U.I.DstReg.WriteMask & RC_MASK_X) {
10971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			moddst.WriteMask = RC_MASK_X;
109873249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard			emit1(c, inst->Prev, RC_OPCODE_COS, &inst->U.I, moddst,
10991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
11001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
11011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->U.I.DstReg.WriteMask & RC_MASK_Y) {
11021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			moddst.WriteMask = RC_MASK_Y;
110373249239cf71e3595ee19f3c1a02b8b0f58994cdTom Stellard			emit1(c, inst->Prev, RC_OPCODE_SIN, &inst->U.I, moddst,
11041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
11051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
11061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
11071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_remove_instruction(inst);
11091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
11101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
11131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Transform the trigonometric functions COS, SIN, and SCS
11141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * to include pre-scaling by 1/(2*PI) and taking the fractional
11151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * part, so that the input to COS and SIN is always in the range [0,1).
11161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * SCS is replaced by one COS and one SIN instruction.
11171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
11181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @warning This transformation implicitly changes the semantics of SIN and COS!
11191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
11201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákint radeonTransformTrigScale(struct radeon_compiler* c,
11211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst,
11221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void* unused)
11231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
11241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	static const float RCP_2PI = 0.15915494309189535;
11251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int temp;
11261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int constant;
11271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int constant_swizzle;
11281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.Opcode != RC_OPCODE_COS &&
11301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	    inst->U.I.Opcode != RC_OPCODE_SIN &&
11311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	    inst->U.I.Opcode != RC_OPCODE_SCS)
11321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
11331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	temp = rc_find_free_temporary(c);
11351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	constant = rc_constants_add_immediate_scalar(&c->Program.Constants, RCP_2PI, &constant_swizzle);
11361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit2(c, inst->Prev, RC_OPCODE_MUL, 0, dstregtmpmask(temp, RC_MASK_W),
11381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_xxxx(inst->U.I.SrcReg[0]),
11391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcregswz(RC_FILE_CONSTANT, constant, constant_swizzle));
11401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(temp, RC_MASK_W),
11411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, temp));
11421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	r300_transform_SIN_COS_SCS(c, inst, temp);
11441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return 1;
11451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
11461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
11481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Transform the trigonometric functions COS, SIN, and SCS
11491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * so that the input to COS and SIN is always in the range [-PI, PI].
11501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * SCS is replaced by one COS and one SIN instruction.
11511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
11521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákint r300_transform_trig_scale_vertex(struct radeon_compiler *c,
11531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction *inst,
11541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void *unused)
11551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
11561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	static const float cons[4] = {0.15915494309189535, 0.5, 6.28318530717959, -3.14159265358979};
11571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int temp;
11581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int constant;
11591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.Opcode != RC_OPCODE_COS &&
11611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	    inst->U.I.Opcode != RC_OPCODE_SIN &&
11621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	    inst->U.I.Opcode != RC_OPCODE_SCS)
11631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
11641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* Repeat x in the range [-PI, PI]:
11661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *
11671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 *   repeat(x) = frac(x / 2PI + 0.5) * 2PI - PI
11681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 */
11691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	temp = rc_find_free_temporary(c);
11711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	constant = rc_constants_add_immediate_vec4(&c->Program.Constants, cons);
11721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(temp, RC_MASK_W),
11741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		swizzle_xxxx(inst->U.I.SrcReg[0]),
11751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcregswz(RC_FILE_CONSTANT, constant, RC_SWIZZLE_XXXX),
11761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcregswz(RC_FILE_CONSTANT, constant, RC_SWIZZLE_YYYY));
11771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(temp, RC_MASK_W),
11781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, temp));
11791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(temp, RC_MASK_W),
11801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcreg(RC_FILE_TEMPORARY, temp),
11811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcregswz(RC_FILE_CONSTANT, constant, RC_SWIZZLE_ZZZZ),
11821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		srcregswz(RC_FILE_CONSTANT, constant, RC_SWIZZLE_WWWW));
11831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	r300_transform_SIN_COS_SCS(c, inst, temp);
11851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return 1;
11861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
11871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
11891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Rewrite DDX/DDY instructions to properly work with r5xx shaders.
11901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The r5xx MDH/MDV instruction provides per-quad partial derivatives.
11911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * It takes the form A*B+C. A and C are set by setting src0. B should be -1.
11921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
11931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @warning This explicitly changes the form of DDX and DDY!
11941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
11951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
11961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákint radeonTransformDeriv(struct radeon_compiler* c,
11971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction* inst,
11981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void* unused)
11991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
12001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->U.I.Opcode != RC_OPCODE_DDX && inst->U.I.Opcode != RC_OPCODE_DDY)
12011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
12021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
12031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_1111;
12041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	inst->U.I.SrcReg[1].Negate = RC_MASK_XYZW;
12051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
12061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return 1;
12071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
12081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
12091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
1210342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * IF Temp[0].x -> IF Temp[0].x
1211342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ...          -> ...
1212342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * KILP         -> KIL -abs(Temp[0].x)
1213342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ...          -> ...
1214342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ENDIF        -> ENDIF
1215342cac71669662abad3435fd13ecf28d073874c3Tom Stellard *
1216342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * === OR ===
1217342cac71669662abad3435fd13ecf28d073874c3Tom Stellard *
12181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * IF Temp[0].x -\
12191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * KILP         - > KIL -abs(Temp[0].x)
12201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * ENDIF        -/
12211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
1222342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * === OR ===
1223342cac71669662abad3435fd13ecf28d073874c3Tom Stellard *
1224342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * IF Temp[0].x -> IF Temp[0].x
1225342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ...          -> ...
1226342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ELSE         -> ELSE
1227342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ...	        -> ...
1228342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * KILP	        -> KIL -abs(Temp[0].x)
1229342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ...          -> ...
1230342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * ENDIF        -> ENDIF
1231342cac71669662abad3435fd13ecf28d073874c3Tom Stellard *
1232342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * === OR ===
1233342cac71669662abad3435fd13ecf28d073874c3Tom Stellard *
1234342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * KILP         -> KIL -none.1111
1235342cac71669662abad3435fd13ecf28d073874c3Tom Stellard *
1236342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * This needs to be done in its own pass, because it might modify the
1237342cac71669662abad3435fd13ecf28d073874c3Tom Stellard * instructions before and after KILP.
12381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
12391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_transform_KILP(struct radeon_compiler * c, void *user)
12401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
12411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst;
12421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (inst = c->Program.Instructions.Next;
12431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst != &c->Program.Instructions; inst = inst->Next) {
1244342cac71669662abad3435fd13ecf28d073874c3Tom Stellard		struct rc_instruction * if_inst;
1245342cac71669662abad3435fd13ecf28d073874c3Tom Stellard		unsigned in_if = 0;
12461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
12471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->U.I.Opcode != RC_OPCODE_KILP)
12481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			continue;
12491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1250342cac71669662abad3435fd13ecf28d073874c3Tom Stellard		for (if_inst = inst->Prev; if_inst != &c->Program.Instructions;
1251342cac71669662abad3435fd13ecf28d073874c3Tom Stellard						if_inst = if_inst->Prev) {
1252342cac71669662abad3435fd13ecf28d073874c3Tom Stellard
1253342cac71669662abad3435fd13ecf28d073874c3Tom Stellard			if (if_inst->U.I.Opcode == RC_OPCODE_IF) {
1254342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				in_if = 1;
1255342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				break;
1256342cac71669662abad3435fd13ecf28d073874c3Tom Stellard			}
1257342cac71669662abad3435fd13ecf28d073874c3Tom Stellard		}
1258342cac71669662abad3435fd13ecf28d073874c3Tom Stellard
12591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->U.I.Opcode = RC_OPCODE_KIL;
12601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1261342cac71669662abad3435fd13ecf28d073874c3Tom Stellard		if (!in_if) {
12621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->U.I.SrcReg[0] = negate(builtin_one);
12631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		} else {
1264342cac71669662abad3435fd13ecf28d073874c3Tom Stellard			/* This should work even if the KILP is inside the ELSE
1265342cac71669662abad3435fd13ecf28d073874c3Tom Stellard			 * block, because -0.0 is considered negative. */
12661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->U.I.SrcReg[0] =
1267342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				negate(absolute(if_inst->U.I.SrcReg[0]));
1268342cac71669662abad3435fd13ecf28d073874c3Tom Stellard
1269342cac71669662abad3435fd13ecf28d073874c3Tom Stellard			if (inst->Prev->U.I.Opcode != RC_OPCODE_IF
1270342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				&& inst->Next->U.I.Opcode != RC_OPCODE_ENDIF) {
1271342cac71669662abad3435fd13ecf28d073874c3Tom Stellard
1272342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				/* Optimize the special case:
1273342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				 * IF Temp[0].x
1274342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				 * KILP
1275342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				 * ENDIF
1276342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				 */
1277342cac71669662abad3435fd13ecf28d073874c3Tom Stellard
1278342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				/* Remove IF */
1279342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				rc_remove_instruction(inst->Prev);
1280342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				/* Remove ENDIF */
1281342cac71669662abad3435fd13ecf28d073874c3Tom Stellard				rc_remove_instruction(inst->Next);
1282342cac71669662abad3435fd13ecf28d073874c3Tom Stellard			}
12831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
12841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
12851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1286