11c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/* 21c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Copyright (C) 2009 Nicolai Haehnle. 31c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 41c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * All Rights Reserved. 51c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 61c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining 71c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * a copy of this software and associated documentation files (the 81c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * "Software"), to deal in the Software without restriction, including 91c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * without limitation the rights to use, copy, modify, merge, publish, 101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * distribute, sublicense, and/or sell copies of the Software, and to 111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * permit persons to whom the Software is furnished to do so, subject to 121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * the following conditions: 131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The above copyright notice and this permission notice (including the 151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * next paragraph) shall be included in all copies or substantial 161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * portions of the Software. 171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * 261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */ 271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_program_pair.h" 291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_compiler.h" 311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_compiler_util.h" 321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/** 351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Finally rewrite ADD, MOV, MUL as the appropriate native instruction 361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * and reverse the order of arguments for CMP. 371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */ 381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void final_rewrite(struct rc_sub_instruction *inst) 391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{ 401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák struct rc_src_register tmp; 411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák switch(inst->Opcode) { 431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_ADD: 441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[2] = inst->SrcReg[1]; 451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[1].File = RC_FILE_NONE; 461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[1].Swizzle = RC_SWIZZLE_1111; 471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[1].Negate = RC_MASK_NONE; 481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->Opcode = RC_OPCODE_MAD; 491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_CMP: 511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák tmp = inst->SrcReg[2]; 521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[2] = inst->SrcReg[0]; 531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[0] = tmp; 541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_MOV: 561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák /* AMD say we should use CMP. 571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * However, when we transform 581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * KIL -r0; 591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * into 601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * CMP tmp, -r0, -r0, 0; 611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * KIL tmp; 621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * we get incorrect behaviour on R500 when r0 == 0.0. 631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * It appears that the R500 KIL hardware treats -0.0 as less 641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * than zero. 651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */ 661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[1].File = RC_FILE_NONE; 671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[1].Swizzle = RC_SWIZZLE_1111; 681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[2].File = RC_FILE_NONE; 691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[2].Swizzle = RC_SWIZZLE_0000; 701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->Opcode = RC_OPCODE_MAD; 711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_MUL: 731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[2].File = RC_FILE_NONE; 741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[2].Swizzle = RC_SWIZZLE_0000; 751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->Opcode = RC_OPCODE_MAD; 761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák default: 781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák /* nothing to do */ 791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák} 821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/** 851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Classify an instruction according to which ALUs etc. it needs 861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */ 871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void classify_instruction(struct rc_sub_instruction * inst, 881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int * needrgb, int * needalpha, int * istranscendent) 891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{ 901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *needrgb = (inst->DstReg.WriteMask & RC_MASK_XYZ) ? 1 : 0; 911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *needalpha = (inst->DstReg.WriteMask & RC_MASK_W) ? 1 : 0; 921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *istranscendent = 0; 931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->WriteALUResult == RC_ALURESULT_X) 951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *needrgb = 1; 961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák else if (inst->WriteALUResult == RC_ALURESULT_W) 971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *needalpha = 1; 981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák switch(inst->Opcode) { 1001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_ADD: 1011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_CMP: 1021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_CND: 1031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_DDX: 1041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_DDY: 1051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_FRC: 1061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_MAD: 1071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_MAX: 1081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_MIN: 1091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_MOV: 1101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_MUL: 1111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 1121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_COS: 1131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_EX2: 1141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_LG2: 1151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_RCP: 1161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_RSQ: 1171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_SIN: 1181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *istranscendent = 1; 1191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *needalpha = 1; 1201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 1211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_DP4: 1221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *needalpha = 1; 1231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák /* fall through */ 1241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák case RC_OPCODE_DP3: 1251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *needrgb = 1; 1261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 1271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák default: 1281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 1291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 1301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák} 1311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void src_uses(struct rc_src_register src, unsigned int * rgb, 1331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int * alpha) 1341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{ 1351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int j; 1361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for(j = 0; j < 4; ++j) { 1371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int swz = GET_SWZ(src.Swizzle, j); 1381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (swz < 3) 1391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *rgb = 1; 1401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák else if (swz < 4) 1411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *alpha = 1; 1421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 1431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák} 1441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/** 1461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Fill the given ALU instruction's opcodes and source operands into the given pair, 1471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * if possible. 1481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */ 1491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void set_pair_instruction(struct r300_fragment_program_compiler *c, 1501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák struct rc_pair_instruction * pair, 1511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák struct rc_sub_instruction * inst) 1521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{ 1531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int needrgb, needalpha, istranscendent; 1541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák const struct rc_opcode_info * opcode; 1551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int i; 1561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák memset(pair, 0, sizeof(struct rc_pair_instruction)); 1581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák classify_instruction(inst, &needrgb, &needalpha, &istranscendent); 1601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (needrgb) { 1621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (istranscendent) 1631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Opcode = RC_OPCODE_REPL_ALPHA; 1641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák else 1651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Opcode = inst->Opcode; 1661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->SaturateMode == RC_SATURATE_ZERO_ONE) 1671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Saturate = 1; 1681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 1691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (needalpha) { 1701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Opcode = inst->Opcode; 1711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->SaturateMode == RC_SATURATE_ZERO_ONE) 1721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Saturate = 1; 1731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 1741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák opcode = rc_get_opcode_info(inst->Opcode); 1761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák /* Presubtract handling: 1781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * We need to make sure that the values used by the presubtract 1791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * operation end up in src0 or src1. */ 1801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if(inst->PreSub.Opcode != RC_PRESUB_NONE) { 1811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák /* rc_pair_alloc_source() will fill in data for 1821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * pair->{RGB,ALPHA}.Src[RC_PAIR_PRESUB_SRC] */ 1831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int j; 1841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for(j = 0; j < 3; j++) { 1851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int src_regs; 1861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if(inst->SrcReg[j].File != RC_FILE_PRESUB) 1871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák continue; 1881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 1891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák src_regs = rc_presubtract_src_reg_count( 1901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->PreSub.Opcode); 1911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for(i = 0; i < src_regs; i++) { 1921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int rgb = 0; 1931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int alpha = 0; 1941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák src_uses(inst->SrcReg[j], &rgb, &alpha); 1951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if(rgb) { 1961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Src[i].File = 1971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->PreSub.SrcReg[i].File; 1981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Src[i].Index = 1991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->PreSub.SrcReg[i].Index; 2001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Src[i].Used = 1; 2011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if(alpha) { 2031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Src[i].File = 2041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->PreSub.SrcReg[i].File; 2051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Src[i].Index = 2061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->PreSub.SrcReg[i].Index; 2071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Src[i].Used = 1; 2081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 2131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for(i = 0; i < opcode->NumSrcRegs; ++i) { 2141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int source; 2151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (needrgb && !istranscendent) { 2161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int srcrgb = 0; 2171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int srcalpha = 0; 2181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int srcmask = 0; 2191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák int j; 2201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák /* We don't care about the alpha channel here. We only 2211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * want the part of the swizzle that writes to rgb, 2221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * since we are creating an rgb instruction. */ 2231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for(j = 0; j < 3; ++j) { 2241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int swz = GET_SWZ(inst->SrcReg[i].Swizzle, j); 2251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 2261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (swz < RC_SWIZZLE_W) 2271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák srcrgb = 1; 2281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák else if (swz == RC_SWIZZLE_W) 2291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák srcalpha = 1; 2301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 2311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (swz < RC_SWIZZLE_UNUSED) 2321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák srcmask |= 1 << j; 2331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák source = rc_pair_alloc_source(pair, srcrgb, srcalpha, 2351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[i].File, inst->SrcReg[i].Index); 2361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (source < 0) { 2371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák rc_error(&c->Base, "Failed to translate " 2381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák "rgb instruction.\n"); 2391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák return; 2401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Arg[i].Source = source; 2421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Arg[i].Swizzle = 2431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák rc_init_swizzle(inst->SrcReg[i].Swizzle, 3); 2441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Arg[i].Abs = inst->SrcReg[i].Abs; 2451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Arg[i].Negate = !!(srcmask & inst->SrcReg[i].Negate & (RC_MASK_X | RC_MASK_Y | RC_MASK_Z)); 2461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (needalpha) { 2481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int srcrgb = 0; 2491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák unsigned int srcalpha = 0; 250b5ecf5ba466c3e1872dc9281b01f4e59ca1a388bTom Stellard unsigned int swz; 251b5ecf5ba466c3e1872dc9281b01f4e59ca1a388bTom Stellard if (istranscendent) { 252b5ecf5ba466c3e1872dc9281b01f4e59ca1a388bTom Stellard swz = rc_get_scalar_src_swz(inst->SrcReg[i].Swizzle); 253b5ecf5ba466c3e1872dc9281b01f4e59ca1a388bTom Stellard } else { 254b5ecf5ba466c3e1872dc9281b01f4e59ca1a388bTom Stellard swz = GET_SWZ(inst->SrcReg[i].Swizzle, 3); 255b5ecf5ba466c3e1872dc9281b01f4e59ca1a388bTom Stellard } 256b5ecf5ba466c3e1872dc9281b01f4e59ca1a388bTom Stellard 2571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (swz < 3) 2581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák srcrgb = 1; 2591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák else if (swz < 4) 2601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák srcalpha = 1; 2611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák source = rc_pair_alloc_source(pair, srcrgb, srcalpha, 2621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->SrcReg[i].File, inst->SrcReg[i].Index); 2631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (source < 0) { 2641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák rc_error(&c->Base, "Failed to translate " 2651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák "alpha instruction.\n"); 2661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák return; 2671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Arg[i].Source = source; 2691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Arg[i].Swizzle = rc_init_swizzle(swz, 1); 2701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Arg[i].Abs = inst->SrcReg[i].Abs; 271befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard 272befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard if (istranscendent) { 273befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard pair->Alpha.Arg[i].Negate = 274befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard !!(inst->SrcReg[i].Negate & 275befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard inst->DstReg.WriteMask); 276befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard } else { 277befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard pair->Alpha.Arg[i].Negate = 278befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard !!(inst->SrcReg[i].Negate & RC_MASK_W); 279befcce264c8bf8fdac233e6a01cadc595a1d11d3Tom Stellard } 2801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 2831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák /* Destination handling */ 2841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->DstReg.File == RC_FILE_OUTPUT) { 2851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->DstReg.Index == c->OutputDepth) { 2861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.DepthWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3); 2871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } else { 2881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for (i = 0; i < 4; i++) { 2891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->DstReg.Index == c->OutputColor[i]) { 2901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.Target = i; 2911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.Target = i; 2921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.OutputWriteMask |= 2931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->DstReg.WriteMask & RC_MASK_XYZ; 2941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.OutputWriteMask |= 2951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák GET_BIT(inst->DstReg.WriteMask, 3); 2961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák break; 2971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 2991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } else { 3011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (needrgb) { 3021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.DestIndex = inst->DstReg.Index; 3031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->RGB.WriteMask |= inst->DstReg.WriteMask & RC_MASK_XYZ; 3041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (needalpha) { 3071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.WriteMask |= (GET_BIT(inst->DstReg.WriteMask, 3) << 3); 3081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (pair->Alpha.WriteMask) { 3091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->Alpha.DestIndex = inst->DstReg.Index; 3101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 314e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard if (needrgb) { 315e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard pair->RGB.Omod = inst->Omod; 316e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard } 317e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard if (needalpha) { 318e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard pair->Alpha.Omod = inst->Omod; 319e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard } 320e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard 3211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->WriteALUResult) { 3221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->WriteALUResult = inst->WriteALUResult; 3231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák pair->ALUResultCompare = inst->ALUResultCompare; 3241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák} 3261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void check_opcode_support(struct r300_fragment_program_compiler *c, 3291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák struct rc_sub_instruction *inst) 3301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{ 3311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode); 3321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (opcode->HasDstReg) { 3341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->SaturateMode == RC_SATURATE_MINUS_PLUS_ONE) { 3351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák rc_error(&c->Base, "Fragment program does not support signed Saturate.\n"); 3361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák return; 3371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for (unsigned i = 0; i < opcode->NumSrcRegs; i++) { 3411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->SrcReg[i].RelAddr) { 3421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák rc_error(&c->Base, "Fragment program does not support relative addressing " 3431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák " of source operands.\n"); 3441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák return; 3451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák} 3481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/** 3511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Translate all ALU instructions into corresponding pair instructions, 3521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * performing no other changes. 3531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */ 3541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_pair_translate(struct radeon_compiler *cc, void *user) 3551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{ 3561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)cc; 3571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák for(struct rc_instruction * inst = c->Base.Program.Instructions.Next; 3591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst != &c->Base.Program.Instructions; 3601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst = inst->Next) { 3611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák const struct rc_opcode_info * opcode; 3621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák struct rc_sub_instruction copy; 3631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (inst->Type != RC_INSTRUCTION_NORMAL) 3651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák continue; 3661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák opcode = rc_get_opcode_info(inst->U.I.Opcode); 3681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák if (opcode->HasTexture || opcode->IsFlowControl || opcode->Opcode == RC_OPCODE_KIL) 3701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák continue; 3711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák copy = inst->U.I; 3731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák check_opcode_support(c, ©); 3751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák 3761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák final_rewrite(©); 3771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák inst->Type = RC_INSTRUCTION_PAIR; 3781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák set_pair_instruction(c, &inst->U.P, ©); 3791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák } 3801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák} 381