1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (c) 2017 Lima Project
3bf215546Sopenharmony_ci * Copyright (c) 2013 Connor Abbott
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
6bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
7bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights
8bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
13bf215546Sopenharmony_ci * all copies or substantial portions 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
18bf215546Sopenharmony_ci * 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 FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21bf215546Sopenharmony_ci * THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#ifndef LIMA_IR_PP_PPIR_H
26bf215546Sopenharmony_ci#define LIMA_IR_PP_PPIR_H
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "util/u_math.h"
29bf215546Sopenharmony_ci#include "util/list.h"
30bf215546Sopenharmony_ci#include "util/set.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "ir/lima_ir.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_citypedef enum {
35bf215546Sopenharmony_ci   ppir_op_unsupported = 0,
36bf215546Sopenharmony_ci   ppir_op_mov,
37bf215546Sopenharmony_ci   ppir_op_abs,
38bf215546Sopenharmony_ci   ppir_op_neg,
39bf215546Sopenharmony_ci   ppir_op_sat,
40bf215546Sopenharmony_ci   ppir_op_add,
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci   ppir_op_ddx,
43bf215546Sopenharmony_ci   ppir_op_ddy,
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   ppir_op_mul,
46bf215546Sopenharmony_ci   ppir_op_rcp,
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   ppir_op_sin_lut,
49bf215546Sopenharmony_ci   ppir_op_cos_lut,
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   ppir_op_sum3,
52bf215546Sopenharmony_ci   ppir_op_sum4,
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   ppir_op_normalize2,
55bf215546Sopenharmony_ci   ppir_op_normalize3,
56bf215546Sopenharmony_ci   ppir_op_normalize4,
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   ppir_op_select,
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   ppir_op_sin,
61bf215546Sopenharmony_ci   ppir_op_cos,
62bf215546Sopenharmony_ci   ppir_op_tan,
63bf215546Sopenharmony_ci   ppir_op_asin,
64bf215546Sopenharmony_ci   ppir_op_acos,
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   ppir_op_atan,
67bf215546Sopenharmony_ci   ppir_op_atan2,
68bf215546Sopenharmony_ci   ppir_op_atan_pt1,
69bf215546Sopenharmony_ci   ppir_op_atan2_pt1,
70bf215546Sopenharmony_ci   ppir_op_atan_pt2,
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   ppir_op_exp,
73bf215546Sopenharmony_ci   ppir_op_log,
74bf215546Sopenharmony_ci   ppir_op_exp2,
75bf215546Sopenharmony_ci   ppir_op_log2,
76bf215546Sopenharmony_ci   ppir_op_sqrt,
77bf215546Sopenharmony_ci   ppir_op_rsqrt,
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   ppir_op_sign,
80bf215546Sopenharmony_ci   ppir_op_floor,
81bf215546Sopenharmony_ci   ppir_op_ceil,
82bf215546Sopenharmony_ci   ppir_op_fract,
83bf215546Sopenharmony_ci   ppir_op_mod,
84bf215546Sopenharmony_ci   ppir_op_min,
85bf215546Sopenharmony_ci   ppir_op_max,
86bf215546Sopenharmony_ci   ppir_op_trunc,
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci   ppir_op_and,
89bf215546Sopenharmony_ci   ppir_op_or,
90bf215546Sopenharmony_ci   ppir_op_xor,
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   ppir_op_lt,
93bf215546Sopenharmony_ci   ppir_op_gt,
94bf215546Sopenharmony_ci   ppir_op_le,
95bf215546Sopenharmony_ci   ppir_op_ge,
96bf215546Sopenharmony_ci   ppir_op_eq,
97bf215546Sopenharmony_ci   ppir_op_ne,
98bf215546Sopenharmony_ci   ppir_op_not,
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   ppir_op_load_uniform,
101bf215546Sopenharmony_ci   ppir_op_load_varying,
102bf215546Sopenharmony_ci   ppir_op_load_coords,
103bf215546Sopenharmony_ci   ppir_op_load_coords_reg,
104bf215546Sopenharmony_ci   ppir_op_load_fragcoord,
105bf215546Sopenharmony_ci   ppir_op_load_pointcoord,
106bf215546Sopenharmony_ci   ppir_op_load_frontface,
107bf215546Sopenharmony_ci   ppir_op_load_texture,
108bf215546Sopenharmony_ci   ppir_op_load_temp,
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   ppir_op_store_temp,
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   ppir_op_const,
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   ppir_op_discard,
115bf215546Sopenharmony_ci   ppir_op_branch,
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   ppir_op_undef,
118bf215546Sopenharmony_ci   ppir_op_dummy,
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   ppir_op_num,
121bf215546Sopenharmony_ci} ppir_op;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_citypedef enum {
124bf215546Sopenharmony_ci   ppir_node_type_alu,
125bf215546Sopenharmony_ci   ppir_node_type_const,
126bf215546Sopenharmony_ci   ppir_node_type_load,
127bf215546Sopenharmony_ci   ppir_node_type_store,
128bf215546Sopenharmony_ci   ppir_node_type_load_texture,
129bf215546Sopenharmony_ci   ppir_node_type_discard,
130bf215546Sopenharmony_ci   ppir_node_type_branch,
131bf215546Sopenharmony_ci} ppir_node_type;
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_citypedef struct {
134bf215546Sopenharmony_ci   char *name;
135bf215546Sopenharmony_ci   ppir_node_type type;
136bf215546Sopenharmony_ci   int *slots;
137bf215546Sopenharmony_ci} ppir_op_info;
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ciextern const ppir_op_info ppir_op_infos[];
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_citypedef enum {
142bf215546Sopenharmony_ci   ppir_dep_src,
143bf215546Sopenharmony_ci   ppir_dep_write_after_read,
144bf215546Sopenharmony_ci   ppir_dep_sequence,
145bf215546Sopenharmony_ci} ppir_dep_type;
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_citypedef struct {
148bf215546Sopenharmony_ci   void *pred, *succ;
149bf215546Sopenharmony_ci   ppir_dep_type type;
150bf215546Sopenharmony_ci   struct list_head pred_link;
151bf215546Sopenharmony_ci   struct list_head succ_link;
152bf215546Sopenharmony_ci} ppir_dep;
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_citypedef struct ppir_node {
155bf215546Sopenharmony_ci   struct list_head list;
156bf215546Sopenharmony_ci   struct list_head sched_list;
157bf215546Sopenharmony_ci   ppir_op op;
158bf215546Sopenharmony_ci   ppir_node_type type;
159bf215546Sopenharmony_ci   int index;
160bf215546Sopenharmony_ci   char name[16];
161bf215546Sopenharmony_ci   bool printed;
162bf215546Sopenharmony_ci   struct ppir_instr *instr;
163bf215546Sopenharmony_ci   int instr_pos;
164bf215546Sopenharmony_ci   struct ppir_block *block;
165bf215546Sopenharmony_ci   bool is_out;
166bf215546Sopenharmony_ci   bool succ_different_block;
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   /* for scheduler */
169bf215546Sopenharmony_ci   struct list_head succ_list;
170bf215546Sopenharmony_ci   struct list_head pred_list;
171bf215546Sopenharmony_ci} ppir_node;
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_citypedef enum {
174bf215546Sopenharmony_ci   ppir_pipeline_reg_const0,
175bf215546Sopenharmony_ci   ppir_pipeline_reg_const1,
176bf215546Sopenharmony_ci   ppir_pipeline_reg_sampler,
177bf215546Sopenharmony_ci   ppir_pipeline_reg_uniform,
178bf215546Sopenharmony_ci   ppir_pipeline_reg_vmul,
179bf215546Sopenharmony_ci   ppir_pipeline_reg_fmul,
180bf215546Sopenharmony_ci   ppir_pipeline_reg_discard, /* varying load */
181bf215546Sopenharmony_ci} ppir_pipeline;
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_citypedef enum {
184bf215546Sopenharmony_ci   ppir_output_color0,
185bf215546Sopenharmony_ci   ppir_output_color1,
186bf215546Sopenharmony_ci   ppir_output_depth,
187bf215546Sopenharmony_ci   ppir_output_num,
188bf215546Sopenharmony_ci   ppir_output_invalid = -1,
189bf215546Sopenharmony_ci} ppir_output_type;
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_cistatic inline const char *ppir_output_type_to_str(ppir_output_type type)
192bf215546Sopenharmony_ci{
193bf215546Sopenharmony_ci   switch (type) {
194bf215546Sopenharmony_ci   case ppir_output_color0:
195bf215546Sopenharmony_ci      return "OUTPUT_COLOR0";
196bf215546Sopenharmony_ci   case ppir_output_color1:
197bf215546Sopenharmony_ci      return "OUTPUT_COLOR1";
198bf215546Sopenharmony_ci   case ppir_output_depth:
199bf215546Sopenharmony_ci      return "OUTPUT_DEPTH";
200bf215546Sopenharmony_ci   default:
201bf215546Sopenharmony_ci      return "INVALID";
202bf215546Sopenharmony_ci   }
203bf215546Sopenharmony_ci}
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_cistatic inline ppir_output_type ppir_nir_output_to_ppir(gl_frag_result res, int dual_src_index)
206bf215546Sopenharmony_ci{
207bf215546Sopenharmony_ci   switch (res) {
208bf215546Sopenharmony_ci   case FRAG_RESULT_COLOR:
209bf215546Sopenharmony_ci   case FRAG_RESULT_DATA0:
210bf215546Sopenharmony_ci      return ppir_output_color0 + dual_src_index;
211bf215546Sopenharmony_ci   case FRAG_RESULT_DEPTH:
212bf215546Sopenharmony_ci      return ppir_output_depth;
213bf215546Sopenharmony_ci   default:
214bf215546Sopenharmony_ci      return ppir_output_invalid;
215bf215546Sopenharmony_ci   }
216bf215546Sopenharmony_ci}
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_citypedef struct ppir_reg {
219bf215546Sopenharmony_ci   struct list_head list;
220bf215546Sopenharmony_ci   int index;
221bf215546Sopenharmony_ci   ppir_output_type out_type;
222bf215546Sopenharmony_ci   int regalloc_index;
223bf215546Sopenharmony_ci   int num_components;
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   /* whether this reg has to start from the x component
226bf215546Sopenharmony_ci    * of a full physical reg, this is true for reg used
227bf215546Sopenharmony_ci    * in load/store instr which has no swizzle field */
228bf215546Sopenharmony_ci   bool is_head;
229bf215546Sopenharmony_ci   bool spilled;
230bf215546Sopenharmony_ci   bool undef;
231bf215546Sopenharmony_ci   bool out_reg;
232bf215546Sopenharmony_ci} ppir_reg;
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_citypedef enum {
235bf215546Sopenharmony_ci   ppir_target_ssa,
236bf215546Sopenharmony_ci   ppir_target_pipeline,
237bf215546Sopenharmony_ci   ppir_target_register,
238bf215546Sopenharmony_ci} ppir_target;
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_citypedef struct ppir_src {
241bf215546Sopenharmony_ci   ppir_target type;
242bf215546Sopenharmony_ci   ppir_node *node;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   union {
245bf215546Sopenharmony_ci      ppir_reg *ssa;
246bf215546Sopenharmony_ci      ppir_reg *reg;
247bf215546Sopenharmony_ci      ppir_pipeline pipeline;
248bf215546Sopenharmony_ci   };
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   uint8_t swizzle[4];
251bf215546Sopenharmony_ci   bool absolute, negate;
252bf215546Sopenharmony_ci} ppir_src;
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_citypedef enum {
255bf215546Sopenharmony_ci   ppir_outmod_none,
256bf215546Sopenharmony_ci   ppir_outmod_clamp_fraction,
257bf215546Sopenharmony_ci   ppir_outmod_clamp_positive,
258bf215546Sopenharmony_ci   ppir_outmod_round,
259bf215546Sopenharmony_ci} ppir_outmod;
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_citypedef struct ppir_dest {
262bf215546Sopenharmony_ci   ppir_target type;
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci   union {
265bf215546Sopenharmony_ci      ppir_reg ssa;
266bf215546Sopenharmony_ci      ppir_reg *reg;
267bf215546Sopenharmony_ci      ppir_pipeline pipeline;
268bf215546Sopenharmony_ci   };
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci   ppir_outmod modifier;
271bf215546Sopenharmony_ci   unsigned write_mask : 4;
272bf215546Sopenharmony_ci} ppir_dest;
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_citypedef struct {
275bf215546Sopenharmony_ci   ppir_node node;
276bf215546Sopenharmony_ci   ppir_dest dest;
277bf215546Sopenharmony_ci   ppir_src src[3];
278bf215546Sopenharmony_ci   int num_src;
279bf215546Sopenharmony_ci   int shift : 3; /* Only used for ppir_op_mul */
280bf215546Sopenharmony_ci} ppir_alu_node;
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_citypedef struct ppir_const {
283bf215546Sopenharmony_ci   union fi value[4];
284bf215546Sopenharmony_ci   int num;
285bf215546Sopenharmony_ci} ppir_const;
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_citypedef struct {
288bf215546Sopenharmony_ci   ppir_node node;
289bf215546Sopenharmony_ci   ppir_const constant;
290bf215546Sopenharmony_ci   ppir_dest dest;
291bf215546Sopenharmony_ci} ppir_const_node;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_citypedef enum {
294bf215546Sopenharmony_ci   ppir_perspective_none = 0,
295bf215546Sopenharmony_ci   ppir_perspective_z,
296bf215546Sopenharmony_ci   ppir_perspective_w,
297bf215546Sopenharmony_ci} ppir_perspective;
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_citypedef struct {
300bf215546Sopenharmony_ci   ppir_node node;
301bf215546Sopenharmony_ci   int index;
302bf215546Sopenharmony_ci   int num_components;
303bf215546Sopenharmony_ci   ppir_dest dest;
304bf215546Sopenharmony_ci   ppir_src src;
305bf215546Sopenharmony_ci   int num_src;
306bf215546Sopenharmony_ci   ppir_perspective perspective;
307bf215546Sopenharmony_ci   int sampler_dim;
308bf215546Sopenharmony_ci} ppir_load_node;
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_citypedef struct {
311bf215546Sopenharmony_ci   ppir_node node;
312bf215546Sopenharmony_ci   int index;
313bf215546Sopenharmony_ci   int num_components;
314bf215546Sopenharmony_ci   ppir_src src;
315bf215546Sopenharmony_ci} ppir_store_node;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_citypedef struct {
318bf215546Sopenharmony_ci   ppir_node node;
319bf215546Sopenharmony_ci   ppir_dest dest;
320bf215546Sopenharmony_ci   ppir_src src[2];
321bf215546Sopenharmony_ci   int num_src;
322bf215546Sopenharmony_ci   int sampler;
323bf215546Sopenharmony_ci   int sampler_dim;
324bf215546Sopenharmony_ci   bool lod_bias_en;
325bf215546Sopenharmony_ci   bool explicit_lod;
326bf215546Sopenharmony_ci} ppir_load_texture_node;
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_citypedef struct {
329bf215546Sopenharmony_ci   ppir_node node;
330bf215546Sopenharmony_ci} ppir_discard_node;
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_cienum ppir_instr_slot {
333bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_VARYING,
334bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_TEXLD,
335bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_UNIFORM,
336bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_ALU_VEC_MUL,
337bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_ALU_SCL_MUL,
338bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_ALU_VEC_ADD,
339bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_ALU_SCL_ADD,
340bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_ALU_COMBINE,
341bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_STORE_TEMP,
342bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_BRANCH,
343bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_NUM,
344bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_END,
345bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_ALU_START = PPIR_INSTR_SLOT_ALU_VEC_MUL,
346bf215546Sopenharmony_ci   PPIR_INSTR_SLOT_ALU_END = PPIR_INSTR_SLOT_ALU_COMBINE,
347bf215546Sopenharmony_ci};
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_citypedef struct ppir_instr {
350bf215546Sopenharmony_ci   struct list_head list;
351bf215546Sopenharmony_ci   int index;
352bf215546Sopenharmony_ci   bool printed;
353bf215546Sopenharmony_ci   int seq; /* command sequence after schedule */
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   ppir_node *slots[PPIR_INSTR_SLOT_NUM];
356bf215546Sopenharmony_ci   ppir_const constant[2];
357bf215546Sopenharmony_ci   bool stop;
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   /* for scheduler */
360bf215546Sopenharmony_ci   struct list_head succ_list;
361bf215546Sopenharmony_ci   struct list_head pred_list;
362bf215546Sopenharmony_ci   float reg_pressure;
363bf215546Sopenharmony_ci   int est; /* earliest start time */
364bf215546Sopenharmony_ci   int parent_index;
365bf215546Sopenharmony_ci   bool scheduled;
366bf215546Sopenharmony_ci   int offset;
367bf215546Sopenharmony_ci   int encode_size;
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci   /* for liveness analysis */
370bf215546Sopenharmony_ci   BITSET_WORD *live_set;
371bf215546Sopenharmony_ci   uint8_t *live_mask; /* mask for non-ssa registers */
372bf215546Sopenharmony_ci   /* live_internal is to mark registers only live within an
373bf215546Sopenharmony_ci    * instruction, without propagation */
374bf215546Sopenharmony_ci   BITSET_WORD *live_internal;
375bf215546Sopenharmony_ci} ppir_instr;
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_citypedef struct ppir_block {
378bf215546Sopenharmony_ci   struct list_head list;
379bf215546Sopenharmony_ci   struct list_head node_list;
380bf215546Sopenharmony_ci   struct list_head instr_list;
381bf215546Sopenharmony_ci   bool stop;
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci   struct ppir_block *successors[2];
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   struct ppir_compiler *comp;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   /* for scheduler */
388bf215546Sopenharmony_ci   int sched_instr_index;
389bf215546Sopenharmony_ci   int sched_instr_base;
390bf215546Sopenharmony_ci   int index;
391bf215546Sopenharmony_ci} ppir_block;
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_citypedef struct {
394bf215546Sopenharmony_ci   ppir_node node;
395bf215546Sopenharmony_ci   ppir_src src[2];
396bf215546Sopenharmony_ci   int num_src;
397bf215546Sopenharmony_ci   bool cond_gt;
398bf215546Sopenharmony_ci   bool cond_eq;
399bf215546Sopenharmony_ci   bool cond_lt;
400bf215546Sopenharmony_ci   bool negate;
401bf215546Sopenharmony_ci   ppir_block *target;
402bf215546Sopenharmony_ci} ppir_branch_node;
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_cistruct ra_regs;
405bf215546Sopenharmony_cistruct lima_fs_compiled_shader;
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_citypedef struct ppir_compiler {
408bf215546Sopenharmony_ci   struct list_head block_list;
409bf215546Sopenharmony_ci   struct hash_table_u64 *blocks;
410bf215546Sopenharmony_ci   int cur_index;
411bf215546Sopenharmony_ci   int cur_instr_index;
412bf215546Sopenharmony_ci   int *out_type_to_reg;
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   struct list_head reg_list;
415bf215546Sopenharmony_ci   int reg_num;
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_ci   /* array for searching ssa/reg node */
418bf215546Sopenharmony_ci   ppir_node **var_nodes;
419bf215546Sopenharmony_ci   unsigned reg_base;
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci   struct ra_regs *ra;
422bf215546Sopenharmony_ci   struct lima_fs_compiled_shader *prog;
423bf215546Sopenharmony_ci   bool uses_discard;
424bf215546Sopenharmony_ci   bool dual_source_blend;
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   /* for scheduler */
427bf215546Sopenharmony_ci   int sched_instr_base;
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   /* for regalloc spilling debug */
430bf215546Sopenharmony_ci   int force_spilling;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci   /* shaderdb */
433bf215546Sopenharmony_ci   int num_loops;
434bf215546Sopenharmony_ci   int num_spills;
435bf215546Sopenharmony_ci   int num_fills;
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci   ppir_block *discard_block;
438bf215546Sopenharmony_ci   ppir_block *current_block;
439bf215546Sopenharmony_ci   ppir_block *loop_break_block;
440bf215546Sopenharmony_ci   ppir_block *loop_cont_block;
441bf215546Sopenharmony_ci} ppir_compiler;
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_civoid *ppir_node_create(ppir_block *block, ppir_op op, int index, unsigned mask);
444bf215546Sopenharmony_civoid ppir_node_add_dep(ppir_node *succ, ppir_node *pred, ppir_dep_type type);
445bf215546Sopenharmony_civoid ppir_node_remove_dep(ppir_dep *dep);
446bf215546Sopenharmony_civoid ppir_node_delete(ppir_node *node);
447bf215546Sopenharmony_civoid ppir_node_print_prog(ppir_compiler *comp);
448bf215546Sopenharmony_civoid ppir_node_replace_child(ppir_node *parent, ppir_node *old_child, ppir_node *new_child);
449bf215546Sopenharmony_civoid ppir_node_replace_all_succ(ppir_node *dst, ppir_node *src);
450bf215546Sopenharmony_civoid ppir_node_replace_pred(ppir_dep *dep, ppir_node *new_pred);
451bf215546Sopenharmony_cippir_dep *ppir_dep_for_pred(ppir_node *node, ppir_node *pred);
452bf215546Sopenharmony_ci/* Assumes that node successors are in the same block */
453bf215546Sopenharmony_cippir_node *ppir_node_insert_mov(ppir_node *node);
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_cistatic inline bool ppir_node_is_root(ppir_node *node)
456bf215546Sopenharmony_ci{
457bf215546Sopenharmony_ci   return list_is_empty(&node->succ_list);
458bf215546Sopenharmony_ci}
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_cistatic inline bool ppir_node_is_leaf(ppir_node *node)
461bf215546Sopenharmony_ci{
462bf215546Sopenharmony_ci   return list_is_empty(&node->pred_list);
463bf215546Sopenharmony_ci}
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_cistatic inline bool ppir_node_has_single_succ(ppir_node *node)
466bf215546Sopenharmony_ci{
467bf215546Sopenharmony_ci   return list_is_singular(&node->succ_list)
468bf215546Sopenharmony_ci      && !node->succ_different_block;
469bf215546Sopenharmony_ci}
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_cibool ppir_node_has_single_src_succ(ppir_node *node);
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_cistatic inline ppir_node *ppir_node_first_succ(ppir_node *node)
474bf215546Sopenharmony_ci{
475bf215546Sopenharmony_ci   return list_first_entry(&node->succ_list, ppir_dep, succ_link)->succ;
476bf215546Sopenharmony_ci}
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_cistatic inline bool ppir_node_has_single_pred(ppir_node *node)
479bf215546Sopenharmony_ci{
480bf215546Sopenharmony_ci   return list_is_singular(&node->pred_list);
481bf215546Sopenharmony_ci}
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_cistatic inline ppir_node *ppir_node_first_pred(ppir_node *node)
484bf215546Sopenharmony_ci{
485bf215546Sopenharmony_ci   return list_first_entry(&node->pred_list, ppir_dep, pred_link)->pred;
486bf215546Sopenharmony_ci}
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci#define ppir_node_foreach_succ(node, dep) \
489bf215546Sopenharmony_ci   list_for_each_entry(ppir_dep, dep, &node->succ_list, succ_link)
490bf215546Sopenharmony_ci#define ppir_node_foreach_succ_safe(node, dep) \
491bf215546Sopenharmony_ci   list_for_each_entry_safe(ppir_dep, dep, &node->succ_list, succ_link)
492bf215546Sopenharmony_ci#define ppir_node_foreach_pred(node, dep) \
493bf215546Sopenharmony_ci   list_for_each_entry(ppir_dep, dep, &node->pred_list, pred_link)
494bf215546Sopenharmony_ci#define ppir_node_foreach_pred_safe(node, dep) \
495bf215546Sopenharmony_ci   list_for_each_entry_safe(ppir_dep, dep, &node->pred_list, pred_link)
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci#define ppir_node_to_alu(node) ((ppir_alu_node *)(node))
498bf215546Sopenharmony_ci#define ppir_node_to_const(node) ((ppir_const_node *)(node))
499bf215546Sopenharmony_ci#define ppir_node_to_load(node) ((ppir_load_node *)(node))
500bf215546Sopenharmony_ci#define ppir_node_to_store(node) ((ppir_store_node *)(node))
501bf215546Sopenharmony_ci#define ppir_node_to_load_texture(node) ((ppir_load_texture_node *)(node))
502bf215546Sopenharmony_ci#define ppir_node_to_discard(node) ((ppir_discard_node *)(node))
503bf215546Sopenharmony_ci#define ppir_node_to_branch(node) ((ppir_branch_node *)(node))
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_cistatic inline ppir_dest *ppir_node_get_dest(ppir_node *node)
506bf215546Sopenharmony_ci{
507bf215546Sopenharmony_ci   assert(node);
508bf215546Sopenharmony_ci   switch (node->type) {
509bf215546Sopenharmony_ci   case ppir_node_type_alu:
510bf215546Sopenharmony_ci      return &ppir_node_to_alu(node)->dest;
511bf215546Sopenharmony_ci   case ppir_node_type_load:
512bf215546Sopenharmony_ci      return &ppir_node_to_load(node)->dest;
513bf215546Sopenharmony_ci   case ppir_node_type_const:
514bf215546Sopenharmony_ci      return &ppir_node_to_const(node)->dest;
515bf215546Sopenharmony_ci   case ppir_node_type_load_texture:
516bf215546Sopenharmony_ci      return &ppir_node_to_load_texture(node)->dest;
517bf215546Sopenharmony_ci   default:
518bf215546Sopenharmony_ci      return NULL;
519bf215546Sopenharmony_ci   }
520bf215546Sopenharmony_ci}
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_cistatic inline int ppir_node_get_src_num(ppir_node *node)
523bf215546Sopenharmony_ci{
524bf215546Sopenharmony_ci   assert(node);
525bf215546Sopenharmony_ci   switch (node->type) {
526bf215546Sopenharmony_ci   case ppir_node_type_alu:
527bf215546Sopenharmony_ci      return ppir_node_to_alu(node)->num_src;
528bf215546Sopenharmony_ci   case ppir_node_type_branch:
529bf215546Sopenharmony_ci      return ppir_node_to_branch(node)->num_src;
530bf215546Sopenharmony_ci   case ppir_node_type_load:
531bf215546Sopenharmony_ci      return ppir_node_to_load(node)->num_src;
532bf215546Sopenharmony_ci   case ppir_node_type_load_texture:
533bf215546Sopenharmony_ci      return ppir_node_to_load_texture(node)->num_src;
534bf215546Sopenharmony_ci   case ppir_node_type_store:
535bf215546Sopenharmony_ci      return 1;
536bf215546Sopenharmony_ci   default:
537bf215546Sopenharmony_ci      return 0;
538bf215546Sopenharmony_ci   }
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci   return 0;
541bf215546Sopenharmony_ci}
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_cistatic inline ppir_src *ppir_node_get_src(ppir_node *node, int idx)
544bf215546Sopenharmony_ci{
545bf215546Sopenharmony_ci   if (idx < 0 || idx >= ppir_node_get_src_num(node))
546bf215546Sopenharmony_ci      return NULL;
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci   switch (node->type) {
549bf215546Sopenharmony_ci   case ppir_node_type_alu:
550bf215546Sopenharmony_ci      return &ppir_node_to_alu(node)->src[idx];
551bf215546Sopenharmony_ci   case ppir_node_type_branch:
552bf215546Sopenharmony_ci      return &ppir_node_to_branch(node)->src[idx];
553bf215546Sopenharmony_ci   case ppir_node_type_load_texture:
554bf215546Sopenharmony_ci      return &ppir_node_to_load_texture(node)->src[idx];
555bf215546Sopenharmony_ci   case ppir_node_type_load:
556bf215546Sopenharmony_ci      return &ppir_node_to_load(node)->src;
557bf215546Sopenharmony_ci   case ppir_node_type_store:
558bf215546Sopenharmony_ci      return &ppir_node_to_store(node)->src;
559bf215546Sopenharmony_ci   default:
560bf215546Sopenharmony_ci      break;
561bf215546Sopenharmony_ci   }
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci   return NULL;
564bf215546Sopenharmony_ci}
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_cistatic inline ppir_reg *ppir_src_get_reg(ppir_src *src)
567bf215546Sopenharmony_ci{
568bf215546Sopenharmony_ci   switch (src->type) {
569bf215546Sopenharmony_ci   case ppir_target_ssa:
570bf215546Sopenharmony_ci      return src->ssa;
571bf215546Sopenharmony_ci   case ppir_target_register:
572bf215546Sopenharmony_ci      return src->reg;
573bf215546Sopenharmony_ci   default:
574bf215546Sopenharmony_ci      return NULL;
575bf215546Sopenharmony_ci   }
576bf215546Sopenharmony_ci}
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_cistatic inline ppir_reg *ppir_dest_get_reg(ppir_dest *dest)
579bf215546Sopenharmony_ci{
580bf215546Sopenharmony_ci   switch (dest->type) {
581bf215546Sopenharmony_ci   case ppir_target_ssa:
582bf215546Sopenharmony_ci      return &dest->ssa;
583bf215546Sopenharmony_ci   case ppir_target_register:
584bf215546Sopenharmony_ci      return dest->reg;
585bf215546Sopenharmony_ci   default:
586bf215546Sopenharmony_ci      return NULL;
587bf215546Sopenharmony_ci   }
588bf215546Sopenharmony_ci}
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_cistatic inline void ppir_node_target_assign(ppir_src *src, ppir_node *node)
591bf215546Sopenharmony_ci{
592bf215546Sopenharmony_ci   ppir_dest *dest = ppir_node_get_dest(node);
593bf215546Sopenharmony_ci   src->type = dest->type;
594bf215546Sopenharmony_ci   switch (src->type) {
595bf215546Sopenharmony_ci   case ppir_target_ssa:
596bf215546Sopenharmony_ci      src->ssa = &dest->ssa;
597bf215546Sopenharmony_ci      src->node = node;
598bf215546Sopenharmony_ci      break;
599bf215546Sopenharmony_ci   case ppir_target_register:
600bf215546Sopenharmony_ci      src->reg = dest->reg;
601bf215546Sopenharmony_ci      /* Registers can be assigned from multiple nodes, so don't keep
602bf215546Sopenharmony_ci       * pointer to the node here
603bf215546Sopenharmony_ci       */
604bf215546Sopenharmony_ci      src->node = NULL;
605bf215546Sopenharmony_ci      break;
606bf215546Sopenharmony_ci   case ppir_target_pipeline:
607bf215546Sopenharmony_ci      src->pipeline = dest->pipeline;
608bf215546Sopenharmony_ci      src->node = node;
609bf215546Sopenharmony_ci      break;
610bf215546Sopenharmony_ci   }
611bf215546Sopenharmony_ci}
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_cistatic inline bool ppir_node_target_equal(ppir_src *src, ppir_dest *dest)
614bf215546Sopenharmony_ci{
615bf215546Sopenharmony_ci   if (src->type != dest->type ||
616bf215546Sopenharmony_ci       (src->type == ppir_target_ssa && src->ssa != &dest->ssa) ||
617bf215546Sopenharmony_ci       (src->type == ppir_target_register && src->reg != dest->reg) ||
618bf215546Sopenharmony_ci       (src->type == ppir_target_pipeline && src->pipeline != dest->pipeline))
619bf215546Sopenharmony_ci      return false;
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci   return true;
622bf215546Sopenharmony_ci}
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_cistatic inline int ppir_target_get_src_reg_index(ppir_src *src)
625bf215546Sopenharmony_ci{
626bf215546Sopenharmony_ci   switch (src->type) {
627bf215546Sopenharmony_ci   case ppir_target_ssa:
628bf215546Sopenharmony_ci      if (src->ssa)
629bf215546Sopenharmony_ci         return src->ssa->index;
630bf215546Sopenharmony_ci      break;
631bf215546Sopenharmony_ci   case ppir_target_register:
632bf215546Sopenharmony_ci      if (src->reg)
633bf215546Sopenharmony_ci         return src->reg->index;
634bf215546Sopenharmony_ci      break;
635bf215546Sopenharmony_ci   case ppir_target_pipeline:
636bf215546Sopenharmony_ci      if (src->pipeline == ppir_pipeline_reg_discard)
637bf215546Sopenharmony_ci         return 15 * 4;
638bf215546Sopenharmony_ci      return (src->pipeline + 12) * 4;
639bf215546Sopenharmony_ci   }
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci   return -1;
642bf215546Sopenharmony_ci}
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_cistatic inline int ppir_target_get_dest_reg_index(ppir_dest *dest)
645bf215546Sopenharmony_ci{
646bf215546Sopenharmony_ci   switch (dest->type) {
647bf215546Sopenharmony_ci   case ppir_target_ssa:
648bf215546Sopenharmony_ci      return dest->ssa.index;
649bf215546Sopenharmony_ci   case ppir_target_register:
650bf215546Sopenharmony_ci      return dest->reg->index;
651bf215546Sopenharmony_ci   case ppir_target_pipeline:
652bf215546Sopenharmony_ci      if (dest->pipeline == ppir_pipeline_reg_discard)
653bf215546Sopenharmony_ci         return 15 * 4;
654bf215546Sopenharmony_ci      return (dest->pipeline + 12) * 4;
655bf215546Sopenharmony_ci   }
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci   return -1;
658bf215546Sopenharmony_ci}
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_cistatic inline int ppir_src_get_mask(ppir_src *src)
661bf215546Sopenharmony_ci{
662bf215546Sopenharmony_ci   ppir_reg *reg = ppir_src_get_reg(src);
663bf215546Sopenharmony_ci   int mask = 0;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   for (int i = 0; i < reg->num_components; i++)
666bf215546Sopenharmony_ci      mask |= (1 << src->swizzle[i]);
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   return mask;
669bf215546Sopenharmony_ci}
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_cistatic inline bool ppir_target_is_scalar(ppir_dest *dest)
672bf215546Sopenharmony_ci{
673bf215546Sopenharmony_ci   switch (dest->type) {
674bf215546Sopenharmony_ci   case ppir_target_ssa:
675bf215546Sopenharmony_ci      return dest->ssa.num_components == 1;
676bf215546Sopenharmony_ci   case ppir_target_register:
677bf215546Sopenharmony_ci      /* only one bit in mask is set */
678bf215546Sopenharmony_ci      if ((dest->write_mask & 0x3) == 0x3 ||
679bf215546Sopenharmony_ci          (dest->write_mask & 0x5) == 0x5 ||
680bf215546Sopenharmony_ci          (dest->write_mask & 0x9) == 0x9 ||
681bf215546Sopenharmony_ci          (dest->write_mask & 0x6) == 0x6 ||
682bf215546Sopenharmony_ci          (dest->write_mask & 0xa) == 0xa ||
683bf215546Sopenharmony_ci          (dest->write_mask & 0xc) == 0xc)
684bf215546Sopenharmony_ci         return false;
685bf215546Sopenharmony_ci      else
686bf215546Sopenharmony_ci         return true;
687bf215546Sopenharmony_ci   case ppir_target_pipeline:
688bf215546Sopenharmony_ci      if (dest->pipeline == ppir_pipeline_reg_fmul)
689bf215546Sopenharmony_ci         return true;
690bf215546Sopenharmony_ci      else
691bf215546Sopenharmony_ci         return false;
692bf215546Sopenharmony_ci   default:
693bf215546Sopenharmony_ci      return false;
694bf215546Sopenharmony_ci   }
695bf215546Sopenharmony_ci}
696bf215546Sopenharmony_ci
697bf215546Sopenharmony_cistatic inline bool ppir_node_schedulable_slot(ppir_node *node,
698bf215546Sopenharmony_ci                                              enum ppir_instr_slot slot)
699bf215546Sopenharmony_ci{
700bf215546Sopenharmony_ci   int *slots = ppir_op_infos[node->op].slots;
701bf215546Sopenharmony_ci   for (int i = 0; slots[i] != PPIR_INSTR_SLOT_END; i++)
702bf215546Sopenharmony_ci      if (slots[i] == slot)
703bf215546Sopenharmony_ci         return true;
704bf215546Sopenharmony_ci
705bf215546Sopenharmony_ci   return false;
706bf215546Sopenharmony_ci}
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_cippir_instr *ppir_instr_create(ppir_block *block);
709bf215546Sopenharmony_cibool ppir_instr_insert_node(ppir_instr *instr, ppir_node *node);
710bf215546Sopenharmony_civoid ppir_instr_add_dep(ppir_instr *succ, ppir_instr *pred);
711bf215546Sopenharmony_civoid ppir_instr_print_list(ppir_compiler *comp);
712bf215546Sopenharmony_civoid ppir_instr_print_dep(ppir_compiler *comp);
713bf215546Sopenharmony_civoid ppir_instr_insert_mul_node(ppir_node *add, ppir_node *mul);
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci#define ppir_instr_foreach_succ(instr, dep) \
716bf215546Sopenharmony_ci   list_for_each_entry(ppir_dep, dep, &instr->succ_list, succ_link)
717bf215546Sopenharmony_ci#define ppir_instr_foreach_succ_safe(instr, dep) \
718bf215546Sopenharmony_ci   list_for_each_entry_safe(ppir_dep, dep, &instr->succ_list, succ_link)
719bf215546Sopenharmony_ci#define ppir_instr_foreach_pred(instr, dep) \
720bf215546Sopenharmony_ci   list_for_each_entry(ppir_dep, dep, &instr->pred_list, pred_link)
721bf215546Sopenharmony_ci#define ppir_instr_foreach_pred_safe(instr, dep) \
722bf215546Sopenharmony_ci   list_for_each_entry_safe(ppir_dep, dep, &instr->pred_list, pred_link)
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_cistatic inline bool ppir_instr_is_root(ppir_instr *instr)
725bf215546Sopenharmony_ci{
726bf215546Sopenharmony_ci   return list_is_empty(&instr->succ_list);
727bf215546Sopenharmony_ci}
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_cistatic inline bool ppir_instr_is_leaf(ppir_instr *instr)
730bf215546Sopenharmony_ci{
731bf215546Sopenharmony_ci   return list_is_empty(&instr->pred_list);
732bf215546Sopenharmony_ci}
733bf215546Sopenharmony_ci
734bf215546Sopenharmony_cibool ppir_lower_prog(ppir_compiler *comp);
735bf215546Sopenharmony_cibool ppir_node_to_instr(ppir_compiler *comp);
736bf215546Sopenharmony_cibool ppir_schedule_prog(ppir_compiler *comp);
737bf215546Sopenharmony_cibool ppir_regalloc_prog(ppir_compiler *comp);
738bf215546Sopenharmony_cibool ppir_codegen_prog(ppir_compiler *comp);
739bf215546Sopenharmony_civoid ppir_liveness_analysis(ppir_compiler *comp);
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_cistatic inline unsigned int reg_mask_size(unsigned int num_reg)
742bf215546Sopenharmony_ci{
743bf215546Sopenharmony_ci   return (num_reg + 1) / 2;
744bf215546Sopenharmony_ci}
745bf215546Sopenharmony_ci
746bf215546Sopenharmony_cistatic inline uint8_t get_reg_mask(uint8_t *set, unsigned index)
747bf215546Sopenharmony_ci{
748bf215546Sopenharmony_ci   unsigned int i = index / 2;
749bf215546Sopenharmony_ci   unsigned int shift = index % 2 ? 4 : 0;
750bf215546Sopenharmony_ci   uint8_t mask = 0x0f << shift;
751bf215546Sopenharmony_ci   return (set[i] & mask) >> shift;
752bf215546Sopenharmony_ci}
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_cistatic inline void set_reg_mask(uint8_t *set, unsigned int index, uint8_t bits)
755bf215546Sopenharmony_ci{
756bf215546Sopenharmony_ci   unsigned int i = index / 2;
757bf215546Sopenharmony_ci   unsigned int shift = index % 2 ? 4 : 0;
758bf215546Sopenharmony_ci   uint8_t mask = 0x0f << shift;
759bf215546Sopenharmony_ci   set[i] &= ~mask;
760bf215546Sopenharmony_ci   set[i] |= (bits << shift);
761bf215546Sopenharmony_ci}
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_ci#endif
764