151125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek/*
24241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * Copyright (C) 2005 Ben Skeggs.
34241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek *
44241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * All Rights Reserved.
54241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek *
64241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * Permission is hereby granted, free of charge, to any person obtaining
74241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * a copy of this software and associated documentation files (the
84241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * "Software"), to deal in the Software without restriction, including
94241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * without limitation the rights to use, copy, modify, merge, publish,
1051125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek * distribute, sublicense, and/or sell copies of the Software, and to
1151125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek * permit persons to whom the Software is furnished to do so, subject to
12b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin * the following conditions:
13b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin *
14b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin * The above copyright notice and this permission notice (including the
15b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin * next paragraph) shall be included in all copies or substantial
164241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * portions of the Software.
174241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek *
184241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
195a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
205a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
214241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
224a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
231309f9a3b225ea846e5822691c39a77423125505Ted Kremenek * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2463bbe5312cd89ce0ceb684bff68c5baef636e93cTed Kremenek * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
254241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek *
264241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek */
27f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek
284241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek/**
29ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek * \file
304a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek *
314a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek * Emit the r300_fragment_program_code that can be understood by the hardware.
3263bbe5312cd89ce0ceb684bff68c5baef636e93cTed Kremenek * Input is a pre-transformed radeon_program.
335fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek *
3418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek * \author Ben Skeggs <darktama@iinet.net.au>
354241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek *
364241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek * \author Jerome Glisse <j.glisse@gmail.com>
374a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek */
3811062b118476368fa5b294954713e5df97d8599fTed Kremenek
395a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis#include "r300_fragprog.h"
409ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek
415a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis#include "../r300_reg.h"
425fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek
4311062b118476368fa5b294954713e5df97d8599fTed Kremenek#include "radeon_program_pair.h"
44cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek#include "r300_fragprog_swizzle.h"
45cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
46cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
47cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekstruct r300_emit_state {
48cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek	struct r300_fragment_program_compiler * compiler;
491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
50bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu	unsigned current_node : 2;
51bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu	unsigned node_first_tex : 8;
52bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu	unsigned node_first_alu : 8;
53c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	uint32_t node_flags;
5438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu};
55d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis
56a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks#define PROG_CODE \
57d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis	struct r300_fragment_program_compiler *c = emit->compiler; \
58d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis	struct r300_fragment_program_code *code = &c->code->code.r300
59d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis
60d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis#define error(fmt, args...) do {			\
61e36de1fe51c39d9161915dd3dbef880954af6476Ted Kremenek		rc_error(&c->Base, "%s::%s(): " fmt "\n",	\
621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			__FILE__, __FUNCTION__, ##args);	\
634c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek	} while(0)
64b38911f16b4943548db6a3695fc6ae23070b25d2Ted Kremenek
654c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenekstatic unsigned int get_msbs_alu(unsigned int bits)
661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump{
67ee98546b0d5f3439c4a590b0d7d1545af794a0ecTed Kremenek	return (bits >> 6) & 0x7;
68596f0a1e54f610926e8bfded9efa1c639f824dedTed Kremenek}
69ee98546b0d5f3439c4a590b0d7d1545af794a0ecTed Kremenek
701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/**
719c378f705405d37f49795d5e915989de774fe11fTed Kremenek * @param lsbs The number of least significant bits
72ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek */
73b38911f16b4943548db6a3695fc6ae23070b25d2Ted Kremenekstatic unsigned int get_msbs_tex(unsigned int bits, unsigned int lsbs)
74ee98546b0d5f3439c4a590b0d7d1545af794a0ecTed Kremenek{
75ee98546b0d5f3439c4a590b0d7d1545af794a0ecTed Kremenek	return (bits >> lsbs) & 0x15;
76c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu}
77c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
78ee98546b0d5f3439c4a590b0d7d1545af794a0ecTed Kremenek#define R400_EXT_GET_MSBS(x, lsbs, mask) (((x) >> lsbs) & mask)
79d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
804c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek/**
814c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek * Mark a temporary register as used.
821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump */
835fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenekstatic void use_temporary(struct r300_fragment_program_code *code, unsigned int index)
841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump{
855fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek	if (index > code->pixsize)
861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		code->pixsize = index;
875d5480380d7b7c3590a0283ddf239220e514e576Ted Kremenek}
881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
895fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenekstatic unsigned int use_source(struct r300_fragment_program_code* code, struct rc_pair_instruction_source src)
901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump{
919c378f705405d37f49795d5e915989de774fe11fTed Kremenek	if (!src.Used)
921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		return 0;
93d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
94d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek	if (src.File == RC_FILE_CONSTANT) {
95b38911f16b4943548db6a3695fc6ae23070b25d2Ted Kremenek		return src.Index | (1 << 5);
965fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek	} else if (src.File == RC_FILE_TEMPORARY || src.File == RC_FILE_INPUT) {
97ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek		use_temporary(code, src.Index);
98f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek		return src.Index & 0x1f;
991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	}
100b38911f16b4943548db6a3695fc6ae23070b25d2Ted Kremenek
101b38911f16b4943548db6a3695fc6ae23070b25d2Ted Kremenek	return 0;
102f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek}
1031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1054a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenekstatic unsigned int translate_rgb_opcode(struct r300_fragment_program_compiler * c, rc_opcode opcode)
1064a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek{
1074a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	switch(opcode) {
1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	case RC_OPCODE_CMP: return R300_ALU_OUTC_CMP;
1094323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek	case RC_OPCODE_CND: return R300_ALU_OUTC_CND;
11018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek	case RC_OPCODE_DP3: return R300_ALU_OUTC_DP3;
1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	case RC_OPCODE_DP4: return R300_ALU_OUTC_DP4;
1124a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	case RC_OPCODE_FRC: return R300_ALU_OUTC_FRC;
1134c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek	default:
1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		error("translate_rgb_opcode: Unknown opcode %s", rc_get_opcode_info(opcode)->Name);
1154a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		/* fall through */
1164c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek	case RC_OPCODE_NOP:
117c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		/* fall through */
1184a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	case RC_OPCODE_MAD: return R300_ALU_OUTC_MAD;
119c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	case RC_OPCODE_MAX: return R300_ALU_OUTC_MAX;
12018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek	case RC_OPCODE_MIN: return R300_ALU_OUTC_MIN;
121e3115e257163321ecde429aeae75f1702f099d4cTed Kremenek	case RC_OPCODE_REPL_ALPHA: return R300_ALU_OUTC_REPL_ALPHA;
12218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek	}
123e40b69de464bc695afcaf7ef9602ad727d77b981Ted Kremenek}
124e40b69de464bc695afcaf7ef9602ad727d77b981Ted Kremenek
125e40b69de464bc695afcaf7ef9602ad727d77b981Ted Kremenekstatic unsigned int translate_alpha_opcode(struct r300_fragment_program_compiler * c, rc_opcode opcode)
12618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek{
127e3115e257163321ecde429aeae75f1702f099d4cTed Kremenek	switch(opcode) {
128c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	case RC_OPCODE_CMP: return R300_ALU_OUTA_CMP;
1294a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	case RC_OPCODE_CND: return R300_ALU_OUTA_CND;
1300f9063c116b7c3b05d8042b5976463c2dae04861Ted Kremenek	case RC_OPCODE_DP3: return R300_ALU_OUTA_DP4;
131c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	case RC_OPCODE_DP4: return R300_ALU_OUTA_DP4;
1321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	case RC_OPCODE_EX2: return R300_ALU_OUTA_EX2;
1331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	case RC_OPCODE_FRC: return R300_ALU_OUTA_FRC;
13425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu	case RC_OPCODE_LG2: return R300_ALU_OUTA_LG2;
13525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu	default:
1365032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu		error("translate_rgb_opcode: Unknown opcode %s", rc_get_opcode_info(opcode)->Name);
1375032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu		/* fall through */
1385032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu	case RC_OPCODE_NOP:
1395032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu		/* fall through */
140b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu	case RC_OPCODE_MAD: return R300_ALU_OUTA_MAD;
141b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu	case RC_OPCODE_MAX: return R300_ALU_OUTA_MAX;
142a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek	case RC_OPCODE_MIN: return R300_ALU_OUTA_MIN;
143a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek	case RC_OPCODE_RCP: return R300_ALU_OUTA_RCP;
144a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek	case RC_OPCODE_RSQ: return R300_ALU_OUTA_RSQ;
145c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	}
146c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu}
14718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek
148b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu/**
14952c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek * Emit one paired ALU instruction.
15052c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek */
151c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* inst)
1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump{
15318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek	int ip;
1545fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek	int j;
1555fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek	PROG_CODE;
1565fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek
157c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	if (code->alu.length >= c->Base.max_alu_insts) {
158c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		error("Too many ALU instructions");
159c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		return 0;
160c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	}
161c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	ip = code->alu.length++;
163c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1649c378f705405d37f49795d5e915989de774fe11fTed Kremenek	code->alu.inst[ip].rgb_inst = translate_rgb_opcode(c, inst->RGB.Opcode);
165c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	code->alu.inst[ip].alpha_inst = translate_alpha_opcode(c, inst->Alpha.Opcode);
1664a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
1674a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	for(j = 0; j < 3; ++j) {
1684a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		/* Set the RGB address */
1690e8a3c743b9b3e3039e329a1736122d3b5b5fed9Ted Kremenek		unsigned int src = use_source(code, inst->RGB.Src[j]);
1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		unsigned int arg;
171ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek		if (inst->RGB.Src[j].Index >= R300_PFS_NUM_TEMP_REGS)
1721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_RGB_MSB_BIT(j);
1734a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
1749c378f705405d37f49795d5e915989de774fe11fTed Kremenek		code->alu.inst[ip].rgb_addr |= src << (6*j);
17552c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek
17652c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek		/* Set the Alpha address */
1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		src = use_source(code, inst->Alpha.Src[j]);
1789c378f705405d37f49795d5e915989de774fe11fTed Kremenek		if (inst->Alpha.Src[j].Index >= R300_PFS_NUM_TEMP_REGS)
17952c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek			code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_A_MSB_BIT(j);
18052c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek
1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		code->alu.inst[ip].alpha_addr |= src << (6*j);
1824a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
1834a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		arg = r300FPTranslateRGBSwizzle(inst->RGB.Arg[j].Source, inst->RGB.Arg[j].Swizzle);
1843148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek		arg |= inst->RGB.Arg[j].Abs << 6;
1854a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		arg |= inst->RGB.Arg[j].Negate << 5;
1863148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek		code->alu.inst[ip].rgb_inst |= arg << (7*j);
1874a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
188c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		arg = r300FPTranslateAlphaSwizzle(inst->Alpha.Arg[j].Source, inst->Alpha.Arg[j].Swizzle);
189c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		arg |= inst->Alpha.Arg[j].Abs << 6;
1904a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		arg |= inst->Alpha.Arg[j].Negate << 5;
1914a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		code->alu.inst[ip].alpha_inst |= arg << (7*j);
1924a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	}
1931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1944a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	/* Presubtract */
1954a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	if (inst->RGB.Src[RC_PAIR_PRESUB_SRC].Used) {
1964a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		switch(inst->RGB.Src[RC_PAIR_PRESUB_SRC].Index) {
1974a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		case RC_PRESUB_BIAS:
198c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			code->alu.inst[ip].rgb_inst |=
199c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu						R300_ALU_SRCP_1_MINUS_2_SRC0;
2004a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			break;
2014a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		case RC_PRESUB_ADD:
2024a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			code->alu.inst[ip].rgb_inst |=
2034a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek						R300_ALU_SRCP_SRC1_PLUS_SRC0;
2044a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			break;
2054a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		case RC_PRESUB_SUB:
2064a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			code->alu.inst[ip].rgb_inst |=
207c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu						R300_ALU_SRCP_SRC1_MINUS_SRC0;
208c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			break;
2091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		case RC_PRESUB_INV:
210c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			code->alu.inst[ip].rgb_inst |=
2111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump						R300_ALU_SRCP_1_MINUS_SRC0;
212c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			break;
213c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		default:
214c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			break;
2159c378f705405d37f49795d5e915989de774fe11fTed Kremenek		}
216c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	}
2171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
218c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	if (inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Used) {
219d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek		switch(inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Index) {
220d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek		case RC_PRESUB_BIAS:
221d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek			code->alu.inst[ip].alpha_inst |=
222d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek						R300_ALU_SRCP_1_MINUS_2_SRC0;
223c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			break;
224c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		case RC_PRESUB_ADD:
22538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			code->alu.inst[ip].alpha_inst |=
22638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu						R300_ALU_SRCP_SRC1_PLUS_SRC0;
22738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			break;
2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		case RC_PRESUB_SUB:
229c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			code->alu.inst[ip].alpha_inst |=
23038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu						R300_ALU_SRCP_SRC1_MINUS_SRC0;
2319c378f705405d37f49795d5e915989de774fe11fTed Kremenek			break;
2321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		case RC_PRESUB_INV:
2337177dee8aee4b432911c91f1b788963bec0cac9fDaniel Dunbar			code->alu.inst[ip].alpha_inst |=
23438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu						R300_ALU_SRCP_1_MINUS_SRC0;
2354a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			break;
2364a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		default:
23738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			break;
2384241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek		}
239d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis	}
240e96de2dfde487211fb52f9139cdcae64d051a406Zhongxing Xu
2414241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	if (inst->RGB.Saturate)
242686775deca8b8685eb90801495880e3abdd844c2Chris Lattner		code->alu.inst[ip].rgb_inst |= R300_ALU_OUTC_CLAMP;
243686775deca8b8685eb90801495880e3abdd844c2Chris Lattner	if (inst->Alpha.Saturate)
2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		code->alu.inst[ip].alpha_inst |= R300_ALU_OUTA_CLAMP;
2454241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
2464241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	if (inst->RGB.WriteMask) {
2474241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek		use_temporary(code, inst->RGB.DestIndex);
2484241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek		if (inst->RGB.DestIndex >= R300_PFS_NUM_TEMP_REGS)
2494241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek			code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_RGB_MSB_BIT;
2504241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek		code->alu.inst[ip].rgb_addr |=
2514241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek			((inst->RGB.DestIndex & 0x1f) << R300_ALU_DSTC_SHIFT) |
2524241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek			(inst->RGB.WriteMask << R300_ALU_DSTC_REG_MASK_SHIFT);
2534241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	}
25438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	if (inst->RGB.OutputWriteMask) {
25538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		code->alu.inst[ip].rgb_addr |=
25638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu            (inst->RGB.OutputWriteMask << R300_ALU_DSTC_OUTPUT_MASK_SHIFT) |
25738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu            R300_RGB_TARGET(inst->RGB.Target);
2585fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek		emit->node_flags |= R300_RGBA_OUT;
2595fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek	}
2605fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek
2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	if (inst->Alpha.WriteMask) {
26239b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek		use_temporary(code, inst->Alpha.DestIndex);
26339b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek		if (inst->Alpha.DestIndex >= R300_PFS_NUM_TEMP_REGS)
264d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek			code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_A_MSB_BIT;
265d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek		code->alu.inst[ip].alpha_addr |=
266d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek			((inst->Alpha.DestIndex & 0x1f) << R300_ALU_DSTA_SHIFT) |
267d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek			R300_ALU_DSTA_REG;
268d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek	}
269d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek	if (inst->Alpha.OutputWriteMask) {
270d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek		code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_OUTPUT |
271d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek            R300_ALPHA_TARGET(inst->Alpha.Target);
272d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek		emit->node_flags |= R300_RGBA_OUT;
2734241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	}
27438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	if (inst->Alpha.DepthWriteMask) {
27538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_DEPTH;
27638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		emit->node_flags |= R300_W_OUT;
27738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		c->code->writes_depth = 1;
27838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	}
27938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	if (inst->Nop)
28018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek		code->alu.inst[ip].rgb_inst |= R300_ALU_INSERT_NOP;
28138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	/* Handle Output Modifier
28338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	 * According to the r300 docs, there is no RC_OMOD_DISABLE for r300 */
284c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu	if (inst->RGB.Omod) {
28538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		if (inst->RGB.Omod == RC_OMOD_DISABLE) {
2864a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			rc_error(&c->Base, "RC_OMOD_DISABLE not supported");
2874241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek		}
2889c378f705405d37f49795d5e915989de774fe11fTed Kremenek		code->alu.inst[ip].rgb_inst |=
289ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek			(inst->RGB.Omod << R300_ALU_OUTC_MOD_SHIFT);
290ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek	}
291ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek	if (inst->Alpha.Omod) {
2924241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek		if (inst->Alpha.Omod == RC_OMOD_DISABLE) {
2934241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek			rc_error(&c->Base, "RC_OMOD_DISABLE not supported");
2949c378f705405d37f49795d5e915989de774fe11fTed Kremenek		}
295ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek		code->alu.inst[ip].alpha_inst |=
296ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek			(inst->Alpha.Omod << R300_ALU_OUTC_MOD_SHIFT);
297ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek	}
29838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	return 1;
299824c547dc5d4451b9dbacc56621592fa010878f4Ted Kremenek}
300824c547dc5d4451b9dbacc56621592fa010878f4Ted Kremenek
301824c547dc5d4451b9dbacc56621592fa010878f4Ted Kremenek
3024a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek/**
303d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek * Finish the current node without advancing to the next one.
304d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek */
3054241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenekstatic int finish_node(struct r300_emit_state * emit)
3064a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek{
3071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	struct r300_fragment_program_compiler * c = emit->compiler;
30839b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek	struct r300_fragment_program_code *code = &emit->compiler->code->code.r300;
30939b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek	unsigned alu_offset;
310c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	unsigned alu_end;
3114241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	unsigned tex_offset;
31238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	unsigned tex_end;
31338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
3147ebde953bb050caa69f791fc1de449d435c6a36fTed Kremenek	unsigned int alu_offset_msbs, alu_end_msbs;
31538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
3167ebde953bb050caa69f791fc1de449d435c6a36fTed Kremenek	if (code->alu.length == emit->node_first_alu) {
31738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		/* Generate a single NOP for this node */
31838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		struct rc_pair_instruction inst;
31938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		memset(&inst, 0, sizeof(inst));
3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		if (!emit_alu(emit, &inst))
32138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			return 0;
3227ebde953bb050caa69f791fc1de449d435c6a36fTed Kremenek	}
32338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
3241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	alu_offset = emit->node_first_alu;
32538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	alu_end = code->alu.length - alu_offset - 1;
3261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	tex_offset = emit->node_first_tex;
32738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	tex_end = code->tex.length - tex_offset - 1;
3281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	if (code->tex.length == emit->node_first_tex) {
3301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		if (emit->current_node > 0) {
33138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			error("Node %i has no TEX instructions", emit->current_node);
3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			return 0;
33338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		}
3341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		tex_end = 0;
3364241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	} else {
33738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu		if (emit->current_node == 0)
3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			code->config |= R300_PFS_CNTL_FIRST_NODE_HAS_TEX;
33938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	}
3401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	/* Write the config register.
3421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	 * Note: The order in which the words for each node are written
34338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	 * is not correct here and needs to be fixed up once we're entirely
34438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	 * done
3455fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek	 *
3465fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek	 * Also note that the register specification from AMD is slightly
34738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	 * incorrect in its description of this register. */
34838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu	code->code_addr[emit->current_node]  =
34938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			((alu_offset << R300_ALU_START_SHIFT)
350c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu				& R300_ALU_START_MASK)
351fe9e543a2a363df7fcaa899367d3b2580b63b27cTed Kremenek			| ((alu_end << R300_ALU_SIZE_SHIFT)
35238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu				& R300_ALU_SIZE_MASK)
353cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek			| ((tex_offset << R300_TEX_START_SHIFT)
35438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu				& R300_TEX_START_MASK)
35538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			| ((tex_end << R300_TEX_SIZE_SHIFT)
35638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu				& R300_TEX_SIZE_MASK)
35738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu			| emit->node_flags
358d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek			| (get_msbs_tex(tex_offset, 5)
359d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek				<< R400_TEX_START_MSB_SHIFT)
360d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek			| (get_msbs_tex(tex_end, 5)
361d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek				<< R400_TEX_SIZE_MSB_SHIFT)
362d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek			;
363d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
364d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek	/* Write r400 extended instruction fields.  These will be ignored on
365d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek	 * r300 cards.  */
3664241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	alu_offset_msbs = get_msbs_alu(alu_offset);
367cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek	alu_end_msbs = get_msbs_alu(alu_end);
368f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek	switch(emit->current_node) {
369c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	case 0:
370f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek		code->r400_code_offset_ext |=
3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			alu_offset_msbs << R400_ALU_START3_MSB_SHIFT
372f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek			| alu_end_msbs << R400_ALU_SIZE3_MSB_SHIFT;
3739c378f705405d37f49795d5e915989de774fe11fTed Kremenek		break;
374c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	case 1:
375f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek		code->r400_code_offset_ext |=
376f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek			alu_offset_msbs << R400_ALU_START2_MSB_SHIFT
3771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			| alu_end_msbs << R400_ALU_SIZE2_MSB_SHIFT;
378f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek		break;
3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	case 2:
3809c378f705405d37f49795d5e915989de774fe11fTed Kremenek		code->r400_code_offset_ext |=
381c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu			alu_offset_msbs << R400_ALU_START1_MSB_SHIFT
382f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek			| alu_end_msbs << R400_ALU_SIZE1_MSB_SHIFT;
3831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		break;
3849c378f705405d37f49795d5e915989de774fe11fTed Kremenek	case 3:
385cc2c6eb04d882466c7cfbb544c251d7e0ba0f356Ted Kremenek		code->r400_code_offset_ext |=
386cc2c6eb04d882466c7cfbb544c251d7e0ba0f356Ted Kremenek			alu_offset_msbs << R400_ALU_START0_MSB_SHIFT
387cc2c6eb04d882466c7cfbb544c251d7e0ba0f356Ted Kremenek			| alu_end_msbs << R400_ALU_SIZE0_MSB_SHIFT;
3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		break;
389c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	}
390c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	return 1;
391f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek}
392fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek
393fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek
394fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek/**
395fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek * Begin a block of texture instructions.
396fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek * Create the necessary indirection.
397fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek */
398fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenekstatic int begin_tex(struct r300_emit_state * emit)
399fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek{
400fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek	PROG_CODE;
401fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek
4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	if (code->alu.length == emit->node_first_alu &&
403f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek	    code->tex.length == emit->node_first_tex) {
404f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek		return 1;
4051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	}
406f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek
407f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek	if (emit->current_node == 3) {
4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		error("Too many texture indirections");
4091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		return 0;
4105a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis	}
4115a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis
4124241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek	if (!finish_node(emit))
4134241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek		return 0;
4144a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
4154a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	emit->current_node++;
4164a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	emit->node_first_tex = code->tex.length;
4179ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek	emit->node_first_alu = code->alu.length;
4189ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek	emit->node_flags = 0;
419c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu	return 1;
4204a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek}
4211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4224a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
4234a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenekstatic int emit_tex(struct r300_emit_state * emit, struct rc_instruction * inst)
4244a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek{
4251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	unsigned int unit;
4264a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	unsigned int dest;
4274a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	unsigned int opcode;
4284a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	PROG_CODE;
4291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4304a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	if (code->tex.length >= emit->compiler->Base.max_tex_insts) {
4314a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		error("Too many TEX instructions");
4324a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		return 0;
4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	}
4344a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
4354a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	unit = inst->U.I.TexSrcUnit;
4364a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	dest = inst->U.I.DstReg.Index;
4371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4384a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	switch(inst->U.I.Opcode) {
4394a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	case RC_OPCODE_KIL: opcode = R300_TEX_OP_KIL; break;
4404a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	case RC_OPCODE_TEX: opcode = R300_TEX_OP_LD; break;
4414a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	case RC_OPCODE_TXB: opcode = R300_TEX_OP_TXB; break;
4421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	case RC_OPCODE_TXP: opcode = R300_TEX_OP_TXP; break;
4439ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek	default:
4449ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek		error("Unknown texture opcode %s", rc_get_opcode_info(inst->U.I.Opcode)->Name);
445c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu		return 0;
4464a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	}
4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4484a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	if (inst->U.I.Opcode == RC_OPCODE_KIL) {
4494a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		unit = 0;
4504a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		dest = 0;
4511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	} else {
4524a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		use_temporary(code, dest);
4534a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	}
4544a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
4551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	use_temporary(code, inst->U.I.SrcReg[0].Index);
4564a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
4574a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	code->tex.inst[code->tex.length++] =
4584a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		((inst->U.I.SrcReg[0].Index << R300_SRC_ADDR_SHIFT)
4591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump			& R300_SRC_ADDR_MASK)
4604a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		| ((dest << R300_DST_ADDR_SHIFT)
4614a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			& R300_DST_ADDR_MASK)
4624a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		| (unit << R300_TEX_ID_SHIFT)
4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		| (opcode << R300_TEX_INST_SHIFT)
4644a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		| (inst->U.I.SrcReg[0].Index >= R300_PFS_NUM_TEMP_REGS ?
4654a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			R400_SRC_ADDR_EXT_BIT : 0)
4664a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek		| (dest >= R300_PFS_NUM_TEMP_REGS ?
4674a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek			R400_DST_ADDR_EXT_BIT : 0)
4681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump		;
4694a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek	return 1;
4704a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek}
4714241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
472
473/**
474 * Final compilation step: Turn the intermediate radeon_program into
475 * machine-readable instructions.
476 */
477void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user)
478{
479	struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c;
480	struct r300_emit_state emit;
481	struct r300_fragment_program_code *code = &compiler->code->code.r300;
482	unsigned int tex_end;
483
484	memset(&emit, 0, sizeof(emit));
485	emit.compiler = compiler;
486
487	memset(code, 0, sizeof(struct r300_fragment_program_code));
488
489	for(struct rc_instruction * inst = compiler->Base.Program.Instructions.Next;
490	    inst != &compiler->Base.Program.Instructions && !compiler->Base.Error;
491	    inst = inst->Next) {
492		if (inst->Type == RC_INSTRUCTION_NORMAL) {
493			if (inst->U.I.Opcode == RC_OPCODE_BEGIN_TEX) {
494				begin_tex(&emit);
495				continue;
496			}
497
498			emit_tex(&emit, inst);
499		} else {
500			emit_alu(&emit, &inst->U.P);
501		}
502	}
503
504	if (code->pixsize >= compiler->Base.max_temp_regs)
505		rc_error(&compiler->Base, "Too many hardware temporaries used.\n");
506
507	if (compiler->Base.Error)
508		return;
509
510	/* Finish the program */
511	finish_node(&emit);
512
513	code->config |= emit.current_node; /* FIRST_NODE_HAS_TEX set by finish_node */
514
515	/* Set r400 extended instruction fields.  These values will be ignored
516	 * on r300 cards. */
517	code->r400_code_offset_ext |=
518		(get_msbs_alu(0)
519				<< R400_ALU_OFFSET_MSB_SHIFT)
520		| (get_msbs_alu(code->alu.length - 1)
521				<< R400_ALU_SIZE_MSB_SHIFT);
522
523	tex_end = code->tex.length ? code->tex.length - 1 : 0;
524	code->code_offset =
525		((0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT)
526			& R300_PFS_CNTL_ALU_OFFSET_MASK)
527		| (((code->alu.length - 1) << R300_PFS_CNTL_ALU_END_SHIFT)
528			& R300_PFS_CNTL_ALU_END_MASK)
529		| ((0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT)
530			& R300_PFS_CNTL_TEX_OFFSET_MASK)
531		| ((tex_end << R300_PFS_CNTL_TEX_END_SHIFT)
532			& R300_PFS_CNTL_TEX_END_MASK)
533		| (get_msbs_tex(0, 5) << R400_TEX_START_MSB_SHIFT)
534		| (get_msbs_tex(tex_end, 6) << R400_TEX_SIZE_MSB_SHIFT)
535		;
536
537	if (emit.current_node < 3) {
538		int shift = 3 - emit.current_node;
539		int i;
540		for(i = emit.current_node; i >= 0; --i)
541			code->code_addr[shift + i] = code->code_addr[i];
542		for(i = 0; i < shift; ++i)
543			code->code_addr[i] = 0;
544	}
545
546	if (code->pixsize >= R300_PFS_NUM_TEMP_REGS
547	    || code->alu.length > R300_PFS_MAX_ALU_INST
548	    || code->tex.length > R300_PFS_MAX_TEX_INST) {
549
550		code->r390_mode = 1;
551	}
552}
553