| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824 |
- /*
- * Copyright (c) 2017 Lima Project
- *
- * 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, sub license,
- * 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 NON-INFRINGEMENT. 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.
- *
- */
-
- #include "util/ralloc.h"
- #include "util/u_half.h"
- #include "util/bitscan.h"
-
- #include "ppir.h"
- #include "codegen.h"
- #include "lima_context.h"
-
- static unsigned encode_swizzle(uint8_t *swizzle, int shift, int dest_shift)
- {
- unsigned ret = 0;
- for (int i = 0; i < 4; i++)
- ret |= ((swizzle[i] + shift) & 0x3) << ((i + dest_shift) * 2);
- return ret;
- }
-
- static int get_scl_reg_index(ppir_src *src, int component)
- {
- int ret = ppir_target_get_src_reg_index(src);
- ret += src->swizzle[component];
- return ret;
- }
-
- static void ppir_codegen_encode_varying(ppir_node *node, void *code)
- {
- ppir_codegen_field_varying *f = code;
- ppir_load_node *load = ppir_node_to_load(node);
- ppir_dest *dest = &load->dest;
- int index = ppir_target_get_dest_reg_index(dest);
- int num_components = load->num_components;
-
- if (node->op != ppir_op_load_coords_reg) {
- assert(node->op == ppir_op_load_varying ||
- node->op == ppir_op_load_coords ||
- node->op == ppir_op_load_fragcoord ||
- node->op == ppir_op_load_pointcoord ||
- node->op == ppir_op_load_frontface);
-
- f->imm.dest = index >> 2;
- f->imm.mask = dest->write_mask << (index & 0x3);
-
- int alignment = num_components == 3 ? 3 : num_components - 1;
- f->imm.alignment = alignment;
-
- if (load->num_src) {
- index = ppir_target_get_src_reg_index(&load->src);
- f->imm.offset_vector = index >> 2;
- f->imm.offset_scalar = index & 0x3;
- } else
- f->imm.offset_vector = 0xf;
-
- if (alignment == 3)
- f->imm.index = load->index >> 2;
- else
- f->imm.index = load->index >> alignment;
-
- switch (node->op) {
- case ppir_op_load_fragcoord:
- f->imm.source_type = 2;
- f->imm.perspective = 3;
- break;
- case ppir_op_load_pointcoord:
- f->imm.source_type = 3;
- break;
- case ppir_op_load_frontface:
- f->imm.source_type = 3;
- f->imm.perspective = 1;
- break;
- case ppir_op_load_coords:
- /* num_components == 3 implies cubemap as we don't support 3D textures */
- f->imm.source_type = num_components == 3 ? 2 : 0;
- break;
- default:
- break;
- }
- }
- else { /* node->op == ppir_op_load_coords_reg */
- f->reg.dest = index >> 2;
- f->reg.mask = dest->write_mask << (index & 0x3);
-
- if (load->num_src) {
- /* num_components == 3 implies cubemap as we don't support 3D textures */
- if (num_components == 3) {
- f->reg.source_type = 2;
- f->reg.perspective = 1;
- } else {
- f->reg.source_type = 1;
- }
- ppir_src *src = &load->src;
- index = ppir_target_get_src_reg_index(src);
- f->reg.source = index >> 2;
- f->reg.negate = src->negate;
- f->reg.absolute = src->absolute;
- f->reg.swizzle = encode_swizzle(src->swizzle, index & 0x3, 0);
- }
- }
- }
-
- static void ppir_codegen_encode_texld(ppir_node *node, void *code)
- {
- ppir_codegen_field_sampler *f = code;
- ppir_load_texture_node *ldtex = ppir_node_to_load_texture(node);
-
- f->index = ldtex->sampler;
-
- f->lod_bias_en = ldtex->lod_bias_en;
- f->explicit_lod = ldtex->explicit_lod;
- if (ldtex->lod_bias_en)
- ppir_target_get_src_reg_index(&ldtex->lod_bias);
-
- switch (ldtex->sampler_dim) {
- case GLSL_SAMPLER_DIM_2D:
- case GLSL_SAMPLER_DIM_RECT:
- case GLSL_SAMPLER_DIM_EXTERNAL:
- f->type = ppir_codegen_sampler_type_2d;
- break;
- case GLSL_SAMPLER_DIM_CUBE:
- f->type = ppir_codegen_sampler_type_cube;
- break;
- default:
- break;
- }
-
- f->offset_en = 0;
- f->unknown_2 = 0x39001;
- }
-
- static void ppir_codegen_encode_uniform(ppir_node *node, void *code)
- {
- ppir_codegen_field_uniform *f = code;
- ppir_load_node *load = ppir_node_to_load(node);
-
- switch (node->op) {
- case ppir_op_load_uniform:
- f->source = ppir_codegen_uniform_src_uniform;
- break;
- case ppir_op_load_temp:
- f->source = ppir_codegen_uniform_src_temporary;
- break;
- default:
- assert(0);
- }
-
- /* Uniforms are always aligned to vec4 boundary */
- f->alignment = 2;
- f->index = load->index;
-
- if (load->num_src) {
- f->offset_en = 1;
- f->offset_reg = ppir_target_get_src_reg_index(&load->src);
- }
- }
-
- static unsigned shift_to_op(int shift)
- {
- assert(shift >= -3 && shift <= 3);
- return shift < 0 ? shift + 8 : shift;
- }
-
- static void ppir_codegen_encode_vec_mul(ppir_node *node, void *code)
- {
- ppir_codegen_field_vec4_mul *f = code;
- ppir_alu_node *alu = ppir_node_to_alu(node);
-
- ppir_dest *dest = &alu->dest;
- int dest_shift = 0;
- if (dest->type != ppir_target_pipeline) {
- int index = ppir_target_get_dest_reg_index(dest);
- dest_shift = index & 0x3;
- f->dest = index >> 2;
- f->mask = dest->write_mask << dest_shift;
- }
- f->dest_modifier = dest->modifier;
-
- switch (node->op) {
- case ppir_op_mul:
- f->op = shift_to_op(alu->shift);
- break;
- case ppir_op_mov:
- case ppir_op_store_color:
- f->op = ppir_codegen_vec4_mul_op_mov;
- break;
- case ppir_op_max:
- f->op = ppir_codegen_vec4_mul_op_max;
- break;
- case ppir_op_min:
- f->op = ppir_codegen_vec4_mul_op_min;
- break;
- case ppir_op_and:
- f->op = ppir_codegen_vec4_mul_op_and;
- break;
- case ppir_op_or:
- f->op = ppir_codegen_vec4_mul_op_or;
- break;
- case ppir_op_xor:
- f->op = ppir_codegen_vec4_mul_op_xor;
- break;
- case ppir_op_gt:
- f->op = ppir_codegen_vec4_mul_op_gt;
- break;
- case ppir_op_ge:
- f->op = ppir_codegen_vec4_mul_op_ge;
- break;
- case ppir_op_eq:
- f->op = ppir_codegen_vec4_mul_op_eq;
- break;
- case ppir_op_ne:
- f->op = ppir_codegen_vec4_mul_op_ne;
- break;
- case ppir_op_not:
- f->op = ppir_codegen_vec4_mul_op_not;
- break;
- default:
- break;
- }
-
- ppir_src *src = alu->src;
- int index = ppir_target_get_src_reg_index(src);
- f->arg0_source = index >> 2;
- f->arg0_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift);
- f->arg0_absolute = src->absolute;
- f->arg0_negate = src->negate;
-
- if (alu->num_src == 2) {
- src = alu->src + 1;
- index = ppir_target_get_src_reg_index(src);
- f->arg1_source = index >> 2;
- f->arg1_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift);
- f->arg1_absolute = src->absolute;
- f->arg1_negate = src->negate;
- }
- }
-
- static void ppir_codegen_encode_scl_mul(ppir_node *node, void *code)
- {
- ppir_codegen_field_float_mul *f = code;
- ppir_alu_node *alu = ppir_node_to_alu(node);
-
- ppir_dest *dest = &alu->dest;
- int dest_component = ffs(dest->write_mask) - 1;
- assert(dest_component >= 0);
-
- if (dest->type != ppir_target_pipeline) {
- f->dest = ppir_target_get_dest_reg_index(dest) + dest_component;
- f->output_en = true;
- }
- f->dest_modifier = dest->modifier;
-
- switch (node->op) {
- case ppir_op_mul:
- f->op = shift_to_op(alu->shift);
- break;
- case ppir_op_mov:
- f->op = ppir_codegen_float_mul_op_mov;
- break;
- case ppir_op_sel_cond:
- f->op = ppir_codegen_float_mul_op_mov;
- break;
- case ppir_op_max:
- f->op = ppir_codegen_float_mul_op_max;
- break;
- case ppir_op_min:
- f->op = ppir_codegen_float_mul_op_min;
- break;
- case ppir_op_and:
- f->op = ppir_codegen_float_mul_op_and;
- break;
- case ppir_op_or:
- f->op = ppir_codegen_float_mul_op_or;
- break;
- case ppir_op_xor:
- f->op = ppir_codegen_float_mul_op_xor;
- break;
- case ppir_op_gt:
- f->op = ppir_codegen_float_mul_op_gt;
- break;
- case ppir_op_ge:
- f->op = ppir_codegen_float_mul_op_ge;
- break;
- case ppir_op_eq:
- f->op = ppir_codegen_float_mul_op_eq;
- break;
- case ppir_op_ne:
- f->op = ppir_codegen_float_mul_op_ne;
- break;
- case ppir_op_not:
- f->op = ppir_codegen_float_mul_op_not;
- break;
- default:
- break;
- }
-
- ppir_src *src = alu->src;
- f->arg0_source = get_scl_reg_index(src, dest_component);
- f->arg0_absolute = src->absolute;
- f->arg0_negate = src->negate;
-
- if (alu->num_src == 2) {
- src = alu->src + 1;
- f->arg1_source = get_scl_reg_index(src, dest_component);
- f->arg1_absolute = src->absolute;
- f->arg1_negate = src->negate;
- }
- }
-
- static void ppir_codegen_encode_vec_add(ppir_node *node, void *code)
- {
- ppir_codegen_field_vec4_acc *f = code;
- ppir_alu_node *alu = ppir_node_to_alu(node);
-
- ppir_dest *dest = &alu->dest;
- int index = ppir_target_get_dest_reg_index(dest);
- int dest_shift = index & 0x3;
- f->dest = index >> 2;
- f->mask = dest->write_mask << dest_shift;
- f->dest_modifier = dest->modifier;
-
- switch (node->op) {
- case ppir_op_add:
- f->op = ppir_codegen_vec4_acc_op_add;
- break;
- case ppir_op_mov:
- case ppir_op_store_color:
- f->op = ppir_codegen_vec4_acc_op_mov;
- break;
- case ppir_op_sum3:
- f->op = ppir_codegen_vec4_acc_op_sum3;
- dest_shift = 0;
- break;
- case ppir_op_sum4:
- f->op = ppir_codegen_vec4_acc_op_sum4;
- dest_shift = 0;
- break;
- case ppir_op_floor:
- f->op = ppir_codegen_vec4_acc_op_floor;
- break;
- case ppir_op_ceil:
- f->op = ppir_codegen_vec4_acc_op_ceil;
- break;
- case ppir_op_fract:
- f->op = ppir_codegen_vec4_acc_op_fract;
- break;
- case ppir_op_gt:
- f->op = ppir_codegen_vec4_acc_op_gt;
- break;
- case ppir_op_ge:
- f->op = ppir_codegen_vec4_acc_op_ge;
- break;
- case ppir_op_eq:
- f->op = ppir_codegen_vec4_acc_op_eq;
- break;
- case ppir_op_ne:
- f->op = ppir_codegen_vec4_acc_op_ne;
- break;
- case ppir_op_select:
- f->op = ppir_codegen_vec4_acc_op_sel;
- break;
- case ppir_op_max:
- f->op = ppir_codegen_vec4_acc_op_max;
- break;
- case ppir_op_min:
- f->op = ppir_codegen_vec4_acc_op_min;
- break;
- case ppir_op_ddx:
- f->op = ppir_codegen_vec4_acc_op_dFdx;
- break;
- case ppir_op_ddy:
- f->op = ppir_codegen_vec4_acc_op_dFdy;
- break;
- default:
- break;
- }
-
- ppir_src *src = node->op == ppir_op_select ? alu->src + 1 : alu->src;
- index = ppir_target_get_src_reg_index(src);
-
- if (src->type == ppir_target_pipeline &&
- src->pipeline == ppir_pipeline_reg_vmul)
- f->mul_in = true;
- else
- f->arg0_source = index >> 2;
-
- f->arg0_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift);
- f->arg0_absolute = src->absolute;
- f->arg0_negate = src->negate;
-
- if (++src < alu->src + alu->num_src) {
- index = ppir_target_get_src_reg_index(src);
- f->arg1_source = index >> 2;
- f->arg1_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift);
- f->arg1_absolute = src->absolute;
- f->arg1_negate = src->negate;
- }
- }
-
- static void ppir_codegen_encode_scl_add(ppir_node *node, void *code)
- {
- ppir_codegen_field_float_acc *f = code;
- ppir_alu_node *alu = ppir_node_to_alu(node);
-
- ppir_dest *dest = &alu->dest;
- int dest_component = ffs(dest->write_mask) - 1;
- assert(dest_component >= 0);
-
- f->dest = ppir_target_get_dest_reg_index(dest) + dest_component;
- f->output_en = true;
- f->dest_modifier = dest->modifier;
-
- switch (node->op) {
- case ppir_op_add:
- f->op = shift_to_op(alu->shift);
- break;
- case ppir_op_mov:
- f->op = ppir_codegen_float_acc_op_mov;
- break;
- case ppir_op_max:
- f->op = ppir_codegen_float_acc_op_max;
- break;
- case ppir_op_min:
- f->op = ppir_codegen_float_acc_op_min;
- break;
- case ppir_op_floor:
- f->op = ppir_codegen_float_acc_op_floor;
- break;
- case ppir_op_ceil:
- f->op = ppir_codegen_float_acc_op_ceil;
- break;
- case ppir_op_fract:
- f->op = ppir_codegen_float_acc_op_fract;
- break;
- case ppir_op_gt:
- f->op = ppir_codegen_float_acc_op_gt;
- break;
- case ppir_op_ge:
- f->op = ppir_codegen_float_acc_op_ge;
- break;
- case ppir_op_eq:
- f->op = ppir_codegen_float_acc_op_eq;
- break;
- case ppir_op_ne:
- f->op = ppir_codegen_float_acc_op_ne;
- break;
- case ppir_op_select:
- f->op = ppir_codegen_float_acc_op_sel;
- break;
- case ppir_op_ddx:
- f->op = ppir_codegen_float_acc_op_dFdx;
- break;
- case ppir_op_ddy:
- f->op = ppir_codegen_float_acc_op_dFdy;
- break;
- default:
- break;
- }
-
- ppir_src *src = node->op == ppir_op_select ? alu->src + 1: alu->src;
- if (src->type == ppir_target_pipeline &&
- src->pipeline == ppir_pipeline_reg_fmul)
- f->mul_in = true;
- else
- f->arg0_source = get_scl_reg_index(src, dest_component);
- f->arg0_absolute = src->absolute;
- f->arg0_negate = src->negate;
-
- if (++src < alu->src + alu->num_src) {
- f->arg1_source = get_scl_reg_index(src, dest_component);
- f->arg1_absolute = src->absolute;
- f->arg1_negate = src->negate;
- }
- }
-
- static void ppir_codegen_encode_combine(ppir_node *node, void *code)
- {
- ppir_codegen_field_combine *f = code;
- ppir_alu_node *alu = ppir_node_to_alu(node);
-
- switch (node->op) {
- case ppir_op_rsqrt:
- case ppir_op_log2:
- case ppir_op_exp2:
- case ppir_op_rcp:
- case ppir_op_sqrt:
- case ppir_op_sin:
- case ppir_op_cos:
- {
- f->scalar.dest_vec = false;
- f->scalar.arg1_en = false;
-
- ppir_dest *dest = &alu->dest;
- int dest_component = ffs(dest->write_mask) - 1;
- assert(dest_component >= 0);
- f->scalar.dest = ppir_target_get_dest_reg_index(dest) + dest_component;
- f->scalar.dest_modifier = dest->modifier;
-
- ppir_src *src = alu->src;
- f->scalar.arg0_src = get_scl_reg_index(src, dest_component);
- f->scalar.arg0_absolute = src->absolute;
- f->scalar.arg0_negate = src->negate;
-
- switch (node->op) {
- case ppir_op_rsqrt:
- f->scalar.op = ppir_codegen_combine_scalar_op_rsqrt;
- break;
- case ppir_op_log2:
- f->scalar.op = ppir_codegen_combine_scalar_op_log2;
- break;
- case ppir_op_exp2:
- f->scalar.op = ppir_codegen_combine_scalar_op_exp2;
- break;
- case ppir_op_rcp:
- f->scalar.op = ppir_codegen_combine_scalar_op_rcp;
- break;
- case ppir_op_sqrt:
- f->scalar.op = ppir_codegen_combine_scalar_op_sqrt;
- break;
- case ppir_op_sin:
- f->scalar.op = ppir_codegen_combine_scalar_op_sin;
- break;
- case ppir_op_cos:
- f->scalar.op = ppir_codegen_combine_scalar_op_cos;
- break;
- default:
- break;
- }
- }
- default:
- break;
- }
- }
-
- static void ppir_codegen_encode_store_temp(ppir_node *node, void *code)
- {
- assert(node->op == ppir_op_store_temp);
-
- ppir_codegen_field_temp_write *f = code;
- ppir_store_node *snode = ppir_node_to_store(node);
- int num_components = snode->num_components;
-
- f->temp_write.dest = 0x03; // 11 - temporary
- f->temp_write.source = snode->src.reg->index;
-
- int alignment = num_components == 4 ? 2 : num_components - 1;
- f->temp_write.alignment = alignment;
- f->temp_write.index = snode->index << (2 - alignment);
-
- f->temp_write.offset_reg = snode->index >> 2;
- }
-
- static void ppir_codegen_encode_const(ppir_const *constant, uint16_t *code)
- {
- for (int i = 0; i < constant->num; i++)
- code[i] = util_float_to_half(constant->value[i].f);
- }
-
- static void ppir_codegen_encode_discard(ppir_node *node, void *code)
- {
- ppir_codegen_field_branch *b = code;
- assert(node->op == ppir_op_discard);
-
- b->discard.word0 = PPIR_CODEGEN_DISCARD_WORD0;
- b->discard.word1 = PPIR_CODEGEN_DISCARD_WORD1;
- b->discard.word2 = PPIR_CODEGEN_DISCARD_WORD2;
- }
-
- static void ppir_codegen_encode_branch(ppir_node *node, void *code)
- {
- ppir_codegen_field_branch *b = code;
- ppir_branch_node *branch;
- ppir_instr *target_instr;
- ppir_block *target;
- if (node->op == ppir_op_discard) {
- ppir_codegen_encode_discard(node, code);
- return;
- }
-
- assert(node->op == ppir_op_branch);
- branch = ppir_node_to_branch(node);
-
- b->branch.unknown_0 = 0x0;
- b->branch.unknown_1 = 0x0;
-
- if (branch->num_src == 2) {
- b->branch.arg0_source = get_scl_reg_index(&branch->src[0], 0);
- b->branch.arg1_source = get_scl_reg_index(&branch->src[1], 0);
- b->branch.cond_gt = branch->cond_gt;
- b->branch.cond_eq = branch->cond_eq;
- b->branch.cond_lt = branch->cond_lt;
- } else if (branch->num_src == 0) {
- /* Unconditional branch */
- b->branch.arg0_source = 0;
- b->branch.arg1_source = 0;
- b->branch.cond_gt = true;
- b->branch.cond_eq = true;
- b->branch.cond_lt = true;
- } else {
- assert(false);
- }
-
- target = branch->target;
- while (list_is_empty(&target->instr_list)) {
- if (!target->list.next)
- break;
- target = LIST_ENTRY(ppir_block, target->list.next, list);
- }
-
- assert(!list_is_empty(&target->instr_list));
-
- target_instr = list_first_entry(&target->instr_list, ppir_instr, list);
- b->branch.target = target_instr->offset - node->instr->offset;
- b->branch.next_count = target_instr->encode_size;
- }
-
- typedef void (*ppir_codegen_instr_slot_encode_func)(ppir_node *, void *);
-
- static const ppir_codegen_instr_slot_encode_func
- ppir_codegen_encode_slot[PPIR_INSTR_SLOT_NUM] = {
- [PPIR_INSTR_SLOT_VARYING] = ppir_codegen_encode_varying,
- [PPIR_INSTR_SLOT_TEXLD] = ppir_codegen_encode_texld,
- [PPIR_INSTR_SLOT_UNIFORM] = ppir_codegen_encode_uniform,
- [PPIR_INSTR_SLOT_ALU_VEC_MUL] = ppir_codegen_encode_vec_mul,
- [PPIR_INSTR_SLOT_ALU_SCL_MUL] = ppir_codegen_encode_scl_mul,
- [PPIR_INSTR_SLOT_ALU_VEC_ADD] = ppir_codegen_encode_vec_add,
- [PPIR_INSTR_SLOT_ALU_SCL_ADD] = ppir_codegen_encode_scl_add,
- [PPIR_INSTR_SLOT_ALU_COMBINE] = ppir_codegen_encode_combine,
- [PPIR_INSTR_SLOT_STORE_TEMP] = ppir_codegen_encode_store_temp,
- [PPIR_INSTR_SLOT_BRANCH] = ppir_codegen_encode_branch,
- };
-
- static const int ppir_codegen_field_size[] = {
- 34, 62, 41, 43, 30, 44, 31, 30, 41, 73
- };
-
- static inline int align_to_word(int size)
- {
- return ((size + 0x1f) >> 5);
- }
-
- static int get_instr_encode_size(ppir_instr *instr)
- {
- int size = 0;
-
- for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
- if (instr->slots[i])
- size += ppir_codegen_field_size[i];
- }
-
- for (int i = 0; i < 2; i++) {
- if (instr->constant[i].num)
- size += 64;
- }
-
- return align_to_word(size) + 1;
- }
-
- static void bitcopy(void *dst, int dst_offset, void *src, int src_size)
- {
- int off1 = dst_offset & 0x1f;
- uint32_t *cpy_dst = dst, *cpy_src = src;
-
- cpy_dst += (dst_offset >> 5);
-
- if (off1) {
- int off2 = 32 - off1;
- int cpy_size = 0;
- while (1) {
- *cpy_dst |= *cpy_src << off1;
- cpy_dst++;
-
- cpy_size += off2;
- if (cpy_size >= src_size)
- break;
-
- *cpy_dst |= *cpy_src >> off2;
- cpy_src++;
-
- cpy_size += off1;
- if (cpy_size >= src_size)
- break;
- }
- }
- else
- memcpy(cpy_dst, cpy_src, align_to_word(src_size) * 4);
- }
-
- static int encode_instr(ppir_instr *instr, void *code, void *last_code)
- {
- int size = 0;
- ppir_codegen_ctrl *ctrl = code;
-
- for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
- if (instr->slots[i]) {
- /* max field size (73), align to dword */
- uint8_t output[12] = {0};
-
- ppir_codegen_encode_slot[i](instr->slots[i], output);
- bitcopy(ctrl + 1, size, output, ppir_codegen_field_size[i]);
-
- size += ppir_codegen_field_size[i];
- ctrl->fields |= 1 << i;
- }
- }
-
- if (instr->slots[PPIR_INSTR_SLOT_TEXLD])
- ctrl->sync = true;
-
- if (instr->slots[PPIR_INSTR_SLOT_ALU_VEC_ADD]) {
- ppir_node *node = instr->slots[PPIR_INSTR_SLOT_ALU_VEC_ADD];
- if (node->op == ppir_op_ddx || node->op == ppir_op_ddy)
- ctrl->sync = true;
- }
-
- if (instr->slots[PPIR_INSTR_SLOT_ALU_SCL_ADD]) {
- ppir_node *node = instr->slots[PPIR_INSTR_SLOT_ALU_SCL_ADD];
- if (node->op == ppir_op_ddx || node->op == ppir_op_ddy)
- ctrl->sync = true;
- }
-
- for (int i = 0; i < 2; i++) {
- if (instr->constant[i].num) {
- uint16_t output[4] = {0};
-
- ppir_codegen_encode_const(instr->constant + i, output);
- bitcopy(ctrl + 1, size, output, instr->constant[i].num * 16);
-
- size += 64;
- ctrl->fields |= 1 << (ppir_codegen_field_shift_vec4_const_0 + i);
- }
- }
-
- size = align_to_word(size) + 1;
-
- ctrl->count = size;
- if (instr->is_end)
- ctrl->stop = true;
-
- if (last_code) {
- ppir_codegen_ctrl *last_ctrl = last_code;
- last_ctrl->next_count = size;
- last_ctrl->prefetch = true;
- }
-
- return size;
- }
-
- static void ppir_codegen_print_prog(ppir_compiler *comp)
- {
- uint32_t *prog = comp->prog->shader;
- unsigned offset = 0;
-
- printf("========ppir codegen========\n");
- list_for_each_entry(ppir_block, block, &comp->block_list, list) {
- list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
- printf("%03d (@%6d): ", instr->index, instr->offset);
- int n = prog[0] & 0x1f;
- for (int i = 0; i < n; i++) {
- if (i && i % 6 == 0)
- printf("\n ");
- printf("%08x ", prog[i]);
- }
- printf("\n");
- ppir_disassemble_instr(prog, offset);
- prog += n;
- offset += n;
- }
- }
- printf("-----------------------\n");
- }
-
- bool ppir_codegen_prog(ppir_compiler *comp)
- {
- int size = 0;
- list_for_each_entry(ppir_block, block, &comp->block_list, list) {
- list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
- instr->offset = size;
- instr->encode_size = get_instr_encode_size(instr);
- size += instr->encode_size;
- }
- }
-
- uint32_t *prog = rzalloc_size(comp->prog, size * sizeof(uint32_t));
- if (!prog)
- return false;
-
- uint32_t *code = prog, *last_code = NULL;
- list_for_each_entry(ppir_block, block, &comp->block_list, list) {
- list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
- int offset = encode_instr(instr, code, last_code);
- last_code = code;
- code += offset;
- }
- }
-
- comp->prog->shader = prog;
- comp->prog->shader_size = size * sizeof(uint32_t);
-
- if (lima_debug & LIMA_DEBUG_PP)
- ppir_codegen_print_prog(comp);
-
- return true;
- }
|