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