1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (c) 2017 Lima Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 13bf215546Sopenharmony_ci * of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "util/ralloc.h" 26bf215546Sopenharmony_ci#include "util/half_float.h" 27bf215546Sopenharmony_ci#include "util/bitscan.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "ppir.h" 30bf215546Sopenharmony_ci#include "codegen.h" 31bf215546Sopenharmony_ci#include "lima_context.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_cistatic unsigned encode_swizzle(uint8_t *swizzle, int shift, int dest_shift) 34bf215546Sopenharmony_ci{ 35bf215546Sopenharmony_ci unsigned ret = 0; 36bf215546Sopenharmony_ci for (int i = 0; i < 4; i++) 37bf215546Sopenharmony_ci ret |= ((swizzle[i] + shift) & 0x3) << ((i + dest_shift) * 2); 38bf215546Sopenharmony_ci return ret; 39bf215546Sopenharmony_ci} 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistatic int get_scl_reg_index(ppir_src *src, int component) 42bf215546Sopenharmony_ci{ 43bf215546Sopenharmony_ci int ret = ppir_target_get_src_reg_index(src); 44bf215546Sopenharmony_ci ret += src->swizzle[component]; 45bf215546Sopenharmony_ci return ret; 46bf215546Sopenharmony_ci} 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic void ppir_codegen_encode_varying(ppir_node *node, void *code) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci ppir_codegen_field_varying *f = code; 51bf215546Sopenharmony_ci ppir_load_node *load = ppir_node_to_load(node); 52bf215546Sopenharmony_ci ppir_dest *dest = &load->dest; 53bf215546Sopenharmony_ci int index = ppir_target_get_dest_reg_index(dest); 54bf215546Sopenharmony_ci int num_components = load->num_components; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci if (node->op != ppir_op_load_coords_reg) { 57bf215546Sopenharmony_ci assert(node->op == ppir_op_load_varying || 58bf215546Sopenharmony_ci node->op == ppir_op_load_coords || 59bf215546Sopenharmony_ci node->op == ppir_op_load_fragcoord || 60bf215546Sopenharmony_ci node->op == ppir_op_load_pointcoord || 61bf215546Sopenharmony_ci node->op == ppir_op_load_frontface); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci f->imm.dest = index >> 2; 64bf215546Sopenharmony_ci f->imm.mask = dest->write_mask << (index & 0x3); 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci int alignment = num_components == 3 ? 3 : num_components - 1; 67bf215546Sopenharmony_ci f->imm.alignment = alignment; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci if (load->num_src) { 70bf215546Sopenharmony_ci index = ppir_target_get_src_reg_index(&load->src); 71bf215546Sopenharmony_ci f->imm.offset_vector = index >> 2; 72bf215546Sopenharmony_ci f->imm.offset_scalar = index & 0x3; 73bf215546Sopenharmony_ci } else 74bf215546Sopenharmony_ci f->imm.offset_vector = 0xf; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci if (alignment == 3) 77bf215546Sopenharmony_ci f->imm.index = load->index >> 2; 78bf215546Sopenharmony_ci else 79bf215546Sopenharmony_ci f->imm.index = load->index >> alignment; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci switch (node->op) { 82bf215546Sopenharmony_ci case ppir_op_load_fragcoord: 83bf215546Sopenharmony_ci f->imm.source_type = 2; 84bf215546Sopenharmony_ci f->imm.perspective = 3; 85bf215546Sopenharmony_ci break; 86bf215546Sopenharmony_ci case ppir_op_load_pointcoord: 87bf215546Sopenharmony_ci f->imm.source_type = 3; 88bf215546Sopenharmony_ci break; 89bf215546Sopenharmony_ci case ppir_op_load_frontface: 90bf215546Sopenharmony_ci f->imm.source_type = 3; 91bf215546Sopenharmony_ci f->imm.perspective = 1; 92bf215546Sopenharmony_ci break; 93bf215546Sopenharmony_ci case ppir_op_load_coords: 94bf215546Sopenharmony_ci if (load->sampler_dim == GLSL_SAMPLER_DIM_CUBE) 95bf215546Sopenharmony_ci f->imm.source_type = 2; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci switch (load->perspective) { 98bf215546Sopenharmony_ci case ppir_perspective_none: 99bf215546Sopenharmony_ci f->imm.perspective = 0; 100bf215546Sopenharmony_ci break; 101bf215546Sopenharmony_ci case ppir_perspective_z: 102bf215546Sopenharmony_ci f->imm.perspective = 2; 103bf215546Sopenharmony_ci break; 104bf215546Sopenharmony_ci case ppir_perspective_w: 105bf215546Sopenharmony_ci f->imm.perspective = 3; 106bf215546Sopenharmony_ci break; 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci break; 109bf215546Sopenharmony_ci default: 110bf215546Sopenharmony_ci break; 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci } 113bf215546Sopenharmony_ci else { /* node->op == ppir_op_load_coords_reg */ 114bf215546Sopenharmony_ci f->reg.dest = index >> 2; 115bf215546Sopenharmony_ci f->reg.mask = dest->write_mask << (index & 0x3); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (load->num_src) { 118bf215546Sopenharmony_ci if (load->sampler_dim == GLSL_SAMPLER_DIM_CUBE) { 119bf215546Sopenharmony_ci f->reg.source_type = 2; 120bf215546Sopenharmony_ci f->reg.perspective = 1; 121bf215546Sopenharmony_ci } else { 122bf215546Sopenharmony_ci f->reg.source_type = 1; 123bf215546Sopenharmony_ci switch (load->perspective) { 124bf215546Sopenharmony_ci case ppir_perspective_none: 125bf215546Sopenharmony_ci f->reg.perspective = 0; 126bf215546Sopenharmony_ci break; 127bf215546Sopenharmony_ci case ppir_perspective_z: 128bf215546Sopenharmony_ci f->reg.perspective = 2; 129bf215546Sopenharmony_ci break; 130bf215546Sopenharmony_ci case ppir_perspective_w: 131bf215546Sopenharmony_ci f->reg.perspective = 3; 132bf215546Sopenharmony_ci break; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci ppir_src *src = &load->src; 136bf215546Sopenharmony_ci index = ppir_target_get_src_reg_index(src); 137bf215546Sopenharmony_ci f->reg.source = index >> 2; 138bf215546Sopenharmony_ci f->reg.negate = src->negate; 139bf215546Sopenharmony_ci f->reg.absolute = src->absolute; 140bf215546Sopenharmony_ci f->reg.swizzle = encode_swizzle(src->swizzle, index & 0x3, 0); 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci } 143bf215546Sopenharmony_ci} 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_cistatic void ppir_codegen_encode_texld(ppir_node *node, void *code) 146bf215546Sopenharmony_ci{ 147bf215546Sopenharmony_ci ppir_codegen_field_sampler *f = code; 148bf215546Sopenharmony_ci ppir_load_texture_node *ldtex = ppir_node_to_load_texture(node); 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci f->index = ldtex->sampler; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci f->lod_bias_en = ldtex->lod_bias_en; 153bf215546Sopenharmony_ci f->explicit_lod = ldtex->explicit_lod; 154bf215546Sopenharmony_ci if (ldtex->lod_bias_en) 155bf215546Sopenharmony_ci f->lod_bias = ppir_target_get_src_reg_index(&ldtex->src[1]); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci switch (ldtex->sampler_dim) { 158bf215546Sopenharmony_ci case GLSL_SAMPLER_DIM_2D: 159bf215546Sopenharmony_ci case GLSL_SAMPLER_DIM_3D: 160bf215546Sopenharmony_ci case GLSL_SAMPLER_DIM_RECT: 161bf215546Sopenharmony_ci case GLSL_SAMPLER_DIM_EXTERNAL: 162bf215546Sopenharmony_ci f->type = ppir_codegen_sampler_type_generic; 163bf215546Sopenharmony_ci break; 164bf215546Sopenharmony_ci case GLSL_SAMPLER_DIM_CUBE: 165bf215546Sopenharmony_ci f->type = ppir_codegen_sampler_type_cube; 166bf215546Sopenharmony_ci break; 167bf215546Sopenharmony_ci default: 168bf215546Sopenharmony_ci break; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci f->offset_en = 0; 172bf215546Sopenharmony_ci f->unknown_2 = 0x39001; 173bf215546Sopenharmony_ci} 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_cistatic void ppir_codegen_encode_uniform(ppir_node *node, void *code) 176bf215546Sopenharmony_ci{ 177bf215546Sopenharmony_ci ppir_codegen_field_uniform *f = code; 178bf215546Sopenharmony_ci ppir_load_node *load = ppir_node_to_load(node); 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci switch (node->op) { 181bf215546Sopenharmony_ci case ppir_op_load_uniform: 182bf215546Sopenharmony_ci f->source = ppir_codegen_uniform_src_uniform; 183bf215546Sopenharmony_ci break; 184bf215546Sopenharmony_ci case ppir_op_load_temp: 185bf215546Sopenharmony_ci f->source = ppir_codegen_uniform_src_temporary; 186bf215546Sopenharmony_ci break; 187bf215546Sopenharmony_ci default: 188bf215546Sopenharmony_ci assert(0); 189bf215546Sopenharmony_ci } 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci /* Uniforms are always aligned to vec4 boundary */ 192bf215546Sopenharmony_ci f->alignment = 2; 193bf215546Sopenharmony_ci f->index = load->index; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci if (load->num_src) { 196bf215546Sopenharmony_ci f->offset_en = 1; 197bf215546Sopenharmony_ci f->offset_reg = ppir_target_get_src_reg_index(&load->src); 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci} 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_cistatic ppir_codegen_outmod ppir_codegen_get_outmod(ppir_outmod outmod) 202bf215546Sopenharmony_ci{ 203bf215546Sopenharmony_ci switch (outmod) { 204bf215546Sopenharmony_ci case ppir_outmod_none: 205bf215546Sopenharmony_ci return ppir_codegen_outmod_none; 206bf215546Sopenharmony_ci case ppir_outmod_clamp_fraction: 207bf215546Sopenharmony_ci return ppir_codegen_outmod_clamp_fraction; 208bf215546Sopenharmony_ci case ppir_outmod_clamp_positive: 209bf215546Sopenharmony_ci return ppir_codegen_outmod_clamp_positive; 210bf215546Sopenharmony_ci case ppir_outmod_round: 211bf215546Sopenharmony_ci return ppir_codegen_outmod_round; 212bf215546Sopenharmony_ci default: 213bf215546Sopenharmony_ci unreachable("invalid ppir_outmod"); 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_cistatic unsigned shift_to_op(int shift) 218bf215546Sopenharmony_ci{ 219bf215546Sopenharmony_ci assert(shift >= -3 && shift <= 3); 220bf215546Sopenharmony_ci return shift < 0 ? shift + 8 : shift; 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_cistatic void ppir_codegen_encode_vec_mul(ppir_node *node, void *code) 224bf215546Sopenharmony_ci{ 225bf215546Sopenharmony_ci ppir_codegen_field_vec4_mul *f = code; 226bf215546Sopenharmony_ci ppir_alu_node *alu = ppir_node_to_alu(node); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci ppir_dest *dest = &alu->dest; 229bf215546Sopenharmony_ci int dest_shift = 0; 230bf215546Sopenharmony_ci if (dest->type != ppir_target_pipeline) { 231bf215546Sopenharmony_ci int index = ppir_target_get_dest_reg_index(dest); 232bf215546Sopenharmony_ci dest_shift = index & 0x3; 233bf215546Sopenharmony_ci f->dest = index >> 2; 234bf215546Sopenharmony_ci f->mask = dest->write_mask << dest_shift; 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci f->dest_modifier = ppir_codegen_get_outmod(dest->modifier); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci switch (node->op) { 239bf215546Sopenharmony_ci case ppir_op_mul: 240bf215546Sopenharmony_ci f->op = shift_to_op(alu->shift); 241bf215546Sopenharmony_ci break; 242bf215546Sopenharmony_ci case ppir_op_mov: 243bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_mov; 244bf215546Sopenharmony_ci break; 245bf215546Sopenharmony_ci case ppir_op_max: 246bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_max; 247bf215546Sopenharmony_ci break; 248bf215546Sopenharmony_ci case ppir_op_min: 249bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_min; 250bf215546Sopenharmony_ci break; 251bf215546Sopenharmony_ci case ppir_op_and: 252bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_and; 253bf215546Sopenharmony_ci break; 254bf215546Sopenharmony_ci case ppir_op_or: 255bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_or; 256bf215546Sopenharmony_ci break; 257bf215546Sopenharmony_ci case ppir_op_xor: 258bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_xor; 259bf215546Sopenharmony_ci break; 260bf215546Sopenharmony_ci case ppir_op_gt: 261bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_gt; 262bf215546Sopenharmony_ci break; 263bf215546Sopenharmony_ci case ppir_op_ge: 264bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_ge; 265bf215546Sopenharmony_ci break; 266bf215546Sopenharmony_ci case ppir_op_eq: 267bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_eq; 268bf215546Sopenharmony_ci break; 269bf215546Sopenharmony_ci case ppir_op_ne: 270bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_ne; 271bf215546Sopenharmony_ci break; 272bf215546Sopenharmony_ci case ppir_op_not: 273bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_mul_op_not; 274bf215546Sopenharmony_ci break; 275bf215546Sopenharmony_ci default: 276bf215546Sopenharmony_ci break; 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci ppir_src *src = alu->src; 280bf215546Sopenharmony_ci int index = ppir_target_get_src_reg_index(src); 281bf215546Sopenharmony_ci f->arg0_source = index >> 2; 282bf215546Sopenharmony_ci f->arg0_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift); 283bf215546Sopenharmony_ci f->arg0_absolute = src->absolute; 284bf215546Sopenharmony_ci f->arg0_negate = src->negate; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci if (alu->num_src == 2) { 287bf215546Sopenharmony_ci src = alu->src + 1; 288bf215546Sopenharmony_ci index = ppir_target_get_src_reg_index(src); 289bf215546Sopenharmony_ci f->arg1_source = index >> 2; 290bf215546Sopenharmony_ci f->arg1_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift); 291bf215546Sopenharmony_ci f->arg1_absolute = src->absolute; 292bf215546Sopenharmony_ci f->arg1_negate = src->negate; 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci} 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_cistatic void ppir_codegen_encode_scl_mul(ppir_node *node, void *code) 297bf215546Sopenharmony_ci{ 298bf215546Sopenharmony_ci ppir_codegen_field_float_mul *f = code; 299bf215546Sopenharmony_ci ppir_alu_node *alu = ppir_node_to_alu(node); 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci ppir_dest *dest = &alu->dest; 302bf215546Sopenharmony_ci int dest_component = ffs(dest->write_mask) - 1; 303bf215546Sopenharmony_ci assert(dest_component >= 0); 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci if (dest->type != ppir_target_pipeline) { 306bf215546Sopenharmony_ci f->dest = ppir_target_get_dest_reg_index(dest) + dest_component; 307bf215546Sopenharmony_ci f->output_en = true; 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci f->dest_modifier = ppir_codegen_get_outmod(dest->modifier); 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci switch (node->op) { 312bf215546Sopenharmony_ci case ppir_op_mul: 313bf215546Sopenharmony_ci f->op = shift_to_op(alu->shift); 314bf215546Sopenharmony_ci break; 315bf215546Sopenharmony_ci case ppir_op_mov: 316bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_mov; 317bf215546Sopenharmony_ci break; 318bf215546Sopenharmony_ci case ppir_op_max: 319bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_max; 320bf215546Sopenharmony_ci break; 321bf215546Sopenharmony_ci case ppir_op_min: 322bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_min; 323bf215546Sopenharmony_ci break; 324bf215546Sopenharmony_ci case ppir_op_and: 325bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_and; 326bf215546Sopenharmony_ci break; 327bf215546Sopenharmony_ci case ppir_op_or: 328bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_or; 329bf215546Sopenharmony_ci break; 330bf215546Sopenharmony_ci case ppir_op_xor: 331bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_xor; 332bf215546Sopenharmony_ci break; 333bf215546Sopenharmony_ci case ppir_op_gt: 334bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_gt; 335bf215546Sopenharmony_ci break; 336bf215546Sopenharmony_ci case ppir_op_ge: 337bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_ge; 338bf215546Sopenharmony_ci break; 339bf215546Sopenharmony_ci case ppir_op_eq: 340bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_eq; 341bf215546Sopenharmony_ci break; 342bf215546Sopenharmony_ci case ppir_op_ne: 343bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_ne; 344bf215546Sopenharmony_ci break; 345bf215546Sopenharmony_ci case ppir_op_not: 346bf215546Sopenharmony_ci f->op = ppir_codegen_float_mul_op_not; 347bf215546Sopenharmony_ci break; 348bf215546Sopenharmony_ci default: 349bf215546Sopenharmony_ci break; 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci ppir_src *src = alu->src; 353bf215546Sopenharmony_ci f->arg0_source = get_scl_reg_index(src, dest_component); 354bf215546Sopenharmony_ci f->arg0_absolute = src->absolute; 355bf215546Sopenharmony_ci f->arg0_negate = src->negate; 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci if (alu->num_src == 2) { 358bf215546Sopenharmony_ci src = alu->src + 1; 359bf215546Sopenharmony_ci f->arg1_source = get_scl_reg_index(src, dest_component); 360bf215546Sopenharmony_ci f->arg1_absolute = src->absolute; 361bf215546Sopenharmony_ci f->arg1_negate = src->negate; 362bf215546Sopenharmony_ci } 363bf215546Sopenharmony_ci} 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_cistatic void ppir_codegen_encode_vec_add(ppir_node *node, void *code) 366bf215546Sopenharmony_ci{ 367bf215546Sopenharmony_ci ppir_codegen_field_vec4_acc *f = code; 368bf215546Sopenharmony_ci ppir_alu_node *alu = ppir_node_to_alu(node); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci ppir_dest *dest = &alu->dest; 371bf215546Sopenharmony_ci int index = ppir_target_get_dest_reg_index(dest); 372bf215546Sopenharmony_ci int dest_shift = index & 0x3; 373bf215546Sopenharmony_ci f->dest = index >> 2; 374bf215546Sopenharmony_ci f->mask = dest->write_mask << dest_shift; 375bf215546Sopenharmony_ci f->dest_modifier = ppir_codegen_get_outmod(dest->modifier); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci switch (node->op) { 378bf215546Sopenharmony_ci case ppir_op_add: 379bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_add; 380bf215546Sopenharmony_ci break; 381bf215546Sopenharmony_ci case ppir_op_mov: 382bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_mov; 383bf215546Sopenharmony_ci break; 384bf215546Sopenharmony_ci case ppir_op_sum3: 385bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_sum3; 386bf215546Sopenharmony_ci dest_shift = 0; 387bf215546Sopenharmony_ci break; 388bf215546Sopenharmony_ci case ppir_op_sum4: 389bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_sum4; 390bf215546Sopenharmony_ci dest_shift = 0; 391bf215546Sopenharmony_ci break; 392bf215546Sopenharmony_ci case ppir_op_floor: 393bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_floor; 394bf215546Sopenharmony_ci break; 395bf215546Sopenharmony_ci case ppir_op_ceil: 396bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_ceil; 397bf215546Sopenharmony_ci break; 398bf215546Sopenharmony_ci case ppir_op_fract: 399bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_fract; 400bf215546Sopenharmony_ci break; 401bf215546Sopenharmony_ci case ppir_op_gt: 402bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_gt; 403bf215546Sopenharmony_ci break; 404bf215546Sopenharmony_ci case ppir_op_ge: 405bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_ge; 406bf215546Sopenharmony_ci break; 407bf215546Sopenharmony_ci case ppir_op_eq: 408bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_eq; 409bf215546Sopenharmony_ci break; 410bf215546Sopenharmony_ci case ppir_op_ne: 411bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_ne; 412bf215546Sopenharmony_ci break; 413bf215546Sopenharmony_ci case ppir_op_select: 414bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_sel; 415bf215546Sopenharmony_ci break; 416bf215546Sopenharmony_ci case ppir_op_max: 417bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_max; 418bf215546Sopenharmony_ci break; 419bf215546Sopenharmony_ci case ppir_op_min: 420bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_min; 421bf215546Sopenharmony_ci break; 422bf215546Sopenharmony_ci case ppir_op_ddx: 423bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_dFdx; 424bf215546Sopenharmony_ci break; 425bf215546Sopenharmony_ci case ppir_op_ddy: 426bf215546Sopenharmony_ci f->op = ppir_codegen_vec4_acc_op_dFdy; 427bf215546Sopenharmony_ci break; 428bf215546Sopenharmony_ci default: 429bf215546Sopenharmony_ci break; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci ppir_src *src = node->op == ppir_op_select ? alu->src + 1 : alu->src; 433bf215546Sopenharmony_ci index = ppir_target_get_src_reg_index(src); 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci if (src->type == ppir_target_pipeline && 436bf215546Sopenharmony_ci src->pipeline == ppir_pipeline_reg_vmul) 437bf215546Sopenharmony_ci f->mul_in = true; 438bf215546Sopenharmony_ci else 439bf215546Sopenharmony_ci f->arg0_source = index >> 2; 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci f->arg0_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift); 442bf215546Sopenharmony_ci f->arg0_absolute = src->absolute; 443bf215546Sopenharmony_ci f->arg0_negate = src->negate; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci if (++src < alu->src + alu->num_src) { 446bf215546Sopenharmony_ci index = ppir_target_get_src_reg_index(src); 447bf215546Sopenharmony_ci f->arg1_source = index >> 2; 448bf215546Sopenharmony_ci f->arg1_swizzle = encode_swizzle(src->swizzle, index & 0x3, dest_shift); 449bf215546Sopenharmony_ci f->arg1_absolute = src->absolute; 450bf215546Sopenharmony_ci f->arg1_negate = src->negate; 451bf215546Sopenharmony_ci } 452bf215546Sopenharmony_ci} 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_cistatic void ppir_codegen_encode_scl_add(ppir_node *node, void *code) 455bf215546Sopenharmony_ci{ 456bf215546Sopenharmony_ci ppir_codegen_field_float_acc *f = code; 457bf215546Sopenharmony_ci ppir_alu_node *alu = ppir_node_to_alu(node); 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci ppir_dest *dest = &alu->dest; 460bf215546Sopenharmony_ci int dest_component = ffs(dest->write_mask) - 1; 461bf215546Sopenharmony_ci assert(dest_component >= 0); 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci f->dest = ppir_target_get_dest_reg_index(dest) + dest_component; 464bf215546Sopenharmony_ci f->output_en = true; 465bf215546Sopenharmony_ci f->dest_modifier = ppir_codegen_get_outmod(dest->modifier); 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci switch (node->op) { 468bf215546Sopenharmony_ci case ppir_op_add: 469bf215546Sopenharmony_ci f->op = shift_to_op(alu->shift); 470bf215546Sopenharmony_ci break; 471bf215546Sopenharmony_ci case ppir_op_mov: 472bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_mov; 473bf215546Sopenharmony_ci break; 474bf215546Sopenharmony_ci case ppir_op_max: 475bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_max; 476bf215546Sopenharmony_ci break; 477bf215546Sopenharmony_ci case ppir_op_min: 478bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_min; 479bf215546Sopenharmony_ci break; 480bf215546Sopenharmony_ci case ppir_op_floor: 481bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_floor; 482bf215546Sopenharmony_ci break; 483bf215546Sopenharmony_ci case ppir_op_ceil: 484bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_ceil; 485bf215546Sopenharmony_ci break; 486bf215546Sopenharmony_ci case ppir_op_fract: 487bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_fract; 488bf215546Sopenharmony_ci break; 489bf215546Sopenharmony_ci case ppir_op_gt: 490bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_gt; 491bf215546Sopenharmony_ci break; 492bf215546Sopenharmony_ci case ppir_op_ge: 493bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_ge; 494bf215546Sopenharmony_ci break; 495bf215546Sopenharmony_ci case ppir_op_eq: 496bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_eq; 497bf215546Sopenharmony_ci break; 498bf215546Sopenharmony_ci case ppir_op_ne: 499bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_ne; 500bf215546Sopenharmony_ci break; 501bf215546Sopenharmony_ci case ppir_op_select: 502bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_sel; 503bf215546Sopenharmony_ci break; 504bf215546Sopenharmony_ci case ppir_op_ddx: 505bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_dFdx; 506bf215546Sopenharmony_ci break; 507bf215546Sopenharmony_ci case ppir_op_ddy: 508bf215546Sopenharmony_ci f->op = ppir_codegen_float_acc_op_dFdy; 509bf215546Sopenharmony_ci break; 510bf215546Sopenharmony_ci default: 511bf215546Sopenharmony_ci break; 512bf215546Sopenharmony_ci } 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci ppir_src *src = node->op == ppir_op_select ? alu->src + 1: alu->src; 515bf215546Sopenharmony_ci if (src->type == ppir_target_pipeline && 516bf215546Sopenharmony_ci src->pipeline == ppir_pipeline_reg_fmul) 517bf215546Sopenharmony_ci f->mul_in = true; 518bf215546Sopenharmony_ci else 519bf215546Sopenharmony_ci f->arg0_source = get_scl_reg_index(src, dest_component); 520bf215546Sopenharmony_ci f->arg0_absolute = src->absolute; 521bf215546Sopenharmony_ci f->arg0_negate = src->negate; 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci if (++src < alu->src + alu->num_src) { 524bf215546Sopenharmony_ci f->arg1_source = get_scl_reg_index(src, dest_component); 525bf215546Sopenharmony_ci f->arg1_absolute = src->absolute; 526bf215546Sopenharmony_ci f->arg1_negate = src->negate; 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci} 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_cistatic void ppir_codegen_encode_combine(ppir_node *node, void *code) 531bf215546Sopenharmony_ci{ 532bf215546Sopenharmony_ci ppir_codegen_field_combine *f = code; 533bf215546Sopenharmony_ci ppir_alu_node *alu = ppir_node_to_alu(node); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci switch (node->op) { 536bf215546Sopenharmony_ci case ppir_op_rsqrt: 537bf215546Sopenharmony_ci case ppir_op_log2: 538bf215546Sopenharmony_ci case ppir_op_exp2: 539bf215546Sopenharmony_ci case ppir_op_rcp: 540bf215546Sopenharmony_ci case ppir_op_sqrt: 541bf215546Sopenharmony_ci case ppir_op_sin: 542bf215546Sopenharmony_ci case ppir_op_cos: 543bf215546Sopenharmony_ci { 544bf215546Sopenharmony_ci f->scalar.dest_vec = false; 545bf215546Sopenharmony_ci f->scalar.arg1_en = false; 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci ppir_dest *dest = &alu->dest; 548bf215546Sopenharmony_ci int dest_component = ffs(dest->write_mask) - 1; 549bf215546Sopenharmony_ci assert(dest_component >= 0); 550bf215546Sopenharmony_ci f->scalar.dest = ppir_target_get_dest_reg_index(dest) + dest_component; 551bf215546Sopenharmony_ci f->scalar.dest_modifier = ppir_codegen_get_outmod(dest->modifier); 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci ppir_src *src = alu->src; 554bf215546Sopenharmony_ci f->scalar.arg0_src = get_scl_reg_index(src, dest_component); 555bf215546Sopenharmony_ci f->scalar.arg0_absolute = src->absolute; 556bf215546Sopenharmony_ci f->scalar.arg0_negate = src->negate; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci switch (node->op) { 559bf215546Sopenharmony_ci case ppir_op_rsqrt: 560bf215546Sopenharmony_ci f->scalar.op = ppir_codegen_combine_scalar_op_rsqrt; 561bf215546Sopenharmony_ci break; 562bf215546Sopenharmony_ci case ppir_op_log2: 563bf215546Sopenharmony_ci f->scalar.op = ppir_codegen_combine_scalar_op_log2; 564bf215546Sopenharmony_ci break; 565bf215546Sopenharmony_ci case ppir_op_exp2: 566bf215546Sopenharmony_ci f->scalar.op = ppir_codegen_combine_scalar_op_exp2; 567bf215546Sopenharmony_ci break; 568bf215546Sopenharmony_ci case ppir_op_rcp: 569bf215546Sopenharmony_ci f->scalar.op = ppir_codegen_combine_scalar_op_rcp; 570bf215546Sopenharmony_ci break; 571bf215546Sopenharmony_ci case ppir_op_sqrt: 572bf215546Sopenharmony_ci f->scalar.op = ppir_codegen_combine_scalar_op_sqrt; 573bf215546Sopenharmony_ci break; 574bf215546Sopenharmony_ci case ppir_op_sin: 575bf215546Sopenharmony_ci f->scalar.op = ppir_codegen_combine_scalar_op_sin; 576bf215546Sopenharmony_ci break; 577bf215546Sopenharmony_ci case ppir_op_cos: 578bf215546Sopenharmony_ci f->scalar.op = ppir_codegen_combine_scalar_op_cos; 579bf215546Sopenharmony_ci break; 580bf215546Sopenharmony_ci default: 581bf215546Sopenharmony_ci break; 582bf215546Sopenharmony_ci } 583bf215546Sopenharmony_ci break; 584bf215546Sopenharmony_ci } 585bf215546Sopenharmony_ci default: 586bf215546Sopenharmony_ci break; 587bf215546Sopenharmony_ci } 588bf215546Sopenharmony_ci} 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_cistatic void ppir_codegen_encode_store_temp(ppir_node *node, void *code) 591bf215546Sopenharmony_ci{ 592bf215546Sopenharmony_ci assert(node->op == ppir_op_store_temp); 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci ppir_codegen_field_temp_write *f = code; 595bf215546Sopenharmony_ci ppir_store_node *snode = ppir_node_to_store(node); 596bf215546Sopenharmony_ci int num_components = snode->num_components; 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci f->temp_write.dest = 0x03; // 11 - temporary 599bf215546Sopenharmony_ci f->temp_write.source = snode->src.reg->index; 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci int alignment = num_components == 4 ? 2 : num_components - 1; 602bf215546Sopenharmony_ci f->temp_write.alignment = alignment; 603bf215546Sopenharmony_ci f->temp_write.index = snode->index << (2 - alignment); 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci f->temp_write.offset_reg = snode->index >> 2; 606bf215546Sopenharmony_ci} 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_cistatic void ppir_codegen_encode_const(ppir_const *constant, uint16_t *code) 609bf215546Sopenharmony_ci{ 610bf215546Sopenharmony_ci for (int i = 0; i < constant->num; i++) 611bf215546Sopenharmony_ci code[i] = _mesa_float_to_half(constant->value[i].f); 612bf215546Sopenharmony_ci} 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_cistatic void ppir_codegen_encode_discard(ppir_node *node, void *code) 615bf215546Sopenharmony_ci{ 616bf215546Sopenharmony_ci ppir_codegen_field_branch *b = code; 617bf215546Sopenharmony_ci assert(node->op == ppir_op_discard); 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci b->discard.word0 = PPIR_CODEGEN_DISCARD_WORD0; 620bf215546Sopenharmony_ci b->discard.word1 = PPIR_CODEGEN_DISCARD_WORD1; 621bf215546Sopenharmony_ci b->discard.word2 = PPIR_CODEGEN_DISCARD_WORD2; 622bf215546Sopenharmony_ci} 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_cistatic void ppir_codegen_encode_branch(ppir_node *node, void *code) 625bf215546Sopenharmony_ci{ 626bf215546Sopenharmony_ci ppir_codegen_field_branch *b = code; 627bf215546Sopenharmony_ci ppir_branch_node *branch; 628bf215546Sopenharmony_ci ppir_instr *target_instr; 629bf215546Sopenharmony_ci ppir_block *target; 630bf215546Sopenharmony_ci if (node->op == ppir_op_discard) { 631bf215546Sopenharmony_ci ppir_codegen_encode_discard(node, code); 632bf215546Sopenharmony_ci return; 633bf215546Sopenharmony_ci } 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci assert(node->op == ppir_op_branch); 636bf215546Sopenharmony_ci branch = ppir_node_to_branch(node); 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci b->branch.unknown_0 = 0x0; 639bf215546Sopenharmony_ci b->branch.unknown_1 = 0x0; 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci if (branch->num_src == 2) { 642bf215546Sopenharmony_ci b->branch.arg0_source = get_scl_reg_index(&branch->src[0], 0); 643bf215546Sopenharmony_ci b->branch.arg1_source = get_scl_reg_index(&branch->src[1], 0); 644bf215546Sopenharmony_ci b->branch.cond_gt = branch->cond_gt; 645bf215546Sopenharmony_ci b->branch.cond_eq = branch->cond_eq; 646bf215546Sopenharmony_ci b->branch.cond_lt = branch->cond_lt; 647bf215546Sopenharmony_ci } else if (branch->num_src == 0) { 648bf215546Sopenharmony_ci /* Unconditional branch */ 649bf215546Sopenharmony_ci b->branch.arg0_source = 0; 650bf215546Sopenharmony_ci b->branch.arg1_source = 0; 651bf215546Sopenharmony_ci b->branch.cond_gt = true; 652bf215546Sopenharmony_ci b->branch.cond_eq = true; 653bf215546Sopenharmony_ci b->branch.cond_lt = true; 654bf215546Sopenharmony_ci } else { 655bf215546Sopenharmony_ci assert(false); 656bf215546Sopenharmony_ci } 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_ci target = branch->target; 659bf215546Sopenharmony_ci while (list_is_empty(&target->instr_list)) { 660bf215546Sopenharmony_ci if (!target->list.next) 661bf215546Sopenharmony_ci break; 662bf215546Sopenharmony_ci target = list_entry(target->list.next, ppir_block, list); 663bf215546Sopenharmony_ci } 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_ci assert(!list_is_empty(&target->instr_list)); 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci target_instr = list_first_entry(&target->instr_list, ppir_instr, list); 668bf215546Sopenharmony_ci b->branch.target = target_instr->offset - node->instr->offset; 669bf215546Sopenharmony_ci b->branch.next_count = target_instr->encode_size; 670bf215546Sopenharmony_ci} 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_citypedef void (*ppir_codegen_instr_slot_encode_func)(ppir_node *, void *); 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_cistatic const ppir_codegen_instr_slot_encode_func 675bf215546Sopenharmony_cippir_codegen_encode_slot[PPIR_INSTR_SLOT_NUM] = { 676bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_VARYING] = ppir_codegen_encode_varying, 677bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_TEXLD] = ppir_codegen_encode_texld, 678bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_UNIFORM] = ppir_codegen_encode_uniform, 679bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_VEC_MUL] = ppir_codegen_encode_vec_mul, 680bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_SCL_MUL] = ppir_codegen_encode_scl_mul, 681bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_VEC_ADD] = ppir_codegen_encode_vec_add, 682bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_SCL_ADD] = ppir_codegen_encode_scl_add, 683bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_COMBINE] = ppir_codegen_encode_combine, 684bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_STORE_TEMP] = ppir_codegen_encode_store_temp, 685bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_BRANCH] = ppir_codegen_encode_branch, 686bf215546Sopenharmony_ci}; 687bf215546Sopenharmony_ci 688bf215546Sopenharmony_cistatic const int ppir_codegen_field_size[] = { 689bf215546Sopenharmony_ci 34, 62, 41, 43, 30, 44, 31, 30, 41, 73 690bf215546Sopenharmony_ci}; 691bf215546Sopenharmony_ci 692bf215546Sopenharmony_cistatic inline int align_to_word(int size) 693bf215546Sopenharmony_ci{ 694bf215546Sopenharmony_ci return ((size + 0x1f) >> 5); 695bf215546Sopenharmony_ci} 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_cistatic int get_instr_encode_size(ppir_instr *instr) 698bf215546Sopenharmony_ci{ 699bf215546Sopenharmony_ci int size = 0; 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) { 702bf215546Sopenharmony_ci if (instr->slots[i]) 703bf215546Sopenharmony_ci size += ppir_codegen_field_size[i]; 704bf215546Sopenharmony_ci } 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci for (int i = 0; i < 2; i++) { 707bf215546Sopenharmony_ci if (instr->constant[i].num) 708bf215546Sopenharmony_ci size += 64; 709bf215546Sopenharmony_ci } 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci return align_to_word(size) + 1; 712bf215546Sopenharmony_ci} 713bf215546Sopenharmony_ci 714bf215546Sopenharmony_cistatic void bitcopy(void *dst, int dst_offset, void *src, int src_size) 715bf215546Sopenharmony_ci{ 716bf215546Sopenharmony_ci unsigned char *cpy_dst = dst, *cpy_src = src; 717bf215546Sopenharmony_ci int off1 = dst_offset & 0x07; 718bf215546Sopenharmony_ci 719bf215546Sopenharmony_ci cpy_dst += (dst_offset >> 3); 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci if (off1) { 722bf215546Sopenharmony_ci int off2 = 0x08 - off1; 723bf215546Sopenharmony_ci int cpy_size = 0; 724bf215546Sopenharmony_ci while (1) { 725bf215546Sopenharmony_ci *cpy_dst |= *cpy_src << off1; 726bf215546Sopenharmony_ci cpy_dst++; 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_ci cpy_size += off2; 729bf215546Sopenharmony_ci if (cpy_size >= src_size) 730bf215546Sopenharmony_ci break; 731bf215546Sopenharmony_ci 732bf215546Sopenharmony_ci *cpy_dst |= *cpy_src >> off2; 733bf215546Sopenharmony_ci cpy_src++; 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_ci cpy_size += off1; 736bf215546Sopenharmony_ci if (cpy_size >= src_size) 737bf215546Sopenharmony_ci break; 738bf215546Sopenharmony_ci } 739bf215546Sopenharmony_ci } 740bf215546Sopenharmony_ci else 741bf215546Sopenharmony_ci memcpy(cpy_dst, cpy_src, align_to_word(src_size) * 4); 742bf215546Sopenharmony_ci} 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_cistatic int encode_instr(ppir_instr *instr, void *code, void *last_code) 745bf215546Sopenharmony_ci{ 746bf215546Sopenharmony_ci int size = 0; 747bf215546Sopenharmony_ci ppir_codegen_ctrl *ctrl = code; 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) { 750bf215546Sopenharmony_ci if (instr->slots[i]) { 751bf215546Sopenharmony_ci /* max field size (73), align to dword */ 752bf215546Sopenharmony_ci uint8_t output[12] = {0}; 753bf215546Sopenharmony_ci 754bf215546Sopenharmony_ci ppir_codegen_encode_slot[i](instr->slots[i], output); 755bf215546Sopenharmony_ci bitcopy(ctrl + 1, size, output, ppir_codegen_field_size[i]); 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci size += ppir_codegen_field_size[i]; 758bf215546Sopenharmony_ci ctrl->fields |= 1 << i; 759bf215546Sopenharmony_ci } 760bf215546Sopenharmony_ci } 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci if (instr->slots[PPIR_INSTR_SLOT_TEXLD]) 763bf215546Sopenharmony_ci ctrl->sync = true; 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci if (instr->slots[PPIR_INSTR_SLOT_ALU_VEC_ADD]) { 766bf215546Sopenharmony_ci ppir_node *node = instr->slots[PPIR_INSTR_SLOT_ALU_VEC_ADD]; 767bf215546Sopenharmony_ci if (node->op == ppir_op_ddx || node->op == ppir_op_ddy) 768bf215546Sopenharmony_ci ctrl->sync = true; 769bf215546Sopenharmony_ci } 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci if (instr->slots[PPIR_INSTR_SLOT_ALU_SCL_ADD]) { 772bf215546Sopenharmony_ci ppir_node *node = instr->slots[PPIR_INSTR_SLOT_ALU_SCL_ADD]; 773bf215546Sopenharmony_ci if (node->op == ppir_op_ddx || node->op == ppir_op_ddy) 774bf215546Sopenharmony_ci ctrl->sync = true; 775bf215546Sopenharmony_ci } 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci for (int i = 0; i < 2; i++) { 778bf215546Sopenharmony_ci if (instr->constant[i].num) { 779bf215546Sopenharmony_ci uint16_t output[4] = {0}; 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci ppir_codegen_encode_const(instr->constant + i, output); 782bf215546Sopenharmony_ci bitcopy(ctrl + 1, size, output, instr->constant[i].num * 16); 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_ci size += 64; 785bf215546Sopenharmony_ci ctrl->fields |= 1 << (ppir_codegen_field_shift_vec4_const_0 + i); 786bf215546Sopenharmony_ci } 787bf215546Sopenharmony_ci } 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ci size = align_to_word(size) + 1; 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci ctrl->count = size; 792bf215546Sopenharmony_ci if (instr->stop) 793bf215546Sopenharmony_ci ctrl->stop = true; 794bf215546Sopenharmony_ci 795bf215546Sopenharmony_ci if (last_code) { 796bf215546Sopenharmony_ci ppir_codegen_ctrl *last_ctrl = last_code; 797bf215546Sopenharmony_ci last_ctrl->next_count = size; 798bf215546Sopenharmony_ci last_ctrl->prefetch = true; 799bf215546Sopenharmony_ci } 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci return size; 802bf215546Sopenharmony_ci} 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_cistatic void ppir_codegen_print_prog(ppir_compiler *comp) 805bf215546Sopenharmony_ci{ 806bf215546Sopenharmony_ci uint32_t *prog = comp->prog->shader; 807bf215546Sopenharmony_ci unsigned offset = 0; 808bf215546Sopenharmony_ci 809bf215546Sopenharmony_ci printf("========ppir codegen========\n"); 810bf215546Sopenharmony_ci list_for_each_entry(ppir_block, block, &comp->block_list, list) { 811bf215546Sopenharmony_ci list_for_each_entry(ppir_instr, instr, &block->instr_list, list) { 812bf215546Sopenharmony_ci printf("%03d (@%6d): ", instr->index, instr->offset); 813bf215546Sopenharmony_ci int n = prog[0] & 0x1f; 814bf215546Sopenharmony_ci for (int i = 0; i < n; i++) { 815bf215546Sopenharmony_ci if (i && i % 6 == 0) 816bf215546Sopenharmony_ci printf("\n "); 817bf215546Sopenharmony_ci printf("%08x ", prog[i]); 818bf215546Sopenharmony_ci } 819bf215546Sopenharmony_ci printf("\n"); 820bf215546Sopenharmony_ci ppir_disassemble_instr(prog, offset, stdout); 821bf215546Sopenharmony_ci prog += n; 822bf215546Sopenharmony_ci offset += n; 823bf215546Sopenharmony_ci } 824bf215546Sopenharmony_ci } 825bf215546Sopenharmony_ci printf("-----------------------\n"); 826bf215546Sopenharmony_ci} 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_cibool ppir_codegen_prog(ppir_compiler *comp) 829bf215546Sopenharmony_ci{ 830bf215546Sopenharmony_ci int size = 0; 831bf215546Sopenharmony_ci list_for_each_entry(ppir_block, block, &comp->block_list, list) { 832bf215546Sopenharmony_ci list_for_each_entry(ppir_instr, instr, &block->instr_list, list) { 833bf215546Sopenharmony_ci instr->offset = size; 834bf215546Sopenharmony_ci instr->encode_size = get_instr_encode_size(instr); 835bf215546Sopenharmony_ci size += instr->encode_size; 836bf215546Sopenharmony_ci } 837bf215546Sopenharmony_ci /* Set stop flag for the last instruction if block has stop flag */ 838bf215546Sopenharmony_ci if (block->stop) { 839bf215546Sopenharmony_ci ppir_instr *instr = list_last_entry(&block->instr_list, ppir_instr, list); 840bf215546Sopenharmony_ci instr->stop = true; 841bf215546Sopenharmony_ci } 842bf215546Sopenharmony_ci } 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci uint32_t *prog = rzalloc_size(comp->prog, size * sizeof(uint32_t)); 845bf215546Sopenharmony_ci if (!prog) 846bf215546Sopenharmony_ci return false; 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_ci uint32_t *code = prog, *last_code = NULL; 849bf215546Sopenharmony_ci list_for_each_entry(ppir_block, block, &comp->block_list, list) { 850bf215546Sopenharmony_ci list_for_each_entry(ppir_instr, instr, &block->instr_list, list) { 851bf215546Sopenharmony_ci int offset = encode_instr(instr, code, last_code); 852bf215546Sopenharmony_ci last_code = code; 853bf215546Sopenharmony_ci code += offset; 854bf215546Sopenharmony_ci } 855bf215546Sopenharmony_ci } 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_ci if (comp->prog->shader) 858bf215546Sopenharmony_ci ralloc_free(comp->prog->shader); 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci comp->prog->shader = prog; 861bf215546Sopenharmony_ci comp->prog->state.shader_size = size * sizeof(uint32_t); 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_PP) 864bf215546Sopenharmony_ci ppir_codegen_print_prog(comp); 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci return true; 867bf215546Sopenharmony_ci} 868