/* * Copyright © 2010 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Authors: * Eric Anholt * */ /* DO NOT EDIT mesa_codegen.h. It is a generated file produced * from mesa_codegen.brg and will be overwritten. */ #include #include #include #include #include /* Everything before the first %% is pasted at the start of the * mesa_codegen.h header file. */ #include "ir_to_mesa.h" #define MBTREE_TYPE struct mbtree %% # The list of terminals is the set of things that ir_to_mesa.cpp will # generate in its trees. %term assign %term reference_vec4 %term exp_vec4 %term exp2_vec4 %term log_vec4 %term log2_vec4 %term add_vec4_vec4 %term sub_vec4_vec4 %term mul_vec4_vec4 %term div_vec4_vec4 %term dp4_vec4_vec4 %term dp3_vec4_vec4 %term dp2_vec4_vec4 %term sqrt_vec4 %term rsq_vec4 %term swizzle_vec4 # Each tree will produce stmt. Currently, the only production for # stmt is from an assign rule -- every statement tree from # ir_to_mesa.cpp assigns a result to a register. %start stmt # Now comes all the rules for code generation. Each rule is of the # general form # # produced: term(term, term) cost # { # code_run_when_we_choose_this_rule(); # } # # where choosing this rule means we turn term(term, term) into # produced at the cost of "cost". We measure "cost" in approximate # instruction count. The BURG should then more or less minimize the # number of instructions. # A reference of a variable is just a vec4 register location, # so it can be used as an argument for pretty much anything. vec4: reference_vec4 0 # Here's the rule everyone will hit: Moving the result of an # expression into a variable-dereference register location. # # Note that this is likely a gratuitous move. We could make variants # of each of the following rules, e.g: # # vec4: add_vec4_vec4(vec4, vec4) 1 # { # emit(ADD, tree, tree->left, tree->right); # } # # becoming # # vec4: assign(vec4_vec4, add_vec4_vec4(vec4, vec4) 1 # { # emit(ADD, tree->left, tree->right->left, tree->right->right); # } # # But it seems like a lot of extra typing and duped code, when we # probably want copy propagation and dead code after codegen anyway, # which would clean these up. stmt: assign(vec4, vec4) 1 { ir_to_mesa_emit_op1(tree, OPCODE_MOV, tree->left->dst_reg, tree->right->src_reg); } # Perform a swizzle by composing our swizzle with the swizzle # required to get at the src reg. vec4: swizzle_vec4(vec4) 1 { ir_to_mesa_src_reg reg = tree->left->src_reg; int swiz[4]; int i; for (i = 0; i < 4; i++) { swiz[i] = GET_SWZ(tree->src_reg.swizzle, i); if (swiz[i] >= SWIZZLE_X && swiz[i] <= SWIZZLE_Y) { swiz[i] = GET_SWZ(tree->left->src_reg.swizzle, swiz[i]); } } reg.swizzle = MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); ir_to_mesa_emit_op1(tree, OPCODE_MOV, tree->dst_reg, reg); } vec4: add_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_ADD, tree->dst_reg, tree->left->src_reg, tree->right->src_reg); } vec4: sub_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_SUB, tree->dst_reg, tree->left->src_reg, tree->right->src_reg); } vec4: mul_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_MUL, tree->dst_reg, tree->left->src_reg, tree->right->src_reg); } vec4: dp4_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_DP4, tree->dst_reg, tree->left->src_reg, tree->right->src_reg); tree->src_reg.swizzle = SWIZZLE_XXXX; } vec4: dp3_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_DP3, tree->dst_reg, tree->left->src_reg, tree->right->src_reg); tree->src_reg.swizzle = SWIZZLE_XXXX; } vec4: dp2_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_op2(tree, OPCODE_DP2, tree->dst_reg, tree->left->src_reg, tree->right->src_reg); tree->src_reg.swizzle = SWIZZLE_XXXX; } vec4: div_vec4_vec4(vec4, vec4) 1 { ir_to_mesa_emit_scalar_op1(tree, OPCODE_RCP, tree->dst_reg, tree->right->src_reg); ir_to_mesa_emit_op2(tree, OPCODE_MUL, tree->dst_reg, tree->src_reg, tree->left->src_reg); } vec4: sqrt_vec4(vec4) 1 { ir_to_mesa_emit_scalar_op1(tree, OPCODE_RSQ, tree->dst_reg, tree->left->src_reg); ir_to_mesa_emit_op1(tree, OPCODE_RCP, tree->dst_reg, tree->src_reg); } vec4: rsq_vec4(vec4) 1 { ir_to_mesa_emit_scalar_op1(tree, OPCODE_RSQ, tree->dst_reg, tree->left->src_reg); } vec4: exp_vec4(vec4) 1 { ir_to_mesa_emit_scalar_op1(tree, OPCODE_EXP, tree->dst_reg, tree->left->src_reg); } vec4: exp2_vec4(vec4) 1 { ir_to_mesa_emit_scalar_op1(tree, OPCODE_EX2, tree->dst_reg, tree->left->src_reg); } vec4: log_vec4(vec4) 1 { ir_to_mesa_emit_scalar_op1(tree, OPCODE_LOG, tree->dst_reg, tree->left->src_reg); } vec4: log2_vec4(vec4) 1 { ir_to_mesa_emit_scalar_op1(tree, OPCODE_LG2, tree->dst_reg, tree->left->src_reg); } %%