1/* 2 * Copyright (c) 2012-2015 Etnaviv Project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sub license, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Wladimir J. van der Laan <laanwj@gmail.com> 25 */ 26 27#include "etnaviv_asm.h" 28#include "etnaviv_debug.h" 29#include "etnaviv_util.h" 30 31/* An instruction can only read from one distinct uniform. 32 * This function verifies this property and returns true if the instruction 33 * is deemed correct and false otherwise. 34 */ 35static bool 36check_uniforms(const struct etna_inst *inst) 37{ 38 unsigned uni_rgroup = -1; 39 unsigned uni_reg = -1; 40 bool conflict = false; 41 42 for (unsigned i = 0; i < ETNA_NUM_SRC; i++) { 43 const struct etna_inst_src *src = &inst->src[i]; 44 45 if (!etna_rgroup_is_uniform(src->rgroup)) 46 continue; 47 48 if (uni_reg == -1) { /* first uniform used */ 49 uni_rgroup = src->rgroup; 50 uni_reg = src->reg; 51 } else { /* second or later; check that it is a re-use */ 52 if (uni_rgroup != src->rgroup || uni_reg != src->reg) { 53 conflict = true; 54 } 55 } 56 } 57 58 return !conflict; 59} 60 61int 62etna_assemble(uint32_t *out, const struct etna_inst *inst) 63{ 64 /* cannot have both src2 and imm */ 65 if (inst->imm && inst->src[2].use) 66 return 1; 67 68 if (!check_uniforms(inst)) 69 BUG("error: generating instruction that accesses two different uniforms"); 70 71 out[0] = VIV_ISA_WORD_0_OPCODE(inst->opcode) | 72 VIV_ISA_WORD_0_COND(inst->cond) | 73 COND(inst->sat, VIV_ISA_WORD_0_SAT) | 74 COND(inst->dst.use, VIV_ISA_WORD_0_DST_USE) | 75 VIV_ISA_WORD_0_DST_AMODE(inst->dst.amode) | 76 VIV_ISA_WORD_0_DST_REG(inst->dst.reg) | 77 VIV_ISA_WORD_0_DST_COMPS(inst->dst.comps) | 78 VIV_ISA_WORD_0_TEX_ID(inst->tex.id); 79 out[1] = VIV_ISA_WORD_1_TEX_AMODE(inst->tex.amode) | 80 VIV_ISA_WORD_1_TEX_SWIZ(inst->tex.swiz) | 81 COND(inst->src[0].use, VIV_ISA_WORD_1_SRC0_USE) | 82 VIV_ISA_WORD_1_SRC0_REG(inst->src[0].reg) | 83 COND(inst->type & 0x4, VIV_ISA_WORD_1_TYPE_BIT2) | 84 VIV_ISA_WORD_1_SRC0_SWIZ(inst->src[0].swiz) | 85 COND(inst->src[0].neg, VIV_ISA_WORD_1_SRC0_NEG) | 86 COND(inst->src[0].abs, VIV_ISA_WORD_1_SRC0_ABS); 87 out[2] = VIV_ISA_WORD_2_SRC0_AMODE(inst->src[0].amode) | 88 VIV_ISA_WORD_2_SRC0_RGROUP(inst->src[0].rgroup) | 89 COND(inst->src[1].use, VIV_ISA_WORD_2_SRC1_USE) | 90 VIV_ISA_WORD_2_SRC1_REG(inst->src[1].reg) | 91 VIV_ISA_WORD_2_SRC1_SWIZ(inst->src[1].swiz) | 92 COND(inst->src[1].neg, VIV_ISA_WORD_2_SRC1_NEG) | 93 COND(inst->src[1].abs, VIV_ISA_WORD_2_SRC1_ABS) | 94 VIV_ISA_WORD_2_SRC1_AMODE(inst->src[1].amode) | 95 VIV_ISA_WORD_2_TYPE_BIT01(inst->type & 0x3); 96 out[3] = VIV_ISA_WORD_3_SRC1_RGROUP(inst->src[1].rgroup) | 97 COND(inst->src[2].use, VIV_ISA_WORD_3_SRC2_USE) | 98 VIV_ISA_WORD_3_SRC2_REG(inst->src[2].reg) | 99 VIV_ISA_WORD_3_SRC2_SWIZ(inst->src[2].swiz) | 100 COND(inst->src[2].neg, VIV_ISA_WORD_3_SRC2_NEG) | 101 COND(inst->src[2].abs, VIV_ISA_WORD_3_SRC2_ABS) | 102 VIV_ISA_WORD_3_SRC2_AMODE(inst->src[2].amode) | 103 VIV_ISA_WORD_3_SRC2_RGROUP(inst->src[2].rgroup); 104 out[3] |= VIV_ISA_WORD_3_SRC2_IMM(inst->imm); 105 106 return 0; 107} 108