11c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/*
21c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Copyright (C) 2009 Nicolai Haehnle.
31c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Copyright 2010 Tom Stellard <tstellar@gmail.com>
41c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
51c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * All Rights Reserved.
61c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
71c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining
81c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * a copy of this software and associated documentation files (the
91c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * "Software"), to deal in the Software without restriction, including
101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * without limitation the rights to use, copy, modify, merge, publish,
111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * distribute, sublicense, and/or sell copies of the Software, and to
121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * permit persons to whom the Software is furnished to do so, subject to
131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * the following conditions:
141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The above copyright notice and this permission notice (including the
161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * next paragraph) shall be included in all copies or substantial
171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * portions of the Software.
181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_dataflow.h"
301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_compiler.h"
321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_compiler_util.h"
331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_program.h"
341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct read_write_mask_data {
361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * UserData;
371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_write_mask_fn Cb;
381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void reads_normal_callback(
411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * userdata,
421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * fullinst,
431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register * src)
441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct read_write_mask_data * cb_data = userdata;
461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int refmask = 0;
471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int chan;
481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(chan = 0; chan < 4; chan++) {
491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		refmask |= 1 << GET_SWZ(src->Swizzle, chan);
501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	refmask &= RC_MASK_XYZW;
521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (refmask) {
541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data->Cb(cb_data->UserData, fullinst, src->File,
551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							src->Index, refmask);
561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (refmask && src->RelAddr) {
591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data->Cb(cb_data->UserData, fullinst, RC_FILE_ADDRESS, 0,
601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák								RC_MASK_X);
611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void pair_get_src_refmasks(unsigned int * refmasks,
651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					struct rc_pair_instruction * inst,
661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					unsigned int swz, unsigned int src)
671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (swz >= 4)
691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y || swz == RC_SWIZZLE_Z) {
721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if(src == RC_PAIR_PRESUB_SRC) {
731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int i;
741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			int srcp_regs =
751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				rc_presubtract_src_reg_count(
761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				inst->RGB.Src[src].Index);
771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for(i = 0; i < srcp_regs; i++) {
781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				refmasks[i] |= 1 << swz;
791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		else {
821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			refmasks[src] |= 1 << swz;
831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (swz == RC_SWIZZLE_W) {
871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (src == RC_PAIR_PRESUB_SRC) {
881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int i;
891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			int srcp_regs = rc_presubtract_src_reg_count(
901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					inst->Alpha.Src[src].Index);
911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for(i = 0; i < srcp_regs; i++) {
921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				refmasks[i] |= 1 << swz;
931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		else {
961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			refmasks[src] |= 1 << swz;
971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void reads_pair(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
1021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_instruction * inst = &fullinst->U.P;
1041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int refmasks[3] = { 0, 0, 0 };
1051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int arg;
1071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(arg = 0; arg < 3; ++arg) {
1091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int chan;
1101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		for(chan = 0; chan < 3; ++chan) {
1111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int swz_rgb =
1121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				GET_SWZ(inst->RGB.Arg[arg].Swizzle, chan);
1131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int swz_alpha =
1141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				GET_SWZ(inst->Alpha.Arg[arg].Swizzle, chan);
1151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			pair_get_src_refmasks(refmasks, inst, swz_rgb,
1161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						inst->RGB.Arg[arg].Source);
1171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			pair_get_src_refmasks(refmasks, inst, swz_alpha,
1181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						inst->Alpha.Arg[arg].Source);
1191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
1201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
1211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(unsigned int src = 0; src < 3; ++src) {
1231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->RGB.Src[src].Used && (refmasks[src] & RC_MASK_XYZ))
1241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			cb(userdata, fullinst, inst->RGB.Src[src].File, inst->RGB.Src[src].Index,
1251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			   refmasks[src] & RC_MASK_XYZ);
1261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->Alpha.Src[src].Used && (refmasks[src] & RC_MASK_W))
1281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			cb(userdata, fullinst, inst->Alpha.Src[src].File, inst->Alpha.Src[src].Index, RC_MASK_W);
1291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
1301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void pair_sub_for_all_args(
1331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * fullinst,
1341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_sub_instruction * sub,
1351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_pair_read_arg_fn cb,
1361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * userdata)
1371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	int i;
1391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode);
1401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(i = 0; i < info->NumSrcRegs; i++) {
1421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int src_type;
1431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		src_type = rc_source_type_swz(sub->Arg[i].Swizzle);
1451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (src_type == RC_SOURCE_NONE)
1471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			continue;
1481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (sub->Arg[i].Source == RC_PAIR_PRESUB_SRC) {
1501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int presub_type;
1511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int presub_src_count;
1521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_pair_instruction_source * src_array;
1531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int j;
1541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (src_type & RC_SOURCE_RGB) {
1561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				presub_type = fullinst->
1571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Index;
1581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				src_array = fullinst->U.P.RGB.Src;
1591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			} else {
1601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				presub_type = fullinst->
1611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Index;
1621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				src_array = fullinst->U.P.Alpha.Src;
1631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
1641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			presub_src_count
1651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				= rc_presubtract_src_reg_count(presub_type);
1661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for(j = 0; j < presub_src_count; j++) {
1671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				cb(userdata, fullinst, &sub->Arg[i],
1681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák								&src_array[j]);
1691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
1701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		} else {
1711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_pair_instruction_source * src =
1721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				rc_pair_get_src(&fullinst->U.P, &sub->Arg[i]);
1731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (src) {
1741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				cb(userdata, fullinst, &sub->Arg[i], src);
1751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
1761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
1771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
1781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/* This function calls the callback function (cb) for each source used by
1811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * the instruction.
1821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * */
1831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_for_all_reads_src(
1841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
1851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_src_fn cb,
1861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * userdata)
1871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	const struct rc_opcode_info * opcode =
1891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					rc_get_opcode_info(inst->U.I.Opcode);
1901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* This function only works with normal instructions. */
1921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->Type != RC_INSTRUCTION_NORMAL) {
1931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		assert(0);
1941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
1951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
1961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
1981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->U.I.SrcReg[src].File == RC_FILE_NONE)
2001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			continue;
2011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->U.I.SrcReg[src].File == RC_FILE_PRESUB) {
2031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int i;
2041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int srcp_regs = rc_presubtract_src_reg_count(
2051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						inst->U.I.PreSub.Opcode);
2061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for( i = 0; i < srcp_regs; i++) {
2071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				cb(userdata, inst, &inst->U.I.PreSub.SrcReg[i]);
2081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
2091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		} else {
2101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			cb(userdata, inst, &inst->U.I.SrcReg[src]);
2111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
2121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
2161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * This function calls the callback function (cb) for each arg of the RGB and
2171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * alpha components.
2181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
2191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_pair_for_all_reads_arg(
2201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
2211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_pair_read_arg_fn cb,
2221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * userdata)
2231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* This function only works with pair instructions. */
2251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->Type != RC_INSTRUCTION_PAIR) {
2261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		assert(0);
2271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
2281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	pair_sub_for_all_args(inst, &inst->U.P.RGB, cb, userdata);
2311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	pair_sub_for_all_args(inst, &inst->U.P.Alpha, cb, userdata);
2321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
2351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Calls a callback function for all register reads.
2361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
2371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * This is conservative, i.e. if the same register is referenced multiple times,
2381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * the callback may also be called multiple times.
2391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Also, the writemask of the instruction is not taken into account.
2401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
2411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_for_all_reads_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata)
2421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->Type == RC_INSTRUCTION_NORMAL) {
2441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct read_write_mask_data cb_data;
2451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data.UserData = userdata;
2461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data.Cb = cb;
2471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_for_all_reads_src(inst, reads_normal_callback, &cb_data);
2491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else {
2501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		reads_pair(inst, cb, userdata);
2511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void writes_normal(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
2571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_sub_instruction * inst = &fullinst->U.I;
2591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
2601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (opcode->HasDstReg && inst->DstReg.WriteMask)
2621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, inst->DstReg.File, inst->DstReg.Index, inst->DstReg.WriteMask);
2631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->WriteALUResult)
2651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, RC_MASK_X);
2661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void writes_pair(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
2691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_instruction * inst = &fullinst->U.P;
2711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->RGB.WriteMask)
2731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->RGB.DestIndex, inst->RGB.WriteMask);
2741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->Alpha.WriteMask)
2761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->Alpha.DestIndex, RC_MASK_W);
2771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->WriteALUResult)
2791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, RC_MASK_X);
2801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
2831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Calls a callback function for all register writes in the instruction,
2841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * reporting writemasks to the callback function.
2851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
2861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * \warning Does not report output registers for paired instructions!
2871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
2881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_for_all_writes_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata)
2891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->Type == RC_INSTRUCTION_NORMAL) {
2911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		writes_normal(inst, cb, userdata);
2921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else {
2931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		writes_pair(inst, cb, userdata);
2941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct mask_to_chan_data {
2991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * UserData;
3001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_write_chan_fn Fn;
3011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
3021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void mask_to_chan_cb(void * data, struct rc_instruction * inst,
3041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_register_file file, unsigned int index, unsigned int mask)
3051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct mask_to_chan_data * d = data;
3071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(unsigned int chan = 0; chan < 4; ++chan) {
3081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (GET_BIT(mask, chan))
3091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			d->Fn(d->UserData, inst, file, index, chan);
3101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
3141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Calls a callback function for all sourced register channels.
3151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
3161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * This is conservative, i.e. channels may be called multiple times,
3171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * and the writemask of the instruction is not taken into account.
3181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
3191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_for_all_reads_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata)
3201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct mask_to_chan_data d;
3221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d.UserData = userdata;
3231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d.Fn = cb;
3241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_for_all_reads_mask(inst, &mask_to_chan_cb, &d);
3251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
3281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Calls a callback function for all written register channels.
3291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
3301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * \warning Does not report output registers for paired instructions!
3311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
3321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_for_all_writes_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata)
3331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct mask_to_chan_data d;
3351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d.UserData = userdata;
3361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d.Fn = cb;
3371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_for_all_writes_mask(inst, &mask_to_chan_cb, &d);
3381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void remap_normal_instruction(struct rc_instruction * fullinst,
3411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_remap_register_fn cb, void * userdata)
3421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_sub_instruction * inst = &fullinst->U.I;
3441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
3451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int remapped_presub = 0;
3461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (opcode->HasDstReg) {
3481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_register_file file = inst->DstReg.File;
3491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int index = inst->DstReg.Index;
3501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, &file, &index);
3521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->DstReg.File = file;
3541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->DstReg.Index = index;
3551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
3581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_register_file file = inst->SrcReg[src].File;
3591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int index = inst->SrcReg[src].Index;
3601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (file == RC_FILE_PRESUB) {
3621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int i;
3631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int srcp_srcs = rc_presubtract_src_reg_count(
3641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						inst->PreSub.Opcode);
3651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			/* Make sure we only remap presubtract sources once in
3661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * case more than one source register reads the
3671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * presubtract result. */
3681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (remapped_presub)
3691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				continue;
3701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for(i = 0; i < srcp_srcs; i++) {
3721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				file = inst->PreSub.SrcReg[i].File;
3731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				index = inst->PreSub.SrcReg[i].Index;
3741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				cb(userdata, fullinst, &file, &index);
3751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				inst->PreSub.SrcReg[i].File = file;
3761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				inst->PreSub.SrcReg[i].Index = index;
3771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
3781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			remapped_presub = 1;
3791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
3801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		else {
3811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			cb(userdata, fullinst, &file, &index);
3821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->SrcReg[src].File = file;
3841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->SrcReg[src].Index = index;
3851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
3861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void remap_pair_instruction(struct rc_instruction * fullinst,
3901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_remap_register_fn cb, void * userdata)
3911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_instruction * inst = &fullinst->U.P;
3931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->RGB.WriteMask) {
3951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_register_file file = RC_FILE_TEMPORARY;
3961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int index = inst->RGB.DestIndex;
3971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, &file, &index);
3991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->RGB.DestIndex = index;
4011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
4021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->Alpha.WriteMask) {
4041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_register_file file = RC_FILE_TEMPORARY;
4051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int index = inst->Alpha.DestIndex;
4061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb(userdata, fullinst, &file, &index);
4081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		inst->Alpha.DestIndex = index;
4101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
4111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(unsigned int src = 0; src < 3; ++src) {
4131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->RGB.Src[src].Used) {
4141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_register_file file = inst->RGB.Src[src].File;
4151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int index = inst->RGB.Src[src].Index;
4161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			cb(userdata, fullinst, &file, &index);
4181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->RGB.Src[src].File = file;
4201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->RGB.Src[src].Index = index;
4211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
4221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->Alpha.Src[src].Used) {
4241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_register_file file = inst->Alpha.Src[src].File;
4251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int index = inst->Alpha.Src[src].Index;
4261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			cb(userdata, fullinst, &file, &index);
4281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->Alpha.Src[src].File = file;
4301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			inst->Alpha.Src[src].Index = index;
4311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
4321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
4331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
4371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Remap all register accesses according to the given function.
4381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * That is, call the function \p cb for each referenced register (both read and written)
4391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * and update the given instruction \p inst accordingly
4401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * if it modifies its \ref pfile and \ref pindex contents.
4411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
4421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_remap_registers(struct rc_instruction * inst, rc_remap_register_fn cb, void * userdata)
4431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (inst->Type == RC_INSTRUCTION_NORMAL)
4451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		remap_normal_instruction(inst, cb, userdata);
4461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	else
4471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		remap_pair_instruction(inst, cb, userdata);
4481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct branch_write_mask {
4511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int IfWriteMask:4;
4521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int ElseWriteMask:4;
4531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int HasElse:1;
4541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
4551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákunion get_readers_read_cb {
4571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_src_fn I;
4581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_pair_read_arg_fn P;
4591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
4601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct get_readers_callback_data {
4621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * C;
4631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * ReaderData;
4641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_src_fn ReadNormalCB;
4651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_pair_read_arg_fn ReadPairCB;
4661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_write_mask_fn WriteCB;
4671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_register_file DstFile;
4681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int DstIndex;
4691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int DstMask;
4701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int AliveWriteMask;
4711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/*  For convenience, this is indexed starting at 1 */
4721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct branch_write_mask BranchMasks[R500_PFS_MAX_BRANCH_DEPTH_FULL + 1];
4731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák};
4741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic struct rc_reader * add_reader(
4761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct memory_pool * pool,
4771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * data,
4781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
4791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int mask)
4801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader * new;
4821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	memory_pool_array_reserve(pool, struct rc_reader, data->Readers,
4831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				data->ReaderCount, data->ReadersReserved, 1);
4841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new = &data->Readers[data->ReaderCount++];
4851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->Inst = inst;
4861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->WriteMask = mask;
4871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return new;
4881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void add_reader_normal(
4911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct memory_pool * pool,
4921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * data,
4931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
4941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int mask,
4951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register * src)
4961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader * new = add_reader(pool, data, inst, mask);
4981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->U.I.Src = src;
4991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void add_reader_pair(
5031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct memory_pool * pool,
5041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * data,
5051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
5061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int mask,
5071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_instruction_arg * arg,
5081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_instruction_source * src)
5091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader * new = add_reader(pool, data, inst, mask);
5111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->U.P.Src = src;
5121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->U.P.Arg = arg;
5131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic unsigned int get_readers_read_callback(
5161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * cb_data,
5171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int has_rel_addr,
5181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_register_file file,
5191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int index,
5201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int swizzle)
5211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int shared_mask, read_mask;
5231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (has_rel_addr) {
5251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data->ReaderData->Abort = 1;
5261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return RC_MASK_NONE;
5271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
5281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	shared_mask = rc_src_reads_dst_mask(file, index, swizzle,
5301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data->DstFile, cb_data->DstIndex, cb_data->AliveWriteMask);
5311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (shared_mask == RC_MASK_NONE)
5331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return shared_mask;
5341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* If we make it this far, it means that this source reads from the
5361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * same register written to by d->ReaderData->Writer. */
5371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	read_mask = rc_swizzle_to_writemask(swizzle);
5391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (cb_data->ReaderData->AbortOnRead & read_mask) {
5401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data->ReaderData->Abort = 1;
5411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return shared_mask;
5421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
5431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (cb_data->ReaderData->LoopDepth > 0) {
5451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data->ReaderData->AbortOnWrite |=
5461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				(read_mask & cb_data->AliveWriteMask);
5471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
5481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* XXX The behavior in this case should be configurable. */
5501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if ((read_mask & cb_data->AliveWriteMask) != read_mask) {
5511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		cb_data->ReaderData->Abort = 1;
5521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return shared_mask;
5531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
5541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return shared_mask;
5561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void get_readers_pair_read_callback(
5591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * userdata,
5601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
5611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_instruction_arg * arg,
5621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_instruction_source * src)
5631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int shared_mask;
5651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * d = userdata;
5661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	shared_mask = get_readers_read_callback(d,
5681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				0 /*Pair Instructions don't use RelAddr*/,
5691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				src->File, src->Index, arg->Swizzle);
5701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (shared_mask == RC_MASK_NONE)
5721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
5731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (d->ReadPairCB)
5751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->ReadPairCB(d->ReaderData, inst, arg, src);
5761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (d->ReaderData->ExitOnAbort && d->ReaderData->Abort)
5781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
5791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	add_reader_pair(&d->C->Pool, d->ReaderData, inst, shared_mask, arg, src);
5811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
5841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * This function is used by rc_get_readers_normal() to determine whether inst
5851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * is a reader of userdata->ReaderData->Writer
5861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
5871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void get_readers_normal_read_callback(
5881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * userdata,
5891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
5901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_src_register * src)
5911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * d = userdata;
5931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int shared_mask;
5941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	shared_mask = get_readers_read_callback(d,
5961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			src->RelAddr, src->File, src->Index, src->Swizzle);
5971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
5981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (shared_mask == RC_MASK_NONE)
5991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
6001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	/* The callback function could potentially clear d->ReaderData->Abort,
6011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	 * so we need to call it before we return. */
6021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (d->ReadNormalCB)
6031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->ReadNormalCB(d->ReaderData, inst, src);
6041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (d->ReaderData->ExitOnAbort && d->ReaderData->Abort)
6061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
6071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	add_reader_normal(&d->C->Pool, d->ReaderData, inst, shared_mask, src);
6091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
6121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * This function is used by rc_get_readers_normal() to determine when
6131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * userdata->ReaderData->Writer is dead (i. e. All compontents of its
6141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * destination register have been overwritten by other instructions).
6151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
6161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void get_readers_write_callback(
6171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void *userdata,
6181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
6191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_register_file file,
6201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int index,
6211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int mask)
6221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * d = userdata;
6241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (index == d->DstIndex && file == d->DstFile) {
6261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int shared_mask = mask & d->DstMask;
6271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->ReaderData->AbortOnRead &= ~shared_mask;
6281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->AliveWriteMask &= ~shared_mask;
6291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (d->ReaderData->AbortOnWrite & shared_mask) {
6301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			d->ReaderData->Abort = 1;
6311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
6321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
6331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if(d->WriteCB)
6351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->WriteCB(d->ReaderData, inst, file, index, mask);
6361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void push_branch_mask(
6391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * d,
6401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int * branch_depth)
6411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	(*branch_depth)++;
6431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (*branch_depth > R500_PFS_MAX_BRANCH_DEPTH_FULL) {
6441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->ReaderData->Abort = 1;
6451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
6461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
6471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->BranchMasks[*branch_depth].IfWriteMask =
6481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					d->AliveWriteMask;
6491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void pop_branch_mask(
6521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * d,
6531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int * branch_depth)
6541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct branch_write_mask * masks = &d->BranchMasks[*branch_depth];
6561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (masks->HasElse) {
6581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		/* Abort on read for components that were written in the IF
6591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		 * block. */
6601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->ReaderData->AbortOnRead |=
6611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				masks->IfWriteMask & ~masks->ElseWriteMask;
6621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		/* Abort on read for components that were written in the ELSE
6631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		 * block. */
6641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->ReaderData->AbortOnRead |=
6651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				masks->ElseWriteMask & ~d->AliveWriteMask;
6661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->AliveWriteMask = masks->IfWriteMask
6681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			^ ((masks->IfWriteMask ^ masks->ElseWriteMask)
6691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			& (masks->IfWriteMask ^ d->AliveWriteMask));
6701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else {
6711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->ReaderData->AbortOnRead |=
6721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				masks->IfWriteMask & ~d->AliveWriteMask;
6731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		d->AliveWriteMask = masks->IfWriteMask;
6741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
6761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	memset(masks, 0, sizeof(struct branch_write_mask));
6771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	(*branch_depth)--;
6781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
6791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void get_readers_for_single_write(
6811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * userdata,
6821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * writer,
6831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_register_file dst_file,
6841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int dst_index,
6851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int dst_mask)
6861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
6871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * tmp;
6881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int branch_depth = 0;
6891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * endloop = NULL;
6901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int abort_on_read_at_endloop = 0;
6911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * d = userdata;
6921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
6931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReaderData->Writer = writer;
6941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReaderData->AbortOnRead = 0;
6951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReaderData->AbortOnWrite = 0;
6961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReaderData->LoopDepth = 0;
6971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReaderData->InElse = 0;
6981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->DstFile = dst_file;
6991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->DstIndex = dst_index;
7001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->DstMask = dst_mask;
7011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->AliveWriteMask = dst_mask;
7021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	memset(d->BranchMasks, 0, sizeof(d->BranchMasks));
7031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (!dst_mask)
7051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
7061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for(tmp = writer->Next; tmp != &d->C->Program.Instructions;
7081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							tmp = tmp->Next){
7091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_opcode opcode = rc_get_flow_control_inst(tmp);
7101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		switch(opcode) {
7111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		case RC_OPCODE_BGNLOOP:
7121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			d->ReaderData->LoopDepth++;
7131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			push_branch_mask(d, &branch_depth);
7141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			break;
7151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		case RC_OPCODE_ENDLOOP:
7161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (d->ReaderData->LoopDepth > 0) {
7171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->ReaderData->LoopDepth--;
7181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (d->ReaderData->LoopDepth == 0) {
7191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					d->ReaderData->AbortOnWrite = 0;
7201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
7211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				pop_branch_mask(d, &branch_depth);
7221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			} else {
7231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				/* Here we have reached an ENDLOOP without
7241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * seeing its BGNLOOP.  These means that
7251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * the writer was written inside of a loop,
7261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * so it could have readers that are above it
7271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * (i.e. they have a lower IP).  To find these
7281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * readers we jump to the BGNLOOP instruction
7291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * and check each instruction until we get
7301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * back to the writer.
7311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 */
7321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				endloop = tmp;
7331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				tmp = rc_match_endloop(tmp);
7341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (!tmp) {
7351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					rc_error(d->C, "Failed to match endloop.\n");
7361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					d->ReaderData->Abort = 1;
7371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					return;
7381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
7391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				abort_on_read_at_endloop = d->ReaderData->AbortOnRead;
7401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->ReaderData->AbortOnRead |= d->AliveWriteMask;
7411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				continue;
7421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
7431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			break;
7441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		case RC_OPCODE_IF:
7451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			push_branch_mask(d, &branch_depth);
7461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			break;
7471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		case RC_OPCODE_ELSE:
7481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (branch_depth == 0) {
7491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->ReaderData->InElse = 1;
7501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			} else {
7511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				unsigned int temp_mask = d->AliveWriteMask;
7521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->AliveWriteMask =
7531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					d->BranchMasks[branch_depth].IfWriteMask;
7541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->BranchMasks[branch_depth].ElseWriteMask =
7551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák								temp_mask;
7561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->BranchMasks[branch_depth].HasElse = 1;
7571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
7581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			break;
7591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		case RC_OPCODE_ENDIF:
7601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (branch_depth == 0) {
7611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->ReaderData->AbortOnRead = d->AliveWriteMask;
7621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				d->ReaderData->InElse = 0;
7631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
7641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			else {
7651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				pop_branch_mask(d, &branch_depth);
7661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
7671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			break;
7681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		default:
7691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			break;
7701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
7711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (d->ReaderData->InElse)
7731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			continue;
7741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (tmp->Type == RC_INSTRUCTION_NORMAL) {
7761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_for_all_reads_src(tmp,
7771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				get_readers_normal_read_callback, d);
7781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		} else {
7791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_pair_for_all_reads_arg(tmp,
7801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				get_readers_pair_read_callback, d);
7811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
7821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		/* This can happen when we jump from an ENDLOOP to BGNLOOP */
7841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (tmp == writer) {
7851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			tmp = endloop;
7861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			endloop = NULL;
7871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			d->ReaderData->AbortOnRead = abort_on_read_at_endloop;
7881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			continue;
7891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
7901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		rc_for_all_writes_mask(tmp, get_readers_write_callback, d);
7911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (d->ReaderData->ExitOnAbort && d->ReaderData->Abort)
7931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			return;
7941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
7951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (branch_depth == 0 && !d->AliveWriteMask)
7961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			return;
7971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
7981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
7991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void init_get_readers_callback_data(
8011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data * d,
8021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * reader_data,
8031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c,
8041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_src_fn read_normal_cb,
8051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_pair_read_arg_fn read_pair_cb,
8061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_write_mask_fn write_cb)
8071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
8081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	reader_data->Abort = 0;
8091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	reader_data->ReaderCount = 0;
8101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	reader_data->ReadersReserved = 0;
8111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	reader_data->Readers = NULL;
8121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->C = c;
8141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReaderData = reader_data;
8151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReadNormalCB = read_normal_cb;
8161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->ReadPairCB = read_pair_cb;
8171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	d->WriteCB = write_cb;
8181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
8191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
8211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * This function will create a list of readers via the rc_reader_data struct.
8221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * This function will abort (set the flag data->Abort) and return if it
8231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * encounters an instruction that reads from @param writer and also a different
8241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * instruction.  Here are some examples:
8251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
8261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * writer = instruction 0;
8271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 0 MOV TEMP[0].xy, TEMP[1].xy
8281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 1 MOV TEMP[0].zw, TEMP[2].xy
8291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 2 MOV TEMP[3], TEMP[0]
8301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The Abort flag will be set on instruction 2, because it reads values written
8311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * by instructions 0 and 1.
8321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
8331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * writer = instruction 1;
8341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 0 IF TEMP[0].x
8351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 1 MOV TEMP[1], TEMP[2]
8361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 2 ELSE
8371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 3 MOV TEMP[1], TEMP[2]
8381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 4 ENDIF
8391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 5 MOV TEMP[3], TEMP[1]
8401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The Abort flag will be set on instruction 5, because it could read from the
8411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * value written by either instruction 1 or 3, depending on the jump decision
8421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * made at instruction 0.
8431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
8441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * writer = instruction 0;
8451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 0 MOV TEMP[0], TEMP[1]
8461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 2 BGNLOOP
8471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 3 ADD TEMP[0], TEMP[0], none.1
8481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 4 ENDLOOP
8491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The Abort flag will be set on instruction 3, because in the first iteration
8501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * of the loop it reads the value written by instruction 0 and in all other
8511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * iterations it reads the value written by instruction 3.
8521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
8531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @param read_cb This function will be called for for every instruction that
8541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * has been determined to be a reader of writer.
8551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @param write_cb This function will be called for every instruction after
8561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * writer.
8571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
8581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_get_readers(
8591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c,
8601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * writer,
8611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * data,
8621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_src_fn read_normal_cb,
8631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_pair_read_arg_fn read_pair_cb,
8641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_write_mask_fn write_cb)
8651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
8661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data d;
8671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	init_get_readers_callback_data(&d, data, c, read_normal_cb,
8691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						read_pair_cb, write_cb);
8701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_for_all_writes_mask(writer, get_readers_for_single_write, &d);
8721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
8731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_get_readers_sub(
8751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c,
8761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * writer,
8771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_sub_instruction * sub_writer,
8781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * data,
8791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_src_fn read_normal_cb,
8801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_pair_read_arg_fn read_pair_cb,
8811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_read_write_mask_fn write_cb)
8821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
8831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct get_readers_callback_data d;
8841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	init_get_readers_callback_data(&d, data, c, read_normal_cb,
8861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						read_pair_cb, write_cb);
8871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
8881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (sub_writer->WriteMask) {
8891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		get_readers_for_single_write(&d, writer, RC_FILE_TEMPORARY,
8901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			sub_writer->DestIndex, sub_writer->WriteMask);
8911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
8921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
893