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 27bf215546Sopenharmony_ci#include "gpir.h" 28bf215546Sopenharmony_ci#include "codegen.h" 29bf215546Sopenharmony_ci#include "lima_context.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_cistatic gpir_codegen_src gpir_get_alu_input(gpir_node *parent, gpir_node *child) 32bf215546Sopenharmony_ci{ 33bf215546Sopenharmony_ci static const int slot_to_src[GPIR_INSTR_SLOT_NUM][3] = { 34bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MUL0] = { 35bf215546Sopenharmony_ci gpir_codegen_src_unused, gpir_codegen_src_p1_mul_0, gpir_codegen_src_p2_mul_0 }, 36bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MUL1] = { 37bf215546Sopenharmony_ci gpir_codegen_src_unused, gpir_codegen_src_p1_mul_1, gpir_codegen_src_p2_mul_1 }, 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_ADD0] = { 40bf215546Sopenharmony_ci gpir_codegen_src_unused, gpir_codegen_src_p1_acc_0, gpir_codegen_src_p2_acc_0 }, 41bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_ADD1] = { 42bf215546Sopenharmony_ci gpir_codegen_src_unused, gpir_codegen_src_p1_acc_1, gpir_codegen_src_p2_acc_1 }, 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_COMPLEX] = { 45bf215546Sopenharmony_ci gpir_codegen_src_unused, gpir_codegen_src_p1_complex, gpir_codegen_src_unused }, 46bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_PASS] = { 47bf215546Sopenharmony_ci gpir_codegen_src_unused, gpir_codegen_src_p1_pass, gpir_codegen_src_p2_pass }, 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG0_LOAD0] = { 50bf215546Sopenharmony_ci gpir_codegen_src_attrib_x, gpir_codegen_src_p1_attrib_x, gpir_codegen_src_unused }, 51bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG0_LOAD1] = { 52bf215546Sopenharmony_ci gpir_codegen_src_attrib_y, gpir_codegen_src_p1_attrib_y, gpir_codegen_src_unused }, 53bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG0_LOAD2] = { 54bf215546Sopenharmony_ci gpir_codegen_src_attrib_z, gpir_codegen_src_p1_attrib_z, gpir_codegen_src_unused }, 55bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG0_LOAD3] = { 56bf215546Sopenharmony_ci gpir_codegen_src_attrib_w, gpir_codegen_src_p1_attrib_w, gpir_codegen_src_unused }, 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG1_LOAD0] = { 59bf215546Sopenharmony_ci gpir_codegen_src_register_x, gpir_codegen_src_unused, gpir_codegen_src_unused}, 60bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG1_LOAD1] = { 61bf215546Sopenharmony_ci gpir_codegen_src_register_y, gpir_codegen_src_unused, gpir_codegen_src_unused}, 62bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG1_LOAD2] = { 63bf215546Sopenharmony_ci gpir_codegen_src_register_z, gpir_codegen_src_unused, gpir_codegen_src_unused}, 64bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG1_LOAD3] = { 65bf215546Sopenharmony_ci gpir_codegen_src_register_w, gpir_codegen_src_unused, gpir_codegen_src_unused}, 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MEM_LOAD0] = { 68bf215546Sopenharmony_ci gpir_codegen_src_load_x, gpir_codegen_src_unused, gpir_codegen_src_unused }, 69bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MEM_LOAD1] = { 70bf215546Sopenharmony_ci gpir_codegen_src_load_y, gpir_codegen_src_unused, gpir_codegen_src_unused }, 71bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MEM_LOAD2] = { 72bf215546Sopenharmony_ci gpir_codegen_src_load_z, gpir_codegen_src_unused, gpir_codegen_src_unused }, 73bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MEM_LOAD3] = { 74bf215546Sopenharmony_ci gpir_codegen_src_load_w, gpir_codegen_src_unused, gpir_codegen_src_unused }, 75bf215546Sopenharmony_ci }; 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci int diff = child->sched.instr->index - parent->sched.instr->index; 78bf215546Sopenharmony_ci assert(diff < 3); 79bf215546Sopenharmony_ci assert(diff >= 0); 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci int src = slot_to_src[child->sched.pos][diff]; 82bf215546Sopenharmony_ci assert(src != gpir_codegen_src_unused); 83bf215546Sopenharmony_ci return src; 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cistatic void gpir_codegen_mul0_slot(gpir_codegen_instr *code, gpir_instr *instr) 87bf215546Sopenharmony_ci{ 88bf215546Sopenharmony_ci gpir_node *node = instr->slots[GPIR_INSTR_SLOT_MUL0]; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci if (!node) { 91bf215546Sopenharmony_ci code->mul0_src0 = gpir_codegen_src_unused; 92bf215546Sopenharmony_ci code->mul0_src1 = gpir_codegen_src_unused; 93bf215546Sopenharmony_ci return; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci gpir_alu_node *alu = gpir_node_to_alu(node); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci switch (node->op) { 99bf215546Sopenharmony_ci case gpir_op_mul: 100bf215546Sopenharmony_ci code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]); 101bf215546Sopenharmony_ci code->mul0_src1 = gpir_get_alu_input(node, alu->children[1]); 102bf215546Sopenharmony_ci if (code->mul0_src1 == gpir_codegen_src_p1_complex) { 103bf215546Sopenharmony_ci /* Will get confused with gpir_codegen_src_ident, so need to swap inputs */ 104bf215546Sopenharmony_ci code->mul0_src1 = code->mul0_src0; 105bf215546Sopenharmony_ci code->mul0_src0 = gpir_codegen_src_p1_complex; 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci code->mul0_neg = alu->dest_negate; 109bf215546Sopenharmony_ci if (alu->children_negate[0]) 110bf215546Sopenharmony_ci code->mul0_neg = !code->mul0_neg; 111bf215546Sopenharmony_ci if (alu->children_negate[1]) 112bf215546Sopenharmony_ci code->mul0_neg = !code->mul0_neg; 113bf215546Sopenharmony_ci break; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci case gpir_op_neg: 116bf215546Sopenharmony_ci code->mul0_neg = true; 117bf215546Sopenharmony_ci FALLTHROUGH; 118bf215546Sopenharmony_ci case gpir_op_mov: 119bf215546Sopenharmony_ci code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]); 120bf215546Sopenharmony_ci code->mul0_src1 = gpir_codegen_src_ident; 121bf215546Sopenharmony_ci break; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci case gpir_op_complex1: 124bf215546Sopenharmony_ci code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]); 125bf215546Sopenharmony_ci code->mul0_src1 = gpir_get_alu_input(node, alu->children[1]); 126bf215546Sopenharmony_ci code->mul_op = gpir_codegen_mul_op_complex1; 127bf215546Sopenharmony_ci break; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci case gpir_op_complex2: 130bf215546Sopenharmony_ci code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]); 131bf215546Sopenharmony_ci code->mul0_src1 = code->mul0_src0; 132bf215546Sopenharmony_ci code->mul_op = gpir_codegen_mul_op_complex2; 133bf215546Sopenharmony_ci break; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci case gpir_op_select: 136bf215546Sopenharmony_ci code->mul0_src0 = gpir_get_alu_input(node, alu->children[2]); 137bf215546Sopenharmony_ci code->mul0_src1 = gpir_get_alu_input(node, alu->children[0]); 138bf215546Sopenharmony_ci code->mul_op = gpir_codegen_mul_op_select; 139bf215546Sopenharmony_ci break; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci default: 142bf215546Sopenharmony_ci assert(0); 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_cistatic void gpir_codegen_mul1_slot(gpir_codegen_instr *code, gpir_instr *instr) 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci gpir_node *node = instr->slots[GPIR_INSTR_SLOT_MUL1]; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci if (!node) { 151bf215546Sopenharmony_ci code->mul1_src0 = gpir_codegen_src_unused; 152bf215546Sopenharmony_ci code->mul1_src1 = gpir_codegen_src_unused; 153bf215546Sopenharmony_ci return; 154bf215546Sopenharmony_ci } 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci gpir_alu_node *alu = gpir_node_to_alu(node); 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci switch (node->op) { 159bf215546Sopenharmony_ci case gpir_op_mul: 160bf215546Sopenharmony_ci code->mul1_src0 = gpir_get_alu_input(node, alu->children[0]); 161bf215546Sopenharmony_ci code->mul1_src1 = gpir_get_alu_input(node, alu->children[1]); 162bf215546Sopenharmony_ci if (code->mul1_src1 == gpir_codegen_src_p1_complex) { 163bf215546Sopenharmony_ci /* Will get confused with gpir_codegen_src_ident, so need to swap inputs */ 164bf215546Sopenharmony_ci code->mul1_src1 = code->mul1_src0; 165bf215546Sopenharmony_ci code->mul1_src0 = gpir_codegen_src_p1_complex; 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci code->mul1_neg = alu->dest_negate; 169bf215546Sopenharmony_ci if (alu->children_negate[0]) 170bf215546Sopenharmony_ci code->mul1_neg = !code->mul1_neg; 171bf215546Sopenharmony_ci if (alu->children_negate[1]) 172bf215546Sopenharmony_ci code->mul1_neg = !code->mul1_neg; 173bf215546Sopenharmony_ci break; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci case gpir_op_neg: 176bf215546Sopenharmony_ci code->mul1_neg = true; 177bf215546Sopenharmony_ci FALLTHROUGH; 178bf215546Sopenharmony_ci case gpir_op_mov: 179bf215546Sopenharmony_ci code->mul1_src0 = gpir_get_alu_input(node, alu->children[0]); 180bf215546Sopenharmony_ci code->mul1_src1 = gpir_codegen_src_ident; 181bf215546Sopenharmony_ci break; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci case gpir_op_complex1: 184bf215546Sopenharmony_ci code->mul1_src0 = gpir_get_alu_input(node, alu->children[0]); 185bf215546Sopenharmony_ci code->mul1_src1 = gpir_get_alu_input(node, alu->children[2]); 186bf215546Sopenharmony_ci break; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci case gpir_op_select: 189bf215546Sopenharmony_ci code->mul1_src0 = gpir_get_alu_input(node, alu->children[1]); 190bf215546Sopenharmony_ci code->mul1_src1 = gpir_codegen_src_unused; 191bf215546Sopenharmony_ci break; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci default: 194bf215546Sopenharmony_ci assert(0); 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci} 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_cistatic void gpir_codegen_add0_slot(gpir_codegen_instr *code, gpir_instr *instr) 199bf215546Sopenharmony_ci{ 200bf215546Sopenharmony_ci gpir_node *node = instr->slots[GPIR_INSTR_SLOT_ADD0]; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci if (!node) { 203bf215546Sopenharmony_ci code->acc0_src0 = gpir_codegen_src_unused; 204bf215546Sopenharmony_ci code->acc0_src1 = gpir_codegen_src_unused; 205bf215546Sopenharmony_ci return; 206bf215546Sopenharmony_ci } 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci gpir_alu_node *alu = gpir_node_to_alu(node); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci switch (node->op) { 211bf215546Sopenharmony_ci case gpir_op_add: 212bf215546Sopenharmony_ci case gpir_op_min: 213bf215546Sopenharmony_ci case gpir_op_max: 214bf215546Sopenharmony_ci case gpir_op_lt: 215bf215546Sopenharmony_ci case gpir_op_ge: 216bf215546Sopenharmony_ci code->acc0_src0 = gpir_get_alu_input(node, alu->children[0]); 217bf215546Sopenharmony_ci code->acc0_src1 = gpir_get_alu_input(node, alu->children[1]); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci code->acc0_src0_neg = alu->children_negate[0]; 220bf215546Sopenharmony_ci code->acc0_src1_neg = alu->children_negate[1]; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci switch (node->op) { 223bf215546Sopenharmony_ci case gpir_op_add: 224bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_add; 225bf215546Sopenharmony_ci if (code->acc0_src1 == gpir_codegen_src_p1_complex) { 226bf215546Sopenharmony_ci code->acc0_src1 = code->acc0_src0; 227bf215546Sopenharmony_ci code->acc0_src0 = gpir_codegen_src_p1_complex; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci bool tmp = code->acc0_src0_neg; 230bf215546Sopenharmony_ci code->acc0_src0_neg = code->acc0_src1_neg; 231bf215546Sopenharmony_ci code->acc0_src1_neg = tmp; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci break; 234bf215546Sopenharmony_ci case gpir_op_min: 235bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_min; 236bf215546Sopenharmony_ci break; 237bf215546Sopenharmony_ci case gpir_op_max: 238bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_max; 239bf215546Sopenharmony_ci break; 240bf215546Sopenharmony_ci case gpir_op_lt: 241bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_lt; 242bf215546Sopenharmony_ci break; 243bf215546Sopenharmony_ci case gpir_op_ge: 244bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_ge; 245bf215546Sopenharmony_ci break; 246bf215546Sopenharmony_ci default: 247bf215546Sopenharmony_ci assert(0); 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci break; 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci case gpir_op_floor: 253bf215546Sopenharmony_ci case gpir_op_sign: 254bf215546Sopenharmony_ci code->acc0_src0 = gpir_get_alu_input(node, alu->children[0]); 255bf215546Sopenharmony_ci code->acc0_src0_neg = alu->children_negate[0]; 256bf215546Sopenharmony_ci switch (node->op) { 257bf215546Sopenharmony_ci case gpir_op_floor: 258bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_floor; 259bf215546Sopenharmony_ci break; 260bf215546Sopenharmony_ci case gpir_op_sign: 261bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_sign; 262bf215546Sopenharmony_ci break; 263bf215546Sopenharmony_ci default: 264bf215546Sopenharmony_ci assert(0); 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci break; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci case gpir_op_neg: 269bf215546Sopenharmony_ci code->acc0_src0_neg = true; 270bf215546Sopenharmony_ci FALLTHROUGH; 271bf215546Sopenharmony_ci case gpir_op_mov: 272bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_add; 273bf215546Sopenharmony_ci code->acc0_src0 = gpir_get_alu_input(node, alu->children[0]); 274bf215546Sopenharmony_ci code->acc0_src1 = gpir_codegen_src_ident; 275bf215546Sopenharmony_ci code->acc0_src1_neg = true; 276bf215546Sopenharmony_ci break; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci default: 279bf215546Sopenharmony_ci assert(0); 280bf215546Sopenharmony_ci } 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_cistatic void gpir_codegen_add1_slot(gpir_codegen_instr *code, gpir_instr *instr) 284bf215546Sopenharmony_ci{ 285bf215546Sopenharmony_ci gpir_node *node = instr->slots[GPIR_INSTR_SLOT_ADD1]; 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci if (!node) { 288bf215546Sopenharmony_ci code->acc1_src0 = gpir_codegen_src_unused; 289bf215546Sopenharmony_ci code->acc1_src1 = gpir_codegen_src_unused; 290bf215546Sopenharmony_ci return; 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci gpir_alu_node *alu = gpir_node_to_alu(node); 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci switch (node->op) { 296bf215546Sopenharmony_ci case gpir_op_add: 297bf215546Sopenharmony_ci case gpir_op_min: 298bf215546Sopenharmony_ci case gpir_op_max: 299bf215546Sopenharmony_ci case gpir_op_lt: 300bf215546Sopenharmony_ci case gpir_op_ge: 301bf215546Sopenharmony_ci code->acc1_src0 = gpir_get_alu_input(node, alu->children[0]); 302bf215546Sopenharmony_ci code->acc1_src1 = gpir_get_alu_input(node, alu->children[1]); 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci code->acc1_src0_neg = alu->children_negate[0]; 305bf215546Sopenharmony_ci code->acc1_src1_neg = alu->children_negate[1]; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci switch (node->op) { 308bf215546Sopenharmony_ci case gpir_op_add: 309bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_add; 310bf215546Sopenharmony_ci if (code->acc1_src1 == gpir_codegen_src_p1_complex) { 311bf215546Sopenharmony_ci code->acc1_src1 = code->acc1_src0; 312bf215546Sopenharmony_ci code->acc1_src0 = gpir_codegen_src_p1_complex; 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci bool tmp = code->acc1_src0_neg; 315bf215546Sopenharmony_ci code->acc1_src0_neg = code->acc1_src1_neg; 316bf215546Sopenharmony_ci code->acc1_src1_neg = tmp; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci break; 319bf215546Sopenharmony_ci case gpir_op_min: 320bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_min; 321bf215546Sopenharmony_ci break; 322bf215546Sopenharmony_ci case gpir_op_max: 323bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_max; 324bf215546Sopenharmony_ci break; 325bf215546Sopenharmony_ci case gpir_op_lt: 326bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_lt; 327bf215546Sopenharmony_ci break; 328bf215546Sopenharmony_ci case gpir_op_ge: 329bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_ge; 330bf215546Sopenharmony_ci break; 331bf215546Sopenharmony_ci default: 332bf215546Sopenharmony_ci assert(0); 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci break; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci case gpir_op_floor: 338bf215546Sopenharmony_ci case gpir_op_sign: 339bf215546Sopenharmony_ci code->acc1_src0 = gpir_get_alu_input(node, alu->children[0]); 340bf215546Sopenharmony_ci code->acc1_src0_neg = alu->children_negate[0]; 341bf215546Sopenharmony_ci switch (node->op) { 342bf215546Sopenharmony_ci case gpir_op_floor: 343bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_floor; 344bf215546Sopenharmony_ci break; 345bf215546Sopenharmony_ci case gpir_op_sign: 346bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_sign; 347bf215546Sopenharmony_ci break; 348bf215546Sopenharmony_ci default: 349bf215546Sopenharmony_ci assert(0); 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci break; 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci case gpir_op_neg: 354bf215546Sopenharmony_ci code->acc1_src0_neg = true; 355bf215546Sopenharmony_ci FALLTHROUGH; 356bf215546Sopenharmony_ci case gpir_op_mov: 357bf215546Sopenharmony_ci code->acc_op = gpir_codegen_acc_op_add; 358bf215546Sopenharmony_ci code->acc1_src0 = gpir_get_alu_input(node, alu->children[0]); 359bf215546Sopenharmony_ci code->acc1_src1 = gpir_codegen_src_ident; 360bf215546Sopenharmony_ci code->acc1_src1_neg = true; 361bf215546Sopenharmony_ci break; 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci default: 364bf215546Sopenharmony_ci assert(0); 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci} 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_cistatic void gpir_codegen_complex_slot(gpir_codegen_instr *code, gpir_instr *instr) 369bf215546Sopenharmony_ci{ 370bf215546Sopenharmony_ci gpir_node *node = instr->slots[GPIR_INSTR_SLOT_COMPLEX]; 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci if (!node) { 373bf215546Sopenharmony_ci code->complex_src = gpir_codegen_src_unused; 374bf215546Sopenharmony_ci return; 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci switch (node->op) { 378bf215546Sopenharmony_ci case gpir_op_mov: 379bf215546Sopenharmony_ci case gpir_op_rcp_impl: 380bf215546Sopenharmony_ci case gpir_op_rsqrt_impl: 381bf215546Sopenharmony_ci case gpir_op_exp2_impl: 382bf215546Sopenharmony_ci case gpir_op_log2_impl: 383bf215546Sopenharmony_ci { 384bf215546Sopenharmony_ci gpir_alu_node *alu = gpir_node_to_alu(node); 385bf215546Sopenharmony_ci code->complex_src = gpir_get_alu_input(node, alu->children[0]); 386bf215546Sopenharmony_ci break; 387bf215546Sopenharmony_ci } 388bf215546Sopenharmony_ci default: 389bf215546Sopenharmony_ci assert(0); 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci switch (node->op) { 393bf215546Sopenharmony_ci case gpir_op_mov: 394bf215546Sopenharmony_ci code->complex_op = gpir_codegen_complex_op_pass; 395bf215546Sopenharmony_ci break; 396bf215546Sopenharmony_ci case gpir_op_rcp_impl: 397bf215546Sopenharmony_ci code->complex_op = gpir_codegen_complex_op_rcp; 398bf215546Sopenharmony_ci break; 399bf215546Sopenharmony_ci case gpir_op_rsqrt_impl: 400bf215546Sopenharmony_ci code->complex_op = gpir_codegen_complex_op_rsqrt; 401bf215546Sopenharmony_ci break; 402bf215546Sopenharmony_ci case gpir_op_exp2_impl: 403bf215546Sopenharmony_ci code->complex_op = gpir_codegen_complex_op_exp2; 404bf215546Sopenharmony_ci break; 405bf215546Sopenharmony_ci case gpir_op_log2_impl: 406bf215546Sopenharmony_ci code->complex_op = gpir_codegen_complex_op_log2; 407bf215546Sopenharmony_ci break; 408bf215546Sopenharmony_ci default: 409bf215546Sopenharmony_ci assert(0); 410bf215546Sopenharmony_ci } 411bf215546Sopenharmony_ci} 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_cistatic void gpir_codegen_pass_slot(gpir_codegen_instr *code, gpir_instr *instr) 414bf215546Sopenharmony_ci{ 415bf215546Sopenharmony_ci gpir_node *node = instr->slots[GPIR_INSTR_SLOT_PASS]; 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci if (!node) { 418bf215546Sopenharmony_ci code->pass_op = gpir_codegen_pass_op_pass; 419bf215546Sopenharmony_ci code->pass_src = gpir_codegen_src_unused; 420bf215546Sopenharmony_ci return; 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci if (node->op == gpir_op_branch_cond) { 424bf215546Sopenharmony_ci gpir_branch_node *branch = gpir_node_to_branch(node); 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci code->pass_op = gpir_codegen_pass_op_pass; 427bf215546Sopenharmony_ci code->pass_src = gpir_get_alu_input(node, branch->cond); 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci /* Fill out branch information */ 430bf215546Sopenharmony_ci unsigned offset = branch->dest->instr_offset; 431bf215546Sopenharmony_ci assert(offset < 0x200); 432bf215546Sopenharmony_ci code->branch = true; 433bf215546Sopenharmony_ci code->branch_target = offset & 0xff; 434bf215546Sopenharmony_ci code->branch_target_lo = !(offset >> 8); 435bf215546Sopenharmony_ci code->unknown_1 = 13; 436bf215546Sopenharmony_ci return; 437bf215546Sopenharmony_ci } 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci gpir_alu_node *alu = gpir_node_to_alu(node); 440bf215546Sopenharmony_ci code->pass_src = gpir_get_alu_input(node, alu->children[0]); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci switch (node->op) { 443bf215546Sopenharmony_ci case gpir_op_mov: 444bf215546Sopenharmony_ci code->pass_op = gpir_codegen_pass_op_pass; 445bf215546Sopenharmony_ci break; 446bf215546Sopenharmony_ci case gpir_op_preexp2: 447bf215546Sopenharmony_ci code->pass_op = gpir_codegen_pass_op_preexp2; 448bf215546Sopenharmony_ci break; 449bf215546Sopenharmony_ci case gpir_op_postlog2: 450bf215546Sopenharmony_ci code->pass_op = gpir_codegen_pass_op_postlog2; 451bf215546Sopenharmony_ci break; 452bf215546Sopenharmony_ci default: 453bf215546Sopenharmony_ci assert(0); 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci} 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_cistatic void gpir_codegen_reg0_slot(gpir_codegen_instr *code, gpir_instr *instr) 459bf215546Sopenharmony_ci{ 460bf215546Sopenharmony_ci if (!instr->reg0_use_count) 461bf215546Sopenharmony_ci return; 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci code->register0_attribute = instr->reg0_is_attr; 464bf215546Sopenharmony_ci code->register0_addr = instr->reg0_index; 465bf215546Sopenharmony_ci} 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_cistatic void gpir_codegen_reg1_slot(gpir_codegen_instr *code, gpir_instr *instr) 468bf215546Sopenharmony_ci{ 469bf215546Sopenharmony_ci if (!instr->reg1_use_count) 470bf215546Sopenharmony_ci return; 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci code->register1_addr = instr->reg1_index; 473bf215546Sopenharmony_ci} 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_cistatic void gpir_codegen_mem_slot(gpir_codegen_instr *code, gpir_instr *instr) 476bf215546Sopenharmony_ci{ 477bf215546Sopenharmony_ci if (!instr->mem_use_count) { 478bf215546Sopenharmony_ci code->load_offset = gpir_codegen_load_off_none; 479bf215546Sopenharmony_ci return; 480bf215546Sopenharmony_ci } 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci code->load_addr = instr->mem_index; 483bf215546Sopenharmony_ci code->load_offset = gpir_codegen_load_off_none; 484bf215546Sopenharmony_ci} 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_cistatic gpir_codegen_store_src gpir_get_store_input(gpir_node *node) 487bf215546Sopenharmony_ci{ 488bf215546Sopenharmony_ci static int slot_to_src[GPIR_INSTR_SLOT_NUM] = { 489bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MUL0] = gpir_codegen_store_src_mul_0, 490bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_MUL1] = gpir_codegen_store_src_mul_1, 491bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_ADD0] = gpir_codegen_store_src_acc_0, 492bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_ADD1] = gpir_codegen_store_src_acc_1, 493bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_COMPLEX] = gpir_codegen_store_src_complex, 494bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_PASS] = gpir_codegen_store_src_pass, 495bf215546Sopenharmony_ci [GPIR_INSTR_SLOT_REG0_LOAD0...GPIR_INSTR_SLOT_STORE3] = gpir_codegen_store_src_none, 496bf215546Sopenharmony_ci }; 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci gpir_store_node *store = gpir_node_to_store(node); 499bf215546Sopenharmony_ci return slot_to_src[store->child->sched.pos]; 500bf215546Sopenharmony_ci} 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_cistatic void gpir_codegen_store_slot(gpir_codegen_instr *code, gpir_instr *instr) 503bf215546Sopenharmony_ci{ 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci gpir_node *node = instr->slots[GPIR_INSTR_SLOT_STORE0]; 506bf215546Sopenharmony_ci if (node) 507bf215546Sopenharmony_ci code->store0_src_x = gpir_get_store_input(node); 508bf215546Sopenharmony_ci else 509bf215546Sopenharmony_ci code->store0_src_x = gpir_codegen_store_src_none; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci node = instr->slots[GPIR_INSTR_SLOT_STORE1]; 512bf215546Sopenharmony_ci if (node) 513bf215546Sopenharmony_ci code->store0_src_y = gpir_get_store_input(node); 514bf215546Sopenharmony_ci else 515bf215546Sopenharmony_ci code->store0_src_y = gpir_codegen_store_src_none; 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci node = instr->slots[GPIR_INSTR_SLOT_STORE2]; 518bf215546Sopenharmony_ci if (node) 519bf215546Sopenharmony_ci code->store1_src_z = gpir_get_store_input(node); 520bf215546Sopenharmony_ci else 521bf215546Sopenharmony_ci code->store1_src_z = gpir_codegen_store_src_none; 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci node = instr->slots[GPIR_INSTR_SLOT_STORE3]; 524bf215546Sopenharmony_ci if (node) 525bf215546Sopenharmony_ci code->store1_src_w = gpir_get_store_input(node); 526bf215546Sopenharmony_ci else 527bf215546Sopenharmony_ci code->store1_src_w = gpir_codegen_store_src_none; 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci if (instr->store_content[0] == GPIR_INSTR_STORE_TEMP) { 530bf215546Sopenharmony_ci code->store0_temporary = true; 531bf215546Sopenharmony_ci code->unknown_1 = 12; 532bf215546Sopenharmony_ci } 533bf215546Sopenharmony_ci else { 534bf215546Sopenharmony_ci code->store0_varying = instr->store_content[0] == GPIR_INSTR_STORE_VARYING; 535bf215546Sopenharmony_ci code->store0_addr = instr->store_index[0]; 536bf215546Sopenharmony_ci } 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci if (instr->store_content[1] == GPIR_INSTR_STORE_TEMP) { 539bf215546Sopenharmony_ci code->store1_temporary = true; 540bf215546Sopenharmony_ci code->unknown_1 = 12; 541bf215546Sopenharmony_ci } 542bf215546Sopenharmony_ci else { 543bf215546Sopenharmony_ci code->store1_varying = instr->store_content[1] == GPIR_INSTR_STORE_VARYING; 544bf215546Sopenharmony_ci code->store1_addr = instr->store_index[1]; 545bf215546Sopenharmony_ci } 546bf215546Sopenharmony_ci} 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_cistatic void gpir_codegen(gpir_codegen_instr *code, gpir_instr *instr) 549bf215546Sopenharmony_ci{ 550bf215546Sopenharmony_ci gpir_codegen_mul0_slot(code, instr); 551bf215546Sopenharmony_ci gpir_codegen_mul1_slot(code, instr); 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci gpir_codegen_add0_slot(code, instr); 554bf215546Sopenharmony_ci gpir_codegen_add1_slot(code, instr); 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci gpir_codegen_complex_slot(code, instr); 557bf215546Sopenharmony_ci gpir_codegen_pass_slot(code, instr); 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci gpir_codegen_reg0_slot(code, instr); 560bf215546Sopenharmony_ci gpir_codegen_reg1_slot(code, instr); 561bf215546Sopenharmony_ci gpir_codegen_mem_slot(code, instr); 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci gpir_codegen_store_slot(code, instr); 564bf215546Sopenharmony_ci} 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_cistatic void gpir_codegen_print_prog(gpir_compiler *comp) 567bf215546Sopenharmony_ci{ 568bf215546Sopenharmony_ci uint32_t *data = comp->prog->shader; 569bf215546Sopenharmony_ci int num_dword_per_instr = sizeof(gpir_codegen_instr) / sizeof(uint32_t); 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci for (int i = 0; i < comp->num_instr; i++) { 572bf215546Sopenharmony_ci printf("%03d: ", i); 573bf215546Sopenharmony_ci for (int j = 0; j < num_dword_per_instr; j++) 574bf215546Sopenharmony_ci printf("%08x ", data[i * num_dword_per_instr + j]); 575bf215546Sopenharmony_ci printf("\n"); 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci} 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_cibool gpir_codegen_prog(gpir_compiler *comp) 580bf215546Sopenharmony_ci{ 581bf215546Sopenharmony_ci int num_instr = 0; 582bf215546Sopenharmony_ci list_for_each_entry(gpir_block, block, &comp->block_list, list) { 583bf215546Sopenharmony_ci block->instr_offset = num_instr; 584bf215546Sopenharmony_ci num_instr += list_length(&block->instr_list); 585bf215546Sopenharmony_ci } 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci assert(num_instr <= 512); 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_ci gpir_codegen_instr *code = rzalloc_array(comp->prog, gpir_codegen_instr, num_instr); 590bf215546Sopenharmony_ci if (!code) 591bf215546Sopenharmony_ci return false; 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci int instr_index = 0; 594bf215546Sopenharmony_ci list_for_each_entry(gpir_block, block, &comp->block_list, list) { 595bf215546Sopenharmony_ci list_for_each_entry(gpir_instr, instr, &block->instr_list, list) { 596bf215546Sopenharmony_ci gpir_codegen(code + instr_index, instr); 597bf215546Sopenharmony_ci instr_index++; 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci } 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci for (int i = 0; i < num_instr; i++) { 602bf215546Sopenharmony_ci if (code[i].register0_attribute) 603bf215546Sopenharmony_ci comp->prog->state.prefetch = i; 604bf215546Sopenharmony_ci } 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci comp->prog->shader = code; 607bf215546Sopenharmony_ci comp->prog->state.shader_size = num_instr * sizeof(gpir_codegen_instr); 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_GP) { 610bf215546Sopenharmony_ci gpir_codegen_print_prog(comp); 611bf215546Sopenharmony_ci gpir_disassemble_program(code, num_instr, stdout); 612bf215546Sopenharmony_ci } 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_ci return true; 615bf215546Sopenharmony_ci} 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_cistatic gpir_codegen_acc_op gpir_codegen_get_acc_op(gpir_op op) 618bf215546Sopenharmony_ci{ 619bf215546Sopenharmony_ci switch (op) { 620bf215546Sopenharmony_ci case gpir_op_add: 621bf215546Sopenharmony_ci case gpir_op_neg: 622bf215546Sopenharmony_ci case gpir_op_mov: 623bf215546Sopenharmony_ci return gpir_codegen_acc_op_add; 624bf215546Sopenharmony_ci case gpir_op_min: 625bf215546Sopenharmony_ci return gpir_codegen_acc_op_min; 626bf215546Sopenharmony_ci case gpir_op_max: 627bf215546Sopenharmony_ci return gpir_codegen_acc_op_max; 628bf215546Sopenharmony_ci case gpir_op_lt: 629bf215546Sopenharmony_ci return gpir_codegen_acc_op_lt; 630bf215546Sopenharmony_ci case gpir_op_ge: 631bf215546Sopenharmony_ci return gpir_codegen_acc_op_ge; 632bf215546Sopenharmony_ci case gpir_op_floor: 633bf215546Sopenharmony_ci return gpir_codegen_acc_op_floor; 634bf215546Sopenharmony_ci case gpir_op_sign: 635bf215546Sopenharmony_ci return gpir_codegen_acc_op_sign; 636bf215546Sopenharmony_ci default: 637bf215546Sopenharmony_ci assert(0); 638bf215546Sopenharmony_ci } 639bf215546Sopenharmony_ci return -1; 640bf215546Sopenharmony_ci} 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_cibool gpir_codegen_acc_same_op(gpir_op op1, gpir_op op2) 643bf215546Sopenharmony_ci{ 644bf215546Sopenharmony_ci return gpir_codegen_get_acc_op(op1) == gpir_codegen_get_acc_op(op2); 645bf215546Sopenharmony_ci} 646