101e04c3fSmrg/* 201e04c3fSmrg * Copyright (c) 2012-2015 Etnaviv Project 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the 1201e04c3fSmrg * next paragraph) shall be included in all copies or substantial portions 1301e04c3fSmrg * of the Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2101e04c3fSmrg * DEALINGS IN THE SOFTWARE. 2201e04c3fSmrg * 2301e04c3fSmrg * Authors: 2401e04c3fSmrg * Wladimir J. van der Laan <laanwj@gmail.com> 2501e04c3fSmrg */ 2601e04c3fSmrg 2701e04c3fSmrg#ifndef H_ETNAVIV_ASM 2801e04c3fSmrg#define H_ETNAVIV_ASM 2901e04c3fSmrg 3001e04c3fSmrg#include <stdint.h> 317ec681f3Smrg#include <stdbool.h> 327ec681f3Smrg#include "util/u_math.h" 3301e04c3fSmrg#include "hw/isa.xml.h" 3401e04c3fSmrg 3501e04c3fSmrg/* Size of an instruction in 32-bit words */ 3601e04c3fSmrg#define ETNA_INST_SIZE (4) 3701e04c3fSmrg/* Number of source operands per instruction */ 3801e04c3fSmrg#define ETNA_NUM_SRC (3) 3901e04c3fSmrg 4001e04c3fSmrg/* Broadcast swizzle to all four components */ 4101e04c3fSmrg#define INST_SWIZ_BROADCAST(x) \ 4201e04c3fSmrg (INST_SWIZ_X(x) | INST_SWIZ_Y(x) | INST_SWIZ_Z(x) | INST_SWIZ_W(x)) 4301e04c3fSmrg/* Identity (NOP) swizzle */ 4401e04c3fSmrg#define INST_SWIZ_IDENTITY \ 4501e04c3fSmrg (INST_SWIZ_X(0) | INST_SWIZ_Y(1) | INST_SWIZ_Z(2) | INST_SWIZ_W(3)) 4601e04c3fSmrg/* Fully specified swizzle */ 4701e04c3fSmrg#define INST_SWIZ(x,y,z,w) \ 4801e04c3fSmrg (INST_SWIZ_X(x) | INST_SWIZ_Y(y) | INST_SWIZ_Z(z) | INST_SWIZ_W(w)) 4901e04c3fSmrg#define SWIZZLE(c0,c1,c2,c3) \ 5001e04c3fSmrg INST_SWIZ(INST_SWIZ_COMP_##c0, \ 5101e04c3fSmrg INST_SWIZ_COMP_##c1, \ 5201e04c3fSmrg INST_SWIZ_COMP_##c2, \ 5301e04c3fSmrg INST_SWIZ_COMP_##c3) 5401e04c3fSmrg 5501e04c3fSmrg/*** operands ***/ 5601e04c3fSmrg 5701e04c3fSmrg/* destination operand */ 5801e04c3fSmrgstruct etna_inst_dst { 5901e04c3fSmrg unsigned use:1; /* 0: not in use, 1: in use */ 6001e04c3fSmrg unsigned amode:3; /* INST_AMODE_* */ 6101e04c3fSmrg unsigned reg:7; /* register number 0..127 */ 627ec681f3Smrg unsigned write_mask:4; /* INST_COMPS_* */ 6301e04c3fSmrg}; 6401e04c3fSmrg 6501e04c3fSmrg/* texture operand */ 6601e04c3fSmrgstruct etna_inst_tex { 6701e04c3fSmrg unsigned id:5; /* sampler id */ 6801e04c3fSmrg unsigned amode:3; /* INST_AMODE_* */ 6901e04c3fSmrg unsigned swiz:8; /* INST_SWIZ */ 7001e04c3fSmrg}; 7101e04c3fSmrg 7201e04c3fSmrg/* source operand */ 7301e04c3fSmrgstruct etna_inst_src { 7401e04c3fSmrg unsigned use:1; /* 0: not in use, 1: in use */ 7501e04c3fSmrg unsigned rgroup:3; /* INST_RGROUP_* */ 767ec681f3Smrg union { 777ec681f3Smrg struct __attribute__((__packed__)) { 787ec681f3Smrg unsigned reg:9; /* register or uniform number 0..511 */ 797ec681f3Smrg unsigned swiz:8; /* INST_SWIZ */ 807ec681f3Smrg unsigned neg:1; /* negate (flip sign) if set */ 817ec681f3Smrg unsigned abs:1; /* absolute (remove sign) if set */ 827ec681f3Smrg unsigned amode:3; /* INST_AMODE_* */ 837ec681f3Smrg }; 847ec681f3Smrg struct __attribute__((__packed__)) { 857ec681f3Smrg unsigned imm_val : 20; 867ec681f3Smrg unsigned imm_type : 2; 877ec681f3Smrg }; 887ec681f3Smrg }; 8901e04c3fSmrg}; 9001e04c3fSmrg 9101e04c3fSmrg/*** instruction ***/ 9201e04c3fSmrgstruct etna_inst { 9301e04c3fSmrg uint8_t opcode; /* INST_OPCODE_* */ 9401e04c3fSmrg uint8_t type; /* INST_TYPE_* */ 9501e04c3fSmrg unsigned cond:5; /* INST_CONDITION_* */ 9601e04c3fSmrg unsigned sat:1; /* saturate result between 0..1 */ 977ec681f3Smrg unsigned sel_bit0:1; /* select low half mediump */ 987ec681f3Smrg unsigned sel_bit1:1; /* select high half mediump */ 997ec681f3Smrg unsigned dst_full:1; /* write to highp register */ 1007ec681f3Smrg unsigned halti5:1; /* allow multiple different uniform sources */ 10101e04c3fSmrg struct etna_inst_dst dst; /* destination operand */ 10201e04c3fSmrg struct etna_inst_tex tex; /* texture operand */ 10301e04c3fSmrg struct etna_inst_src src[ETNA_NUM_SRC]; /* source operand */ 10401e04c3fSmrg unsigned imm; /* takes place of src[2] for BRANCH/CALL */ 10501e04c3fSmrg}; 10601e04c3fSmrg 10701e04c3fSmrg/* Compose two swizzles (computes swz1.swz2) */ 10801e04c3fSmrgstatic inline uint32_t inst_swiz_compose(uint32_t swz1, uint32_t swz2) 10901e04c3fSmrg{ 11001e04c3fSmrg return INST_SWIZ_X((swz1 >> (((swz2 >> 0)&3)*2))&3) | 11101e04c3fSmrg INST_SWIZ_Y((swz1 >> (((swz2 >> 2)&3)*2))&3) | 11201e04c3fSmrg INST_SWIZ_Z((swz1 >> (((swz2 >> 4)&3)*2))&3) | 11301e04c3fSmrg INST_SWIZ_W((swz1 >> (((swz2 >> 6)&3)*2))&3); 11401e04c3fSmrg}; 11501e04c3fSmrg 1167ec681f3Smrg/* Compose two write_masks (computes wm1.wm2) */ 1177ec681f3Smrgstatic inline uint32_t inst_write_mask_compose(uint32_t wm1, uint32_t wm2) 1187ec681f3Smrg{ 1197ec681f3Smrg unsigned wm = 0; 1207ec681f3Smrg for (unsigned i = 0, j = 0; i < 4; i++) { 1217ec681f3Smrg if (wm2 & (1 << i)) { 1227ec681f3Smrg if (wm1 & (1 << j)) 1237ec681f3Smrg wm |= (1 << i); 1247ec681f3Smrg j++; 1257ec681f3Smrg } 1267ec681f3Smrg } 1277ec681f3Smrg return wm; 1287ec681f3Smrg}; 1297ec681f3Smrg 13001e04c3fSmrg/* Return whether the rgroup is one of the uniforms */ 13101e04c3fSmrgstatic inline int 13201e04c3fSmrgetna_rgroup_is_uniform(unsigned rgroup) 13301e04c3fSmrg{ 13401e04c3fSmrg return rgroup == INST_RGROUP_UNIFORM_0 || 13501e04c3fSmrg rgroup == INST_RGROUP_UNIFORM_1; 13601e04c3fSmrg} 13701e04c3fSmrg 1387ec681f3Smrgstatic inline struct etna_inst_src 1397ec681f3Smrgetna_immediate_src(unsigned type, uint32_t bits) 1407ec681f3Smrg{ 1417ec681f3Smrg return (struct etna_inst_src) { 1427ec681f3Smrg .use = 1, 1437ec681f3Smrg .rgroup = INST_RGROUP_IMMEDIATE, 1447ec681f3Smrg .imm_val = bits, 1457ec681f3Smrg .imm_type = type 1467ec681f3Smrg }; 1477ec681f3Smrg} 1487ec681f3Smrg 1497ec681f3Smrgstatic inline struct etna_inst_src 1507ec681f3Smrgetna_immediate_float(float x) 1517ec681f3Smrg{ 1527ec681f3Smrg uint32_t bits = fui(x); 1537ec681f3Smrg assert((bits & 0xfff) == 0); /* 12 lsb cut off */ 1547ec681f3Smrg return etna_immediate_src(0, bits >> 12); 1557ec681f3Smrg} 1567ec681f3Smrg 1577ec681f3Smrgstatic inline struct etna_inst_src 1587ec681f3Smrgetna_immediate_int(int x) 1597ec681f3Smrg{ 1607ec681f3Smrg assert(x >= -0x80000 && x < 0x80000); /* 20-bit signed int */ 1617ec681f3Smrg return etna_immediate_src(1, x); 1627ec681f3Smrg} 1637ec681f3Smrg 16401e04c3fSmrg/** 16501e04c3fSmrg * Build vivante instruction from structure with 16601e04c3fSmrg * opcode, cond, sat, dst_use, dst_amode, 16701e04c3fSmrg * dst_reg, dst_comps, tex_id, tex_amode, tex_swiz, 16801e04c3fSmrg * src[0-2]_reg, use, swiz, neg, abs, amode, rgroup, 16901e04c3fSmrg * imm 17001e04c3fSmrg * 17101e04c3fSmrg * Return 0 if successful, and a non-zero 17201e04c3fSmrg * value otherwise. 17301e04c3fSmrg */ 17401e04c3fSmrgint 17501e04c3fSmrgetna_assemble(uint32_t *out, const struct etna_inst *inst); 17601e04c3fSmrg 17701e04c3fSmrg/** 17801e04c3fSmrg * Set field imm of already-assembled instruction. 17901e04c3fSmrg * This is used for filling in jump destinations in a separate pass. 18001e04c3fSmrg */ 18101e04c3fSmrgstatic inline void 18201e04c3fSmrgetna_assemble_set_imm(uint32_t *out, uint32_t imm) 18301e04c3fSmrg{ 18401e04c3fSmrg out[3] |= VIV_ISA_WORD_3_SRC2_IMM(imm); 18501e04c3fSmrg} 18601e04c3fSmrg 18701e04c3fSmrg#endif 188