summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
diff options
context:
space:
mode:
authorNicolai Hähnle <nhaehnle@gmail.com>2009-10-04 16:49:53 +0200
committerNicolai Hähnle <nhaehnle@gmail.com>2009-10-04 16:50:07 +0200
commita30560e6f0fc8e3056f48a140c9c6b582f5e2e77 (patch)
treea498edd61d2a200f992a2b77ed920299f0dca8ed /src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
parent995135479d5662d1b1970c0f233c3c3d944d8b4d (diff)
r300/compiler: Refactor the radeon_pair code to support control flow instructions
Signed-off-by: Nicolai Hähnle <nhaehnle@gmail.com>
Diffstat (limited to 'src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c')
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c132
1 files changed, 131 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
index a171d8ab54..58dcb20d29 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
@@ -27,6 +27,136 @@
#include "radeon_dataflow.h"
-#include "radeon_compiler.h"
+#include "radeon_program.h"
+static void reads_normal(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+{
+ struct rc_sub_instruction * inst = &fullinst->U.I;
+ const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
+
+ for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
+ unsigned int refmask = 0;
+
+ if (inst->SrcReg[src].File == RC_FILE_NONE)
+ return;
+
+ for(unsigned int chan = 0; chan < 4; ++chan)
+ refmask |= 1 << GET_SWZ(inst->SrcReg[src].Swizzle, chan);
+
+ refmask &= ~RC_MASK_XYZW;
+
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ if (GET_BIT(refmask, chan)) {
+ cb(userdata, fullinst, inst->SrcReg[src].File, inst->SrcReg[src].Index, chan);
+ }
+ }
+
+ if (refmask && inst->SrcReg[src].RelAddr)
+ cb(userdata, fullinst, RC_FILE_ADDRESS, 0, RC_MASK_X);
+ }
+}
+
+static void reads_pair(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+{
+ struct rc_pair_instruction * inst = &fullinst->U.P;
+ unsigned int refmasks[3] = { 0, 0, 0 };
+
+ if (inst->RGB.Opcode != RC_OPCODE_NOP) {
+ const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->RGB.Opcode);
+
+ for(unsigned int arg = 0; arg < opcode->NumSrcRegs; ++arg) {
+ for(unsigned int chan = 0; chan < 3; ++chan) {
+ unsigned int swz = GET_SWZ(inst->RGB.Arg[arg].Swizzle, chan);
+ if (swz < 4)
+ refmasks[inst->RGB.Arg[arg].Source] |= 1 << swz;
+ }
+ }
+ }
+
+ if (inst->Alpha.Opcode != RC_OPCODE_NOP) {
+ const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Alpha.Opcode);
+
+ for(unsigned int arg = 0; arg < opcode->NumSrcRegs; ++arg) {
+ if (inst->Alpha.Arg[arg].Swizzle < 4)
+ refmasks[inst->Alpha.Arg[arg].Source] |= 1 << inst->Alpha.Arg[arg].Swizzle;
+ }
+ }
+
+ for(unsigned int src = 0; src < 3; ++src) {
+ if (inst->RGB.Src[src].Used) {
+ for(unsigned int chan = 0; chan < 3; ++chan) {
+ if (GET_BIT(refmasks[src], chan))
+ cb(userdata, fullinst, inst->RGB.Src[src].File, inst->RGB.Src[src].Index, chan);
+ }
+ }
+
+ if (inst->Alpha.Src[src].Used) {
+ if (GET_BIT(refmasks[src], 3))
+ cb(userdata, fullinst, inst->Alpha.Src[src].File, inst->Alpha.Src[src].Index, 3);
+ }
+ }
+}
+
+/**
+ * Calls a callback function for all sourced register channels.
+ *
+ * This is conservative, i.e. channels may be called multiple times,
+ * and the writemask of the instruction is not taken into account.
+ */
+void rc_for_all_reads(struct rc_instruction * inst, rc_read_write_fn cb, void * userdata)
+{
+ if (inst->Type == RC_INSTRUCTION_NORMAL) {
+ reads_normal(inst, cb, userdata);
+ } else {
+ reads_pair(inst, cb, userdata);
+ }
+}
+
+
+
+static void writes_normal(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+{
+ struct rc_sub_instruction * inst = &fullinst->U.I;
+ const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
+
+ if (opcode->HasDstReg) {
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ if (GET_BIT(inst->DstReg.WriteMask, chan))
+ cb(userdata, fullinst, inst->DstReg.File, inst->DstReg.Index, chan);
+ }
+ }
+
+ if (inst->WriteALUResult)
+ cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, 0);
+}
+
+static void writes_pair(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+{
+ struct rc_pair_instruction * inst = &fullinst->U.P;
+
+ for(unsigned int chan = 0; chan < 3; ++chan) {
+ if (GET_BIT(inst->RGB.WriteMask, chan))
+ cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->RGB.DestIndex, chan);
+ }
+
+ if (inst->Alpha.WriteMask)
+ cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->Alpha.DestIndex, 3);
+
+ if (inst->WriteALUResult)
+ cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, 0);
+}
+
+/**
+ * Calls a callback function for all written register channels.
+ *
+ * \warning Does not report output registers for paired instructions!
+ */
+void rc_for_all_writes(struct rc_instruction * inst, rc_read_write_fn cb, void * userdata)
+{
+ if (inst->Type == RC_INSTRUCTION_NORMAL) {
+ writes_normal(inst, cb, userdata);
+ } else {
+ writes_pair(inst, cb, userdata);
+ }
+}