/* * Copyright © 2016 Broadcom * * 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. */ /** * @file qpu_instr.h * * Definitions of the unpacked form of QPU instructions. Assembly and * disassembly will use this for talking about instructions, with qpu_encode.c * and qpu_decode.c handling the pack and unpack of the actual 64-bit QPU * instruction. */ #ifndef QPU_INSTR_H #define QPU_INSTR_H #include #include #include "util/macros.h" struct v3d_device_info; struct v3d_qpu_sig { bool thrsw:1; bool ldunif:1; bool ldunifa:1; bool ldunifrf:1; bool ldunifarf:1; bool ldtmu:1; bool ldvary:1; bool ldvpm:1; bool ldtlb:1; bool ldtlbu:1; bool small_imm:1; bool ucb:1; bool rotate:1; bool wrtmuc:1; }; enum v3d_qpu_cond { V3D_QPU_COND_NONE, V3D_QPU_COND_IFA, V3D_QPU_COND_IFB, V3D_QPU_COND_IFNA, V3D_QPU_COND_IFNB, }; enum v3d_qpu_pf { V3D_QPU_PF_NONE, V3D_QPU_PF_PUSHZ, V3D_QPU_PF_PUSHN, V3D_QPU_PF_PUSHC, }; enum v3d_qpu_uf { V3D_QPU_UF_NONE, V3D_QPU_UF_ANDZ, V3D_QPU_UF_ANDNZ, V3D_QPU_UF_NORNZ, V3D_QPU_UF_NORZ, V3D_QPU_UF_ANDN, V3D_QPU_UF_ANDNN, V3D_QPU_UF_NORNN, V3D_QPU_UF_NORN, V3D_QPU_UF_ANDC, V3D_QPU_UF_ANDNC, V3D_QPU_UF_NORNC, V3D_QPU_UF_NORC, }; enum v3d_qpu_waddr { V3D_QPU_WADDR_R0 = 0, V3D_QPU_WADDR_R1 = 1, V3D_QPU_WADDR_R2 = 2, V3D_QPU_WADDR_R3 = 3, V3D_QPU_WADDR_R4 = 4, V3D_QPU_WADDR_R5 = 5, /* 6 is reserved, but note 3.2.2.8: "Result Writes" */ V3D_QPU_WADDR_NOP = 6, V3D_QPU_WADDR_TLB = 7, V3D_QPU_WADDR_TLBU = 8, V3D_QPU_WADDR_TMU = 9, V3D_QPU_WADDR_TMUL = 10, V3D_QPU_WADDR_TMUD = 11, V3D_QPU_WADDR_TMUA = 12, V3D_QPU_WADDR_TMUAU = 13, V3D_QPU_WADDR_VPM = 14, V3D_QPU_WADDR_VPMU = 15, V3D_QPU_WADDR_SYNC = 16, V3D_QPU_WADDR_SYNCU = 17, V3D_QPU_WADDR_SYNCB = 18, V3D_QPU_WADDR_RECIP = 19, V3D_QPU_WADDR_RSQRT = 20, V3D_QPU_WADDR_EXP = 21, V3D_QPU_WADDR_LOG = 22, V3D_QPU_WADDR_SIN = 23, V3D_QPU_WADDR_RSQRT2 = 24, V3D_QPU_WADDR_TMUC = 32, V3D_QPU_WADDR_TMUS = 33, V3D_QPU_WADDR_TMUT = 34, V3D_QPU_WADDR_TMUR = 35, V3D_QPU_WADDR_TMUI = 36, V3D_QPU_WADDR_TMUB = 37, V3D_QPU_WADDR_TMUDREF = 38, V3D_QPU_WADDR_TMUOFF = 39, V3D_QPU_WADDR_TMUSCM = 40, V3D_QPU_WADDR_TMUSF = 41, V3D_QPU_WADDR_TMUSLOD = 42, V3D_QPU_WADDR_TMUHS = 43, V3D_QPU_WADDR_TMUHSCM = 44, V3D_QPU_WADDR_TMUHSF = 45, V3D_QPU_WADDR_TMUHSLOD = 46, V3D_QPU_WADDR_R5REP = 55, }; struct v3d_qpu_flags { enum v3d_qpu_cond ac, mc; enum v3d_qpu_pf apf, mpf; enum v3d_qpu_uf auf, muf; }; enum v3d_qpu_add_op { V3D_QPU_A_FADD, V3D_QPU_A_FADDNF, V3D_QPU_A_VFPACK, V3D_QPU_A_ADD, V3D_QPU_A_SUB, V3D_QPU_A_FSUB, V3D_QPU_A_MIN, V3D_QPU_A_MAX, V3D_QPU_A_UMIN, V3D_QPU_A_UMAX, V3D_QPU_A_SHL, V3D_QPU_A_SHR, V3D_QPU_A_ASR, V3D_QPU_A_ROR, V3D_QPU_A_FMIN, V3D_QPU_A_FMAX, V3D_QPU_A_VFMIN, V3D_QPU_A_AND, V3D_QPU_A_OR, V3D_QPU_A_XOR, V3D_QPU_A_VADD, V3D_QPU_A_VSUB, V3D_QPU_A_NOT, V3D_QPU_A_NEG, V3D_QPU_A_FLAPUSH, V3D_QPU_A_FLBPUSH, V3D_QPU_A_FLPOP, V3D_QPU_A_RECIP, V3D_QPU_A_SETMSF, V3D_QPU_A_SETREVF, V3D_QPU_A_NOP, V3D_QPU_A_TIDX, V3D_QPU_A_EIDX, V3D_QPU_A_LR, V3D_QPU_A_VFLA, V3D_QPU_A_VFLNA, V3D_QPU_A_VFLB, V3D_QPU_A_VFLNB, V3D_QPU_A_FXCD, V3D_QPU_A_XCD, V3D_QPU_A_FYCD, V3D_QPU_A_YCD, V3D_QPU_A_MSF, V3D_QPU_A_REVF, V3D_QPU_A_VDWWT, V3D_QPU_A_IID, V3D_QPU_A_SAMPID, V3D_QPU_A_BARRIERID, V3D_QPU_A_TMUWT, V3D_QPU_A_VPMSETUP, V3D_QPU_A_VPMWT, V3D_QPU_A_LDVPMV_IN, V3D_QPU_A_LDVPMV_OUT, V3D_QPU_A_LDVPMD_IN, V3D_QPU_A_LDVPMD_OUT, V3D_QPU_A_LDVPMP, V3D_QPU_A_RSQRT, V3D_QPU_A_EXP, V3D_QPU_A_LOG, V3D_QPU_A_SIN, V3D_QPU_A_RSQRT2, V3D_QPU_A_LDVPMG_IN, V3D_QPU_A_LDVPMG_OUT, V3D_QPU_A_FCMP, V3D_QPU_A_VFMAX, V3D_QPU_A_FROUND, V3D_QPU_A_FTOIN, V3D_QPU_A_FTRUNC, V3D_QPU_A_FTOIZ, V3D_QPU_A_FFLOOR, V3D_QPU_A_FTOUZ, V3D_QPU_A_FCEIL, V3D_QPU_A_FTOC, V3D_QPU_A_FDX, V3D_QPU_A_FDY, V3D_QPU_A_STVPMV, V3D_QPU_A_STVPMD, V3D_QPU_A_STVPMP, V3D_QPU_A_ITOF, V3D_QPU_A_CLZ, V3D_QPU_A_UTOF, }; enum v3d_qpu_mul_op { V3D_QPU_M_ADD, V3D_QPU_M_SUB, V3D_QPU_M_UMUL24, V3D_QPU_M_VFMUL, V3D_QPU_M_SMUL24, V3D_QPU_M_MULTOP, V3D_QPU_M_FMOV, V3D_QPU_M_MOV, V3D_QPU_M_NOP, V3D_QPU_M_FMUL, }; enum v3d_qpu_output_pack { V3D_QPU_PACK_NONE, /** * Convert to 16-bit float, put in low 16 bits of destination leaving * high unmodified. */ V3D_QPU_PACK_L, /** * Convert to 16-bit float, put in high 16 bits of destination leaving * low unmodified. */ V3D_QPU_PACK_H, }; enum v3d_qpu_input_unpack { /** * No-op input unpacking. Note that this enum's value doesn't match * the packed QPU instruction value of the field (we use 0 so that the * default on new instruction creation is no-op). */ V3D_QPU_UNPACK_NONE, /** Absolute value. Only available for some operations. */ V3D_QPU_UNPACK_ABS, /** Convert low 16 bits from 16-bit float to 32-bit float. */ V3D_QPU_UNPACK_L, /** Convert high 16 bits from 16-bit float to 32-bit float. */ V3D_QPU_UNPACK_H, /** Convert to 16f and replicate it to the high bits. */ V3D_QPU_UNPACK_REPLICATE_32F_16, /** Replicate low 16 bits to high */ V3D_QPU_UNPACK_REPLICATE_L_16, /** Replicate high 16 bits to low */ V3D_QPU_UNPACK_REPLICATE_H_16, /** Swap high and low 16 bits */ V3D_QPU_UNPACK_SWAP_16, }; enum v3d_qpu_mux { V3D_QPU_MUX_R0, V3D_QPU_MUX_R1, V3D_QPU_MUX_R2, V3D_QPU_MUX_R3, V3D_QPU_MUX_R4, V3D_QPU_MUX_R5, V3D_QPU_MUX_A, V3D_QPU_MUX_B, }; struct v3d_qpu_alu_instr { struct { enum v3d_qpu_add_op op; enum v3d_qpu_mux a, b; uint8_t waddr; bool magic_write; enum v3d_qpu_output_pack output_pack; enum v3d_qpu_input_unpack a_unpack; enum v3d_qpu_input_unpack b_unpack; } add; struct { enum v3d_qpu_mul_op op; enum v3d_qpu_mux a, b; uint8_t waddr; bool magic_write; enum v3d_qpu_output_pack output_pack; enum v3d_qpu_input_unpack a_unpack; enum v3d_qpu_input_unpack b_unpack; } mul; }; enum v3d_qpu_branch_cond { V3D_QPU_BRANCH_COND_ALWAYS, V3D_QPU_BRANCH_COND_A0, V3D_QPU_BRANCH_COND_NA0, V3D_QPU_BRANCH_COND_ALLA, V3D_QPU_BRANCH_COND_ANYNA, V3D_QPU_BRANCH_COND_ANYA, V3D_QPU_BRANCH_COND_ALLNA, }; enum v3d_qpu_msfign { /** Ignore multisample flags when determining branch condition. */ V3D_QPU_MSFIGN_NONE, /** * If no multisample flags are set in the lane (a pixel in the FS, a * vertex in the VS), ignore the lane's condition when computing the * branch condition. */ V3D_QPU_MSFIGN_P, /** * If no multisample flags are set in a 2x2 quad in the FS, ignore the * quad's a/b conditions. */ V3D_QPU_MSFIGN_Q, }; enum v3d_qpu_branch_dest { V3D_QPU_BRANCH_DEST_ABS, V3D_QPU_BRANCH_DEST_REL, V3D_QPU_BRANCH_DEST_LINK_REG, V3D_QPU_BRANCH_DEST_REGFILE, }; struct v3d_qpu_branch_instr { enum v3d_qpu_branch_cond cond; enum v3d_qpu_msfign msfign; /** Selects how to compute the new IP if the branch is taken. */ enum v3d_qpu_branch_dest bdi; /** * Selects how to compute the new uniforms pointer if the branch is * taken. (ABS/REL implicitly load a uniform and use that) */ enum v3d_qpu_branch_dest bdu; /** * If set, then udest determines how the uniform stream will branch, * otherwise the uniform stream is left as is. */ bool ub; uint8_t raddr_a; uint32_t offset; }; enum v3d_qpu_instr_type { V3D_QPU_INSTR_TYPE_ALU, V3D_QPU_INSTR_TYPE_BRANCH, }; struct v3d_qpu_instr { enum v3d_qpu_instr_type type; struct v3d_qpu_sig sig; uint8_t sig_addr; bool sig_magic; /* If the signal writes to a magic address */ uint8_t raddr_a; uint8_t raddr_b; struct v3d_qpu_flags flags; union { struct v3d_qpu_alu_instr alu; struct v3d_qpu_branch_instr branch; }; }; const char *v3d_qpu_magic_waddr_name(enum v3d_qpu_waddr waddr); const char *v3d_qpu_add_op_name(enum v3d_qpu_add_op op); const char *v3d_qpu_mul_op_name(enum v3d_qpu_mul_op op); const char *v3d_qpu_cond_name(enum v3d_qpu_cond cond); const char *v3d_qpu_pf_name(enum v3d_qpu_pf pf); const char *v3d_qpu_uf_name(enum v3d_qpu_uf uf); const char *v3d_qpu_pack_name(enum v3d_qpu_output_pack pack); const char *v3d_qpu_unpack_name(enum v3d_qpu_input_unpack unpack); const char *v3d_qpu_branch_cond_name(enum v3d_qpu_branch_cond cond); const char *v3d_qpu_msfign_name(enum v3d_qpu_msfign msfign); enum v3d_qpu_cond v3d_qpu_cond_invert(enum v3d_qpu_cond cond) ATTRIBUTE_CONST; bool v3d_qpu_add_op_has_dst(enum v3d_qpu_add_op op); bool v3d_qpu_mul_op_has_dst(enum v3d_qpu_mul_op op); int v3d_qpu_add_op_num_src(enum v3d_qpu_add_op op); int v3d_qpu_mul_op_num_src(enum v3d_qpu_mul_op op); bool v3d_qpu_sig_pack(const struct v3d_device_info *devinfo, const struct v3d_qpu_sig *sig, uint32_t *packed_sig); bool v3d_qpu_sig_unpack(const struct v3d_device_info *devinfo, uint32_t packed_sig, struct v3d_qpu_sig *sig); bool v3d_qpu_flags_pack(const struct v3d_device_info *devinfo, const struct v3d_qpu_flags *cond, uint32_t *packed_cond); bool v3d_qpu_flags_unpack(const struct v3d_device_info *devinfo, uint32_t packed_cond, struct v3d_qpu_flags *cond); bool v3d_qpu_small_imm_pack(const struct v3d_device_info *devinfo, uint32_t value, uint32_t *packed_small_immediate); bool v3d_qpu_small_imm_unpack(const struct v3d_device_info *devinfo, uint32_t packed_small_immediate, uint32_t *small_immediate); bool v3d_qpu_instr_pack(const struct v3d_device_info *devinfo, const struct v3d_qpu_instr *instr, uint64_t *packed_instr); bool v3d_qpu_instr_unpack(const struct v3d_device_info *devinfo, uint64_t packed_instr, struct v3d_qpu_instr *instr); bool v3d_qpu_magic_waddr_is_sfu(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; bool v3d_qpu_magic_waddr_is_tmu(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; bool v3d_qpu_magic_waddr_is_tlb(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; bool v3d_qpu_magic_waddr_is_vpm(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; bool v3d_qpu_magic_waddr_is_tsy(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; bool v3d_qpu_magic_waddr_loads_unif(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; bool v3d_qpu_uses_tlb(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_uses_sfu(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_writes_tmu(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_writes_r3(const struct v3d_device_info *devinfo, const struct v3d_qpu_instr *instr) ATTRIBUTE_CONST; bool v3d_qpu_writes_r4(const struct v3d_device_info *devinfo, const struct v3d_qpu_instr *instr) ATTRIBUTE_CONST; bool v3d_qpu_writes_r5(const struct v3d_device_info *devinfo, const struct v3d_qpu_instr *instr) ATTRIBUTE_CONST; bool v3d_qpu_waits_on_tmu(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_uses_mux(const struct v3d_qpu_instr *inst, enum v3d_qpu_mux mux); bool v3d_qpu_uses_vpm(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_reads_vpm(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_writes_vpm(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_reads_flags(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_writes_flags(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_sig_writes_address(const struct v3d_device_info *devinfo, const struct v3d_qpu_sig *sig) ATTRIBUTE_CONST; bool v3d_qpu_unpacks_f32(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; bool v3d_qpu_unpacks_f16(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST; #endif