1 /* 2 * Copyright (C) 2009 Nicolai Haehnle. 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 */ 27 28 #include "radeon_dataflow.h" 29 30 #include "radeon_compiler.h" 31 #include "radeon_swizzle.h" 32 33 34 static void rewrite_source(struct radeon_compiler * c, 35 struct rc_instruction * inst, unsigned src) 36 { 37 struct rc_swizzle_split split; 38 unsigned int tempreg = rc_find_free_temporary(c); 39 unsigned int usemask; 40 41 usemask = 0; 42 for(unsigned int chan = 0; chan < 4; ++chan) { 43 if (GET_SWZ(inst->U.I.SrcReg[src].Swizzle, chan) != RC_SWIZZLE_UNUSED) 44 usemask |= 1 << chan; 45 } 46 47 c->SwizzleCaps->Split(inst->U.I.SrcReg[src], usemask, &split); 48 49 for(unsigned int phase = 0; phase < split.NumPhases; ++phase) { 50 struct rc_instruction * mov = rc_insert_new_instruction(c, inst->Prev); 51 unsigned int phase_refmask; 52 unsigned int masked_negate; 53 54 mov->U.I.Opcode = RC_OPCODE_MOV; 55 mov->U.I.DstReg.File = RC_FILE_TEMPORARY; 56 mov->U.I.DstReg.Index = tempreg; 57 mov->U.I.DstReg.WriteMask = split.Phase[phase]; 58 mov->U.I.SrcReg[0] = inst->U.I.SrcReg[src]; 59 mov->U.I.PreSub = inst->U.I.PreSub; 60 61 phase_refmask = 0; 62 for(unsigned int chan = 0; chan < 4; ++chan) { 63 if (!GET_BIT(split.Phase[phase], chan)) 64 SET_SWZ(mov->U.I.SrcReg[0].Swizzle, chan, RC_SWIZZLE_UNUSED); 65 else 66 phase_refmask |= 1 << GET_SWZ(mov->U.I.SrcReg[0].Swizzle, chan); 67 } 68 69 phase_refmask &= RC_MASK_XYZW; 70 71 masked_negate = split.Phase[phase] & mov->U.I.SrcReg[0].Negate; 72 if (masked_negate == 0) 73 mov->U.I.SrcReg[0].Negate = 0; 74 else if (masked_negate == split.Phase[phase]) 75 mov->U.I.SrcReg[0].Negate = RC_MASK_XYZW; 76 77 } 78 79 inst->U.I.SrcReg[src].File = RC_FILE_TEMPORARY; 80 inst->U.I.SrcReg[src].Index = tempreg; 81 inst->U.I.SrcReg[src].Swizzle = 0; 82 inst->U.I.SrcReg[src].Negate = RC_MASK_NONE; 83 inst->U.I.SrcReg[src].Abs = 0; 84 for(unsigned int chan = 0; chan < 4; ++chan) { 85 SET_SWZ(inst->U.I.SrcReg[src].Swizzle, chan, 86 GET_BIT(usemask, chan) ? chan : RC_SWIZZLE_UNUSED); 87 } 88 } 89 90 void rc_dataflow_swizzles(struct radeon_compiler * c, void *user) 91 { 92 struct rc_instruction * inst; 93 94 for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { 95 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); 96 unsigned int src; 97 98 for(src = 0; src < opcode->NumSrcRegs; ++src) { 99 if (!c->SwizzleCaps->IsNative(inst->U.I.Opcode, inst->U.I.SrcReg[src])) 100 rewrite_source(c, inst, src); 101 } 102 } 103 } 104