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