1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 2009 Nicolai Haehnle.
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2010 Tom Stellard <tstellar@gmail.com>
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All Rights Reserved.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * a copy of this software and associated documentation files (the
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sublicense, and/or sell copies of the Software, and to
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * portions of the Software.
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_dataflow.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_compiler.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_compiler_util.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_program.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct read_write_mask_data {
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * UserData;
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_write_mask_fn Cb;
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void reads_normal_callback(
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * userdata,
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * fullinst,
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_src_register * src)
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct read_write_mask_data * cb_data = userdata;
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int refmask = 0;
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int chan;
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(chan = 0; chan < 4; chan++) {
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		refmask |= 1 << GET_SWZ(src->Swizzle, chan);
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	refmask &= RC_MASK_XYZW;
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (refmask) {
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data->Cb(cb_data->UserData, fullinst, src->File,
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							src->Index, refmask);
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (refmask && src->RelAddr) {
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data->Cb(cb_data->UserData, fullinst, RC_FILE_ADDRESS, 0,
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org								RC_MASK_X);
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void pair_get_src_refmasks(unsigned int * refmasks,
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					struct rc_pair_instruction * inst,
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					unsigned int swz, unsigned int src)
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (swz >= 4)
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y || swz == RC_SWIZZLE_Z) {
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if(src == RC_PAIR_PRESUB_SRC) {
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int i;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			int srcp_regs =
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				rc_presubtract_src_reg_count(
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->RGB.Src[src].Index);
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(i = 0; i < srcp_regs; i++) {
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				refmasks[i] |= 1 << swz;
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else {
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			refmasks[src] |= 1 << swz;
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (swz == RC_SWIZZLE_W) {
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (src == RC_PAIR_PRESUB_SRC) {
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int i;
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			int srcp_regs = rc_presubtract_src_reg_count(
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					inst->Alpha.Src[src].Index);
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(i = 0; i < srcp_regs; i++) {
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				refmasks[i] |= 1 << swz;
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else {
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			refmasks[src] |= 1 << swz;
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void reads_pair(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_instruction * inst = &fullinst->U.P;
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int refmasks[3] = { 0, 0, 0 };
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int arg;
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(arg = 0; arg < 3; ++arg) {
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int chan;
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for(chan = 0; chan < 3; ++chan) {
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int swz_rgb =
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				GET_SWZ(inst->RGB.Arg[arg].Swizzle, chan);
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int swz_alpha =
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				GET_SWZ(inst->Alpha.Arg[arg].Swizzle, chan);
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			pair_get_src_refmasks(refmasks, inst, swz_rgb,
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						inst->RGB.Arg[arg].Source);
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			pair_get_src_refmasks(refmasks, inst, swz_alpha,
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						inst->Alpha.Arg[arg].Source);
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int src = 0; src < 3; ++src) {
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->RGB.Src[src].Used && (refmasks[src] & RC_MASK_XYZ))
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			cb(userdata, fullinst, inst->RGB.Src[src].File, inst->RGB.Src[src].Index,
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			   refmasks[src] & RC_MASK_XYZ);
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->Alpha.Src[src].Used && (refmasks[src] & RC_MASK_W))
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			cb(userdata, fullinst, inst->Alpha.Src[src].File, inst->Alpha.Src[src].Index, RC_MASK_W);
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void pair_sub_for_all_args(
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * fullinst,
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_sub_instruction * sub,
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_pair_read_arg_fn cb,
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * userdata)
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int i;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode);
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(i = 0; i < info->NumSrcRegs; i++) {
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int src_type;
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_type = rc_source_type_swz(sub->Arg[i].Swizzle);
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (src_type == RC_SOURCE_NONE)
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (sub->Arg[i].Source == RC_PAIR_PRESUB_SRC) {
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int presub_type;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int presub_src_count;
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct rc_pair_instruction_source * src_array;
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int j;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (src_type & RC_SOURCE_RGB) {
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				presub_type = fullinst->
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Index;
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				src_array = fullinst->U.P.RGB.Src;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else {
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				presub_type = fullinst->
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Index;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				src_array = fullinst->U.P.Alpha.Src;
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			presub_src_count
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				= rc_presubtract_src_reg_count(presub_type);
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(j = 0; j < presub_src_count; j++) {
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cb(userdata, fullinst, &sub->Arg[i],
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org								&src_array[j]);
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else {
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct rc_pair_instruction_source * src =
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				rc_pair_get_src(&fullinst->U.P, &sub->Arg[i]);
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (src) {
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cb(userdata, fullinst, &sub->Arg[i], src);
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* This function calls the callback function (cb) for each source used by
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the instruction.
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * */
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_for_all_reads_src(
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_src_fn cb,
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * userdata)
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const struct rc_opcode_info * opcode =
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					rc_get_opcode_info(inst->U.I.Opcode);
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* This function only works with normal instructions. */
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->Type != RC_INSTRUCTION_NORMAL) {
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		assert(0);
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->U.I.SrcReg[src].File == RC_FILE_NONE)
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->U.I.SrcReg[src].File == RC_FILE_PRESUB) {
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int i;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int srcp_regs = rc_presubtract_src_reg_count(
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						inst->U.I.PreSub.Opcode);
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for( i = 0; i < srcp_regs; i++) {
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cb(userdata, inst, &inst->U.I.PreSub.SrcReg[i]);
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else {
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			cb(userdata, inst, &inst->U.I.SrcReg[src]);
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This function calls the callback function (cb) for each arg of the RGB and
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * alpha components.
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_pair_for_all_reads_arg(
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_pair_read_arg_fn cb,
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * userdata)
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* This function only works with pair instructions. */
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->Type != RC_INSTRUCTION_PAIR) {
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		assert(0);
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	pair_sub_for_all_args(inst, &inst->U.P.RGB, cb, userdata);
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	pair_sub_for_all_args(inst, &inst->U.P.Alpha, cb, userdata);
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Calls a callback function for all register reads.
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This is conservative, i.e. if the same register is referenced multiple times,
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the callback may also be called multiple times.
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Also, the writemask of the instruction is not taken into account.
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_for_all_reads_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata)
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->Type == RC_INSTRUCTION_NORMAL) {
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		struct read_write_mask_data cb_data;
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data.UserData = userdata;
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data.Cb = cb;
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_for_all_reads_src(inst, reads_normal_callback, &cb_data);
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		reads_pair(inst, cb, userdata);
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void writes_normal(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_sub_instruction * inst = &fullinst->U.I;
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (opcode->HasDstReg && inst->DstReg.WriteMask)
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, inst->DstReg.File, inst->DstReg.Index, inst->DstReg.WriteMask);
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->WriteALUResult)
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, RC_MASK_X);
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void writes_pair(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_instruction * inst = &fullinst->U.P;
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->RGB.WriteMask)
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->RGB.DestIndex, inst->RGB.WriteMask);
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->Alpha.WriteMask)
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->Alpha.DestIndex, RC_MASK_W);
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->WriteALUResult)
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, RC_MASK_X);
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Calls a callback function for all register writes in the instruction,
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * reporting writemasks to the callback function.
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \warning Does not report output registers for paired instructions!
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_for_all_writes_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata)
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->Type == RC_INSTRUCTION_NORMAL) {
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		writes_normal(inst, cb, userdata);
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		writes_pair(inst, cb, userdata);
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct mask_to_chan_data {
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * UserData;
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_write_chan_fn Fn;
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void mask_to_chan_cb(void * data, struct rc_instruction * inst,
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_register_file file, unsigned int index, unsigned int mask)
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct mask_to_chan_data * d = data;
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int chan = 0; chan < 4; ++chan) {
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (GET_BIT(mask, chan))
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			d->Fn(d->UserData, inst, file, index, chan);
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Calls a callback function for all sourced register channels.
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This is conservative, i.e. channels may be called multiple times,
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and the writemask of the instruction is not taken into account.
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_for_all_reads_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata)
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct mask_to_chan_data d;
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d.UserData = userdata;
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d.Fn = cb;
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_for_all_reads_mask(inst, &mask_to_chan_cb, &d);
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Calls a callback function for all written register channels.
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \warning Does not report output registers for paired instructions!
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_for_all_writes_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata)
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct mask_to_chan_data d;
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d.UserData = userdata;
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d.Fn = cb;
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_for_all_writes_mask(inst, &mask_to_chan_cb, &d);
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void remap_normal_instruction(struct rc_instruction * fullinst,
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_remap_register_fn cb, void * userdata)
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_sub_instruction * inst = &fullinst->U.I;
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int remapped_presub = 0;
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (opcode->HasDstReg) {
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_register_file file = inst->DstReg.File;
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int index = inst->DstReg.Index;
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, &file, &index);
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->DstReg.File = file;
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->DstReg.Index = index;
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_register_file file = inst->SrcReg[src].File;
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int index = inst->SrcReg[src].Index;
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (file == RC_FILE_PRESUB) {
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int i;
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int srcp_srcs = rc_presubtract_src_reg_count(
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						inst->PreSub.Opcode);
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* Make sure we only remap presubtract sources once in
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * case more than one source register reads the
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * presubtract result. */
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (remapped_presub)
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				continue;
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(i = 0; i < srcp_srcs; i++) {
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				file = inst->PreSub.SrcReg[i].File;
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				index = inst->PreSub.SrcReg[i].Index;
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cb(userdata, fullinst, &file, &index);
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->PreSub.SrcReg[i].File = file;
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->PreSub.SrcReg[i].Index = index;
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			remapped_presub = 1;
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else {
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			cb(userdata, fullinst, &file, &index);
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->SrcReg[src].File = file;
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->SrcReg[src].Index = index;
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void remap_pair_instruction(struct rc_instruction * fullinst,
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_remap_register_fn cb, void * userdata)
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_instruction * inst = &fullinst->U.P;
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->RGB.WriteMask) {
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_register_file file = RC_FILE_TEMPORARY;
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int index = inst->RGB.DestIndex;
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, &file, &index);
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->RGB.DestIndex = index;
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->Alpha.WriteMask) {
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_register_file file = RC_FILE_TEMPORARY;
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int index = inst->Alpha.DestIndex;
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb(userdata, fullinst, &file, &index);
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->Alpha.DestIndex = index;
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int src = 0; src < 3; ++src) {
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->RGB.Src[src].Used) {
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			rc_register_file file = inst->RGB.Src[src].File;
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int index = inst->RGB.Src[src].Index;
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			cb(userdata, fullinst, &file, &index);
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->RGB.Src[src].File = file;
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->RGB.Src[src].Index = index;
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->Alpha.Src[src].Used) {
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			rc_register_file file = inst->Alpha.Src[src].File;
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int index = inst->Alpha.Src[src].Index;
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			cb(userdata, fullinst, &file, &index);
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->Alpha.Src[src].File = file;
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->Alpha.Src[src].Index = index;
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Remap all register accesses according to the given function.
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * That is, call the function \p cb for each referenced register (both read and written)
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and update the given instruction \p inst accordingly
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * if it modifies its \ref pfile and \ref pindex contents.
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_remap_registers(struct rc_instruction * inst, rc_remap_register_fn cb, void * userdata)
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->Type == RC_INSTRUCTION_NORMAL)
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		remap_normal_instruction(inst, cb, userdata);
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		remap_pair_instruction(inst, cb, userdata);
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct branch_write_mask {
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int IfWriteMask:4;
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int ElseWriteMask:4;
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int HasElse:1;
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgunion get_readers_read_cb {
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_src_fn I;
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_pair_read_arg_fn P;
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct get_readers_callback_data {
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct radeon_compiler * C;
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader_data * ReaderData;
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_src_fn ReadNormalCB;
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_pair_read_arg_fn ReadPairCB;
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_write_mask_fn WriteCB;
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_register_file DstFile;
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int DstIndex;
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int DstMask;
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int AliveWriteMask;
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*  For convenience, this is indexed starting at 1 */
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct branch_write_mask BranchMasks[R500_PFS_MAX_BRANCH_DEPTH_FULL + 1];
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct rc_reader * add_reader(
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct memory_pool * pool,
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader_data * data,
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int mask)
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader * new;
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memory_pool_array_reserve(pool, struct rc_reader, data->Readers,
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				data->ReaderCount, data->ReadersReserved, 1);
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	new = &data->Readers[data->ReaderCount++];
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	new->Inst = inst;
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	new->WriteMask = mask;
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return new;
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void add_reader_normal(
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct memory_pool * pool,
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader_data * data,
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int mask,
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_src_register * src)
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader * new = add_reader(pool, data, inst, mask);
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	new->U.I.Src = src;
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void add_reader_pair(
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct memory_pool * pool,
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader_data * data,
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int mask,
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_instruction_arg * arg,
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_instruction_source * src)
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader * new = add_reader(pool, data, inst, mask);
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	new->U.P.Src = src;
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	new->U.P.Arg = arg;
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic unsigned int get_readers_read_callback(
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * cb_data,
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int has_rel_addr,
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_register_file file,
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int index,
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int swizzle)
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int shared_mask, read_mask;
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (has_rel_addr) {
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data->ReaderData->Abort = 1;
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return RC_MASK_NONE;
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	shared_mask = rc_src_reads_dst_mask(file, index, swizzle,
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data->DstFile, cb_data->DstIndex, cb_data->AliveWriteMask);
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (shared_mask == RC_MASK_NONE)
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return shared_mask;
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* If we make it this far, it means that this source reads from the
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * same register written to by d->ReaderData->Writer. */
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	read_mask = rc_swizzle_to_writemask(swizzle);
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (cb_data->ReaderData->AbortOnRead & read_mask) {
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data->ReaderData->Abort = 1;
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return shared_mask;
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (cb_data->ReaderData->LoopDepth > 0) {
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data->ReaderData->AbortOnWrite |=
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				(read_mask & cb_data->AliveWriteMask);
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* XXX The behavior in this case should be configurable. */
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if ((read_mask & cb_data->AliveWriteMask) != read_mask) {
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cb_data->ReaderData->Abort = 1;
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return shared_mask;
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return shared_mask;
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void get_readers_pair_read_callback(
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * userdata,
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_instruction_arg * arg,
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_instruction_source * src)
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int shared_mask;
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * d = userdata;
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	shared_mask = get_readers_read_callback(d,
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				0 /*Pair Instructions don't use RelAddr*/,
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				src->File, src->Index, arg->Swizzle);
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (shared_mask == RC_MASK_NONE)
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (d->ReadPairCB)
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->ReadPairCB(d->ReaderData, inst, arg, src);
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (d->ReaderData->ExitOnAbort && d->ReaderData->Abort)
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	add_reader_pair(&d->C->Pool, d->ReaderData, inst, shared_mask, arg, src);
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This function is used by rc_get_readers_normal() to determine whether inst
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is a reader of userdata->ReaderData->Writer
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void get_readers_normal_read_callback(
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * userdata,
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_src_register * src)
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * d = userdata;
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int shared_mask;
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	shared_mask = get_readers_read_callback(d,
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			src->RelAddr, src->File, src->Index, src->Swizzle);
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (shared_mask == RC_MASK_NONE)
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* The callback function could potentially clear d->ReaderData->Abort,
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * so we need to call it before we return. */
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (d->ReadNormalCB)
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->ReadNormalCB(d->ReaderData, inst, src);
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (d->ReaderData->ExitOnAbort && d->ReaderData->Abort)
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	add_reader_normal(&d->C->Pool, d->ReaderData, inst, shared_mask, src);
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This function is used by rc_get_readers_normal() to determine when
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * userdata->ReaderData->Writer is dead (i. e. All compontents of its
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * destination register have been overwritten by other instructions).
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void get_readers_write_callback(
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void *userdata,
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_register_file file,
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int index,
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int mask)
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * d = userdata;
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (index == d->DstIndex && file == d->DstFile) {
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int shared_mask = mask & d->DstMask;
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->ReaderData->AbortOnRead &= ~shared_mask;
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->AliveWriteMask &= ~shared_mask;
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (d->ReaderData->AbortOnWrite & shared_mask) {
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			d->ReaderData->Abort = 1;
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if(d->WriteCB)
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->WriteCB(d->ReaderData, inst, file, index, mask);
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void push_branch_mask(
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * d,
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int * branch_depth)
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	(*branch_depth)++;
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (*branch_depth > R500_PFS_MAX_BRANCH_DEPTH_FULL) {
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->ReaderData->Abort = 1;
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->BranchMasks[*branch_depth].IfWriteMask =
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					d->AliveWriteMask;
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void pop_branch_mask(
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * d,
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int * branch_depth)
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct branch_write_mask * masks = &d->BranchMasks[*branch_depth];
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (masks->HasElse) {
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* Abort on read for components that were written in the IF
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * block. */
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->ReaderData->AbortOnRead |=
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				masks->IfWriteMask & ~masks->ElseWriteMask;
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* Abort on read for components that were written in the ELSE
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * block. */
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->ReaderData->AbortOnRead |=
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				masks->ElseWriteMask & ~d->AliveWriteMask;
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->AliveWriteMask = masks->IfWriteMask
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			^ ((masks->IfWriteMask ^ masks->ElseWriteMask)
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			& (masks->IfWriteMask ^ d->AliveWriteMask));
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->ReaderData->AbortOnRead |=
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				masks->IfWriteMask & ~d->AliveWriteMask;
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		d->AliveWriteMask = masks->IfWriteMask;
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(masks, 0, sizeof(struct branch_write_mask));
677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	(*branch_depth)--;
678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void get_readers_for_single_write(
681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void * userdata,
682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * writer,
683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_register_file dst_file,
684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int dst_index,
685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int dst_mask)
686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * tmp;
688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int branch_depth = 0;
689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * endloop = NULL;
690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int abort_on_read_at_endloop = 0;
691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * d = userdata;
692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReaderData->Writer = writer;
694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReaderData->AbortOnRead = 0;
695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReaderData->AbortOnWrite = 0;
696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReaderData->LoopDepth = 0;
697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReaderData->InElse = 0;
698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->DstFile = dst_file;
699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->DstIndex = dst_index;
700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->DstMask = dst_mask;
701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->AliveWriteMask = dst_mask;
702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(d->BranchMasks, 0, sizeof(d->BranchMasks));
703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!dst_mask)
705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(tmp = writer->Next; tmp != &d->C->Program.Instructions;
708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							tmp = tmp->Next){
709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_opcode opcode = rc_get_flow_control_inst(tmp);
710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		switch(opcode) {
711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_BGNLOOP:
712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			d->ReaderData->LoopDepth++;
713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			push_branch_mask(d, &branch_depth);
714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_ENDLOOP:
716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (d->ReaderData->LoopDepth > 0) {
717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->ReaderData->LoopDepth--;
718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (d->ReaderData->LoopDepth == 0) {
719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					d->ReaderData->AbortOnWrite = 0;
720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				pop_branch_mask(d, &branch_depth);
722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else {
723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* Here we have reached an ENDLOOP without
724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * seeing its BGNLOOP.  These means that
725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * the writer was written inside of a loop,
726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * so it could have readers that are above it
727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * (i.e. they have a lower IP).  To find these
728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * readers we jump to the BGNLOOP instruction
729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * and check each instruction until we get
730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * back to the writer.
731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				endloop = tmp;
733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				tmp = rc_match_endloop(tmp);
734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (!tmp) {
735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					rc_error(d->C, "Failed to match endloop.\n");
736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					d->ReaderData->Abort = 1;
737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					return;
738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				abort_on_read_at_endloop = d->ReaderData->AbortOnRead;
740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->ReaderData->AbortOnRead |= d->AliveWriteMask;
741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				continue;
742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_IF:
745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			push_branch_mask(d, &branch_depth);
746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_ELSE:
748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (branch_depth == 0) {
749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->ReaderData->InElse = 1;
750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else {
751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				unsigned int temp_mask = d->AliveWriteMask;
752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->AliveWriteMask =
753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					d->BranchMasks[branch_depth].IfWriteMask;
754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->BranchMasks[branch_depth].ElseWriteMask =
755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org								temp_mask;
756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->BranchMasks[branch_depth].HasElse = 1;
757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_ENDIF:
760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (branch_depth == 0) {
761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->ReaderData->AbortOnRead = d->AliveWriteMask;
762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				d->ReaderData->InElse = 0;
763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else {
765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				pop_branch_mask(d, &branch_depth);
766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		default:
769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (d->ReaderData->InElse)
773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (tmp->Type == RC_INSTRUCTION_NORMAL) {
776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			rc_for_all_reads_src(tmp,
777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				get_readers_normal_read_callback, d);
778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else {
779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			rc_pair_for_all_reads_arg(tmp,
780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				get_readers_pair_read_callback, d);
781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* This can happen when we jump from an ENDLOOP to BGNLOOP */
784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (tmp == writer) {
785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			tmp = endloop;
786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			endloop = NULL;
787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			d->ReaderData->AbortOnRead = abort_on_read_at_endloop;
788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_for_all_writes_mask(tmp, get_readers_write_callback, d);
791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (d->ReaderData->ExitOnAbort && d->ReaderData->Abort)
793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return;
794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (branch_depth == 0 && !d->AliveWriteMask)
796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return;
797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void init_get_readers_callback_data(
801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data * d,
802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader_data * reader_data,
803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct radeon_compiler * c,
804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_src_fn read_normal_cb,
805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_pair_read_arg_fn read_pair_cb,
806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_write_mask_fn write_cb)
807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	reader_data->Abort = 0;
809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	reader_data->ReaderCount = 0;
810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	reader_data->ReadersReserved = 0;
811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	reader_data->Readers = NULL;
812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->C = c;
814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReaderData = reader_data;
815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReadNormalCB = read_normal_cb;
816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->ReadPairCB = read_pair_cb;
817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	d->WriteCB = write_cb;
818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This function will create a list of readers via the rc_reader_data struct.
822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This function will abort (set the flag data->Abort) and return if it
823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * encounters an instruction that reads from @param writer and also a different
824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * instruction.  Here are some examples:
825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * writer = instruction 0;
827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 0 MOV TEMP[0].xy, TEMP[1].xy
828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1 MOV TEMP[0].zw, TEMP[2].xy
829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2 MOV TEMP[3], TEMP[0]
830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The Abort flag will be set on instruction 2, because it reads values written
831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * by instructions 0 and 1.
832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * writer = instruction 1;
834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 0 IF TEMP[0].x
835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1 MOV TEMP[1], TEMP[2]
836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2 ELSE
837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 3 MOV TEMP[1], TEMP[2]
838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4 ENDIF
839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 5 MOV TEMP[3], TEMP[1]
840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The Abort flag will be set on instruction 5, because it could read from the
841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * value written by either instruction 1 or 3, depending on the jump decision
842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * made at instruction 0.
843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * writer = instruction 0;
845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 0 MOV TEMP[0], TEMP[1]
846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2 BGNLOOP
847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 3 ADD TEMP[0], TEMP[0], none.1
848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4 ENDLOOP
849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The Abort flag will be set on instruction 3, because in the first iteration
850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the loop it reads the value written by instruction 0 and in all other
851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * iterations it reads the value written by instruction 3.
852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param read_cb This function will be called for for every instruction that
854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * has been determined to be a reader of writer.
855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param write_cb This function will be called for every instruction after
856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * writer.
857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_get_readers(
859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct radeon_compiler * c,
860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * writer,
861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader_data * data,
862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_src_fn read_normal_cb,
863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_pair_read_arg_fn read_pair_cb,
864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_write_mask_fn write_cb)
865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data d;
867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	init_get_readers_callback_data(&d, data, c, read_normal_cb,
869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						read_pair_cb, write_cb);
870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_for_all_writes_mask(writer, get_readers_for_single_write, &d);
872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_get_readers_sub(
875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct radeon_compiler * c,
876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * writer,
877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_pair_sub_instruction * sub_writer,
878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_reader_data * data,
879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_src_fn read_normal_cb,
880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_pair_read_arg_fn read_pair_cb,
881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_read_write_mask_fn write_cb)
882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct get_readers_callback_data d;
884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	init_get_readers_callback_data(&d, data, c, read_normal_cb,
886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						read_pair_cb, write_cb);
887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (sub_writer->WriteMask) {
889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		get_readers_for_single_write(&d, writer, RC_FILE_TEMPORARY,
890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sub_writer->DestIndex, sub_writer->WriteMask);
891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
893