Path: blob/21.2-virgl/src/freedreno/isa/encode.c
4564 views
/*1* Copyright © 2020 Google, Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*/2223#include "util/log.h"2425#include "ir3/ir3.h"26#include "ir3/ir3_shader.h"27#include "ir3/instr-a3xx.h" // TODO move opc's and other useful things to ir3-instr.h or so2829#include "isa.h"3031struct bitset_params;3233struct encode_state {34struct ir3_compiler *compiler;3536/**37* The instruction which is currently being encoded38*/39struct ir3_instruction *instr;40};4142/*43* Helpers defining how to map from ir3_instruction/ir3_register/etc to fields44* to be encoded:45*/4647static inline bool48extract_SRC1_R(struct ir3_instruction *instr)49{50if (instr->nop) {51assert(!instr->repeat);52return instr->nop & 0x1;53}54return !!(instr->srcs[0]->flags & IR3_REG_R);55}5657static inline bool58extract_SRC2_R(struct ir3_instruction *instr)59{60if (instr->nop) {61assert(!instr->repeat);62return (instr->nop >> 1) & 0x1;63}64/* src2 does not appear in all cat2, but SRC2_R does (for nop encoding) */65if (instr->srcs_count > 1)66return !!(instr->srcs[1]->flags & IR3_REG_R);67return 0;68}6970static inline opc_t71__instruction_case(struct encode_state *s, struct ir3_instruction *instr)72{73/*74* Temporary hack.. the new world doesn't map opcodes directly to hw75* encoding, so there are some cases where we need to fixup the opc76* to match what the encoder expects. Eventually this will go away77* once we completely transition away from the packed-struct encoding/78* decoding and split up things which are logically different79* instructions80*/81if (instr->opc == OPC_B) {82switch (instr->cat0.brtype) {83case BRANCH_PLAIN:84return OPC_BR;85case BRANCH_OR:86return OPC_BRAO;87case BRANCH_AND:88return OPC_BRAA;89case BRANCH_CONST:90return OPC_BRAC;91case BRANCH_ANY:92return OPC_BANY;93case BRANCH_ALL:94return OPC_BALL;95case BRANCH_X:96return OPC_BRAX;97}98} else if (instr->opc == OPC_MOV) {99struct ir3_register *src = instr->srcs[0];100if (src->flags & IR3_REG_IMMED) {101return OPC_MOV_IMMED;102} if (src->flags & IR3_REG_RELATIV) {103if (src->flags & IR3_REG_CONST) {104return OPC_MOV_RELCONST;105} else {106return OPC_MOV_RELGPR;107}108} else if (src->flags & IR3_REG_CONST) {109return OPC_MOV_CONST;110} else {111return OPC_MOV_GPR;112}113} else if (instr->opc == OPC_DEMOTE) {114return OPC_KILL;115} else if ((instr->block->shader->compiler->gpu_id > 600) &&116is_atomic(instr->opc) && (instr->flags & IR3_INSTR_G)) {117return instr->opc - OPC_ATOMIC_ADD + OPC_ATOMIC_B_ADD;118} else if (s->compiler->gpu_id >= 600) {119if (instr->opc == OPC_RESINFO) {120return OPC_RESINFO_B;121} else if (instr->opc == OPC_LDIB) {122return OPC_LDIB_B;123} else if (instr->opc == OPC_STIB) {124return OPC_STIB_B;125}126}127return instr->opc;128}129130static inline unsigned131extract_ABSNEG(struct ir3_register *reg)132{133// TODO generate enums for this:134if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)) {135if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) {136return 3; // ABSNEG137} else {138return 1; // NEG139}140} else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) {141return 2; // ABS142} else {143return 0;144}145}146147/**148* This is a bit messy, to deal with the fact that the optional "s2en"149* src is the first src, shifting everything else up by one.150*151* TODO revisit this once legacy 'packed struct' encoding is gone152*/153static inline struct ir3_register *154extract_cat5_SRC(struct ir3_instruction *instr, unsigned n)155{156if (instr->flags & IR3_INSTR_S2EN) {157n++;158}159if (n < instr->srcs_count)160return instr->srcs[n];161return NULL;162}163164static inline bool165extract_cat5_FULL(struct ir3_instruction *instr)166{167struct ir3_register *reg = extract_cat5_SRC(instr, 0);168/* some cat5 have zero src regs, in which case 'FULL' is false */169if (!reg)170return false;171return !(reg->flags & IR3_REG_HALF);172}173174static inline cat5_desc_mode_t175extract_cat5_DESC_MODE(struct ir3_instruction *instr)176{177assert(instr->flags & (IR3_INSTR_S2EN | IR3_INSTR_B));178if (instr->flags & IR3_INSTR_S2EN) {179if (instr->flags & IR3_INSTR_B) {180if (instr->flags & IR3_INSTR_A1EN) {181return CAT5_BINDLESS_A1_UNIFORM;182} else if (instr->flags & IR3_INSTR_NONUNIF) {183return CAT5_BINDLESS_NONUNIFORM;184} else {185return CAT5_BINDLESS_UNIFORM;186}187} else {188/* TODO: This should probably be CAT5_UNIFORM, at least on a6xx,189* as this is what the blob does and it is presumably faster, but190* first we should confirm it is actually nonuniform and figure191* out when the whole descriptor mode mechanism was introduced.192*/193return CAT5_NONUNIFORM;194}195assert(!(instr->cat5.samp | instr->cat5.tex));196} else if (instr->flags & IR3_INSTR_B) {197if (instr->flags & IR3_INSTR_A1EN) {198return CAT5_BINDLESS_A1_IMM;199} else {200return CAT5_BINDLESS_IMM;201}202}203return 0;204}205206static inline unsigned207extract_cat6_DESC_MODE(struct ir3_instruction *instr)208{209struct ir3_register *ssbo = instr->srcs[0];210if (ssbo->flags & IR3_REG_IMMED) {211return 0; // todo enum212} else if (instr->flags & IR3_INSTR_NONUNIF) {213return 2; // todo enum214} else {215return 1; // todo enum216}217}218219/**220* This is a bit messy, for legacy (pre-bindless) atomic instructions,221* the .g (global) variety have SSBO as first src and everything else222* shifted up by one.223*224* TODO revisit this once legacy 'packed struct' encoding is gone225*/226static inline struct ir3_register *227extract_cat6_SRC(struct ir3_instruction *instr, unsigned n)228{229if (instr->flags & IR3_INSTR_G) {230n++;231}232assert(n < instr->srcs_count);233return instr->srcs[n];234}235236typedef enum {237REG_MULITSRC_IMMED,238REG_MULTISRC_IMMED_FLUT_FULL,239REG_MULTISRC_IMMED_FLUT_HALF,240REG_MULTISRC_GPR,241REG_MULTISRC_CONST,242REG_MULTISRC_RELATIVE_GPR,243REG_MULTISRC_RELATIVE_CONST,244} reg_multisrc_t;245246static inline reg_multisrc_t247__multisrc_case(struct encode_state *s, struct ir3_register *reg)248{249if (reg->flags & IR3_REG_IMMED) {250assert(opc_cat(s->instr->opc) == 2);251if (ir3_cat2_int(s->instr->opc)) {252return REG_MULITSRC_IMMED;253} else if (reg->flags & IR3_REG_HALF) {254return REG_MULTISRC_IMMED_FLUT_HALF;255} else {256return REG_MULTISRC_IMMED_FLUT_FULL;257}258} else if (reg->flags & IR3_REG_RELATIV) {259if (reg->flags & IR3_REG_CONST) {260return REG_MULTISRC_RELATIVE_CONST;261} else {262return REG_MULTISRC_RELATIVE_GPR;263}264} else if (reg->flags & IR3_REG_CONST) {265return REG_MULTISRC_CONST;266} else {267return REG_MULTISRC_GPR;268}269}270271typedef enum {272REG_CAT3_SRC_GPR,273REG_CAT3_SRC_CONST_OR_IMMED,274REG_CAT3_SRC_RELATIVE_GPR,275REG_CAT3_SRC_RELATIVE_CONST,276} reg_cat3_src_t;277278static inline reg_cat3_src_t279__cat3_src_case(struct encode_state *s, struct ir3_register *reg)280{281if (reg->flags & IR3_REG_RELATIV) {282if (reg->flags & IR3_REG_CONST) {283return REG_CAT3_SRC_RELATIVE_CONST;284} else {285return REG_CAT3_SRC_RELATIVE_GPR;286}287} else if (reg->flags & (IR3_REG_CONST | IR3_REG_IMMED)) {288return REG_CAT3_SRC_CONST_OR_IMMED;289} else {290return REG_CAT3_SRC_GPR;291}292}293294#include "encode.h"295296297void *298isa_assemble(struct ir3_shader_variant *v)299{300uint64_t *ptr, *instrs;301const struct ir3_info *info = &v->info;302struct ir3 *shader = v->ir;303304ptr = instrs = rzalloc_size(v, info->size);305306foreach_block (block, &shader->block_list) {307foreach_instr (instr, &block->instr_list) {308struct encode_state s = {309.compiler = shader->compiler,310.instr = instr,311};312313*(instrs++) = encode__instruction(&s, NULL, instr);314}315}316317return ptr;318}319320321