xref: /aosp_15_r20/external/mesa3d/src/imagination/rogue/rogue_builder.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Imagination Technologies Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include "rogue.h"
25 #include "rogue_builder.h"
26 #include "util/macros.h"
27 
28 /**
29  * \file rogue_builder.c
30  *
31  * \brief Contains helper functions for building Rogue shaders.
32  */
33 
34 /**
35  * \brief Inserts an instruction at the current builder context position.
36  *
37  * \param[in] b The builder context.
38  * \param[in] instr The instruction to insert.
39  */
rogue_builder_insert_instr(rogue_builder * b,rogue_instr * instr)40 static inline void rogue_builder_insert_instr(rogue_builder *b,
41                                               rogue_instr *instr)
42 {
43    rogue_instr_insert(instr, b->cursor);
44    b->cursor = rogue_cursor_after_instr(instr);
45 }
46 
47 /* ALU instructions */
48 
rogue_build_alu(rogue_builder * b,enum rogue_alu_op op,unsigned num_dsts,rogue_ref dsts[num_dsts],unsigned num_srcs,rogue_ref srcs[num_srcs])49 static inline rogue_alu_instr *rogue_build_alu(rogue_builder *b,
50                                                enum rogue_alu_op op,
51                                                unsigned num_dsts,
52                                                rogue_ref dsts[num_dsts],
53                                                unsigned num_srcs,
54                                                rogue_ref srcs[num_srcs])
55 {
56    rogue_alu_instr *alu =
57       rogue_alu_instr_create(rogue_cursor_block(b->cursor), op);
58 
59    for (unsigned i = 0; i < num_dsts; ++i) {
60       alu->dst[i].ref = dsts[i];
61       alu->dst[i].index = i;
62    }
63 
64    for (unsigned i = 0; i < num_srcs; ++i) {
65       alu->src[i].ref = srcs[i];
66       alu->src[i].index = i;
67    }
68 
69    rogue_builder_insert_instr(b, &alu->instr);
70    return alu;
71 }
72 
rogue_build_alu11(rogue_builder * b,enum rogue_alu_op op,rogue_ref dst0,rogue_ref src0)73 static inline rogue_alu_instr *rogue_build_alu11(rogue_builder *b,
74                                                  enum rogue_alu_op op,
75                                                  rogue_ref dst0,
76                                                  rogue_ref src0)
77 {
78    rogue_ref dsts[] = { dst0 };
79    rogue_ref srcs[] = { src0 };
80    return rogue_build_alu(b, op, 1, dsts, 1, srcs);
81 }
82 
rogue_build_alu12(rogue_builder * b,enum rogue_alu_op op,rogue_ref dst0,rogue_ref src0,rogue_ref src1)83 static inline rogue_alu_instr *rogue_build_alu12(rogue_builder *b,
84                                                  enum rogue_alu_op op,
85                                                  rogue_ref dst0,
86                                                  rogue_ref src0,
87                                                  rogue_ref src1)
88 {
89    rogue_ref dsts[] = { dst0 };
90    rogue_ref srcs[] = { src0, src1 };
91    return rogue_build_alu(b, op, 1, dsts, 2, srcs);
92 }
93 
rogue_build_alu13(rogue_builder * b,enum rogue_alu_op op,rogue_ref dst0,rogue_ref src0,rogue_ref src1,rogue_ref src2)94 static inline rogue_alu_instr *rogue_build_alu13(rogue_builder *b,
95                                                  enum rogue_alu_op op,
96                                                  rogue_ref dst0,
97                                                  rogue_ref src0,
98                                                  rogue_ref src1,
99                                                  rogue_ref src2)
100 {
101    rogue_ref dsts[] = { dst0 };
102    rogue_ref srcs[] = { src0, src1, src2 };
103    return rogue_build_alu(b, op, 1, dsts, 3, srcs);
104 }
105 
rogue_build_alu22(rogue_builder * b,enum rogue_alu_op op,rogue_ref dst0,rogue_ref dst1,rogue_ref src0,rogue_ref src1)106 static inline rogue_alu_instr *rogue_build_alu22(rogue_builder *b,
107                                                  enum rogue_alu_op op,
108                                                  rogue_ref dst0,
109                                                  rogue_ref dst1,
110                                                  rogue_ref src0,
111                                                  rogue_ref src1)
112 {
113    rogue_ref dsts[] = { dst0, dst1 };
114    rogue_ref srcs[] = { src0, src1 };
115    return rogue_build_alu(b, op, 2, dsts, 2, srcs);
116 }
117 
rogue_build_alu23(rogue_builder * b,enum rogue_alu_op op,rogue_ref dst0,rogue_ref dst1,rogue_ref src0,rogue_ref src1,rogue_ref src2)118 static inline rogue_alu_instr *rogue_build_alu23(rogue_builder *b,
119                                                  enum rogue_alu_op op,
120                                                  rogue_ref dst0,
121                                                  rogue_ref dst1,
122                                                  rogue_ref src0,
123                                                  rogue_ref src1,
124                                                  rogue_ref src2)
125 {
126    rogue_ref dsts[] = { dst0, dst1 };
127    rogue_ref srcs[] = { src0, src1, src2 };
128    return rogue_build_alu(b, op, 2, dsts, 3, srcs);
129 }
130 
rogue_build_alu35(rogue_builder * b,enum rogue_alu_op op,rogue_ref dst0,rogue_ref dst1,rogue_ref dst2,rogue_ref src0,rogue_ref src1,rogue_ref src2,rogue_ref src3,rogue_ref src4)131 static inline rogue_alu_instr *rogue_build_alu35(rogue_builder *b,
132                                                  enum rogue_alu_op op,
133                                                  rogue_ref dst0,
134                                                  rogue_ref dst1,
135                                                  rogue_ref dst2,
136                                                  rogue_ref src0,
137                                                  rogue_ref src1,
138                                                  rogue_ref src2,
139                                                  rogue_ref src3,
140                                                  rogue_ref src4)
141 {
142    rogue_ref dsts[] = { dst0, dst1, dst2 };
143    rogue_ref srcs[] = { src0, src1, src2, src3, src4 };
144    return rogue_build_alu(b, op, 3, dsts, 5, srcs);
145 }
146 
147 /* TODO: Static inline in rogue.h? */
148 #define ROGUE_BUILDER_DEFINE_ALU11(op)                             \
149    PUBLIC                                                          \
150    rogue_alu_instr *rogue_##op(rogue_builder *b,                   \
151                                rogue_ref dst0,                     \
152                                rogue_ref src0)                     \
153    {                                                               \
154       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \
155       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 1); \
156       return rogue_build_alu11(b, ROGUE_ALU_OP_##op, dst0, src0);  \
157    }
158 
159 #define ROGUE_BUILDER_DEFINE_ALU12(op)                                  \
160    PUBLIC                                                               \
161    rogue_alu_instr *rogue_##op(rogue_builder *b,                        \
162                                rogue_ref dst0,                          \
163                                rogue_ref src0,                          \
164                                rogue_ref src1)                          \
165    {                                                                    \
166       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1);      \
167       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2);      \
168       return rogue_build_alu12(b, ROGUE_ALU_OP_##op, dst0, src0, src1); \
169    }
170 
171 #define ROGUE_BUILDER_DEFINE_ALU13(op)                                        \
172    PUBLIC                                                                     \
173    rogue_alu_instr *rogue_##op(rogue_builder *b,                              \
174                                rogue_ref dst0,                                \
175                                rogue_ref src0,                                \
176                                rogue_ref src1,                                \
177                                rogue_ref src2)                                \
178    {                                                                          \
179       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1);            \
180       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3);            \
181       return rogue_build_alu13(b, ROGUE_ALU_OP_##op, dst0, src0, src1, src2); \
182    }
183 
184 #define ROGUE_BUILDER_DEFINE_ALU22(op)                                        \
185    PUBLIC                                                                     \
186    rogue_alu_instr *rogue_##op(rogue_builder *b,                              \
187                                rogue_ref dst0,                                \
188                                rogue_ref dst1,                                \
189                                rogue_ref src0,                                \
190                                rogue_ref src1)                                \
191    {                                                                          \
192       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 2);            \
193       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2);            \
194       return rogue_build_alu22(b, ROGUE_ALU_OP_##op, dst0, dst1, src0, src1); \
195    }
196 
197 #define ROGUE_BUILDER_DEFINE_ALU23(op)                             \
198    PUBLIC                                                          \
199    rogue_alu_instr *rogue_##op(rogue_builder *b,                   \
200                                rogue_ref dst0,                     \
201                                rogue_ref dst1,                     \
202                                rogue_ref src0,                     \
203                                rogue_ref src1,                     \
204                                rogue_ref src2)                     \
205    {                                                               \
206       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 2); \
207       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \
208       return rogue_build_alu23(b,                                  \
209                                ROGUE_ALU_OP_##op,                  \
210                                dst0,                               \
211                                dst1,                               \
212                                src0,                               \
213                                src1,                               \
214                                src2);                              \
215    }
216 
217 #define ROGUE_BUILDER_DEFINE_ALU35(op)                             \
218    PUBLIC                                                          \
219    rogue_alu_instr *rogue_##op(rogue_builder *b,                   \
220                                rogue_ref dst0,                     \
221                                rogue_ref dst1,                     \
222                                rogue_ref dst2,                     \
223                                rogue_ref src0,                     \
224                                rogue_ref src1,                     \
225                                rogue_ref src2,                     \
226                                rogue_ref src3,                     \
227                                rogue_ref src4)                     \
228    {                                                               \
229       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 3); \
230       assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 5); \
231       return rogue_build_alu35(b,                                  \
232                                ROGUE_ALU_OP_##op,                  \
233                                dst0,                               \
234                                dst1,                               \
235                                dst2,                               \
236                                src0,                               \
237                                src1,                               \
238                                src2,                               \
239                                src3,                               \
240                                src4);                              \
241    }
242 
243 #include "rogue_alu_instrs.def"
244 
rogue_build_backend(rogue_builder * b,enum rogue_backend_op op,unsigned num_dsts,rogue_ref dsts[num_dsts],unsigned num_srcs,rogue_ref srcs[num_srcs])245 static inline rogue_backend_instr *rogue_build_backend(rogue_builder *b,
246                                                        enum rogue_backend_op op,
247                                                        unsigned num_dsts,
248                                                        rogue_ref dsts[num_dsts],
249                                                        unsigned num_srcs,
250                                                        rogue_ref srcs[num_srcs])
251 {
252    rogue_backend_instr *backend =
253       rogue_backend_instr_create(rogue_cursor_block(b->cursor), op);
254 
255    for (unsigned i = 0; i < num_dsts; ++i) {
256       backend->dst[i].ref = dsts[i];
257       backend->dst[i].index = i;
258    }
259 
260    for (unsigned i = 0; i < num_srcs; ++i) {
261       backend->src[i].ref = srcs[i];
262       backend->src[i].index = i;
263    }
264 
265    rogue_builder_insert_instr(b, &backend->instr);
266    return backend;
267 }
268 
269 static inline rogue_backend_instr *
rogue_build_backend00(rogue_builder * b,enum rogue_backend_op op)270 rogue_build_backend00(rogue_builder *b, enum rogue_backend_op op)
271 {
272    return rogue_build_backend(b, op, 0, NULL, 0, NULL);
273 }
274 
275 static inline rogue_backend_instr *
rogue_build_backend02(rogue_builder * b,enum rogue_backend_op op,rogue_ref src0,rogue_ref src1)276 rogue_build_backend02(rogue_builder *b,
277                       enum rogue_backend_op op,
278                       rogue_ref src0,
279                       rogue_ref src1)
280 {
281    rogue_ref srcs[] = { src0, src1 };
282    return rogue_build_backend(b, op, 0, NULL, 2, srcs);
283 }
284 
285 static inline rogue_backend_instr *
rogue_build_backend11(rogue_builder * b,enum rogue_backend_op op,rogue_ref dst0,rogue_ref src0)286 rogue_build_backend11(rogue_builder *b,
287                       enum rogue_backend_op op,
288                       rogue_ref dst0,
289                       rogue_ref src0)
290 {
291    rogue_ref dsts[] = { dst0 };
292    rogue_ref srcs[] = { src0 };
293    return rogue_build_backend(b, op, 1, dsts, 1, srcs);
294 }
295 
296 static inline rogue_backend_instr *
rogue_build_backend13(rogue_builder * b,enum rogue_backend_op op,rogue_ref dst0,rogue_ref src0,rogue_ref src1,rogue_ref src2)297 rogue_build_backend13(rogue_builder *b,
298                       enum rogue_backend_op op,
299                       rogue_ref dst0,
300                       rogue_ref src0,
301                       rogue_ref src1,
302                       rogue_ref src2)
303 {
304    rogue_ref dsts[] = { dst0 };
305    rogue_ref srcs[] = { src0, src1, src2 };
306    return rogue_build_backend(b, op, 1, dsts, 3, srcs);
307 }
308 
309 static inline rogue_backend_instr *
rogue_build_backend14(rogue_builder * b,enum rogue_backend_op op,rogue_ref dst0,rogue_ref src0,rogue_ref src1,rogue_ref src2,rogue_ref src3)310 rogue_build_backend14(rogue_builder *b,
311                       enum rogue_backend_op op,
312                       rogue_ref dst0,
313                       rogue_ref src0,
314                       rogue_ref src1,
315                       rogue_ref src2,
316                       rogue_ref src3)
317 {
318    rogue_ref dsts[] = { dst0 };
319    rogue_ref srcs[] = { src0, src1, src2, src3 };
320    return rogue_build_backend(b, op, 1, dsts, 4, srcs);
321 }
322 
323 static inline rogue_backend_instr *
rogue_build_backend06(rogue_builder * b,enum rogue_backend_op op,rogue_ref src0,rogue_ref src1,rogue_ref src2,rogue_ref src3,rogue_ref src4,rogue_ref src5)324 rogue_build_backend06(rogue_builder *b,
325                       enum rogue_backend_op op,
326                       rogue_ref src0,
327                       rogue_ref src1,
328                       rogue_ref src2,
329                       rogue_ref src3,
330                       rogue_ref src4,
331                       rogue_ref src5)
332 {
333    rogue_ref srcs[] = { src0, src1, src2, src3, src4, src5 };
334    return rogue_build_backend(b, op, 0, NULL, 6, srcs);
335 }
336 
337 static inline rogue_backend_instr *
rogue_build_backend16(rogue_builder * b,enum rogue_backend_op op,rogue_ref dst0,rogue_ref src0,rogue_ref src1,rogue_ref src2,rogue_ref src3,rogue_ref src4,rogue_ref src5)338 rogue_build_backend16(rogue_builder *b,
339                       enum rogue_backend_op op,
340                       rogue_ref dst0,
341                       rogue_ref src0,
342                       rogue_ref src1,
343                       rogue_ref src2,
344                       rogue_ref src3,
345                       rogue_ref src4,
346                       rogue_ref src5)
347 {
348    rogue_ref dsts[] = { dst0 };
349    rogue_ref srcs[] = { src0, src1, src2, src3, src4, src5 };
350    return rogue_build_backend(b, op, 1, dsts, 6, srcs);
351 }
352 
353 #define ROGUE_BUILDER_DEFINE_BACKEND00(op)                                 \
354    PUBLIC                                                                  \
355    rogue_backend_instr *rogue_##op(rogue_builder *b)                       \
356    {                                                                       \
357       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 0); \
358       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 0); \
359       return rogue_build_backend00(b, ROGUE_BACKEND_OP_##op);              \
360    }
361 
362 #define ROGUE_BUILDER_DEFINE_BACKEND02(op)                                 \
363    PUBLIC                                                                  \
364    rogue_backend_instr *rogue_##op(rogue_builder *b,                       \
365                                    rogue_ref src0,                         \
366                                    rogue_ref src1)                         \
367    {                                                                       \
368       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 0); \
369       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 2); \
370       return rogue_build_backend02(b, ROGUE_BACKEND_OP_##op, src0, src1);  \
371    }
372 
373 #define ROGUE_BUILDER_DEFINE_BACKEND11(op)                                 \
374    PUBLIC                                                                  \
375    rogue_backend_instr *rogue_##op(rogue_builder *b,                       \
376                                    rogue_ref dst0,                         \
377                                    rogue_ref src0)                         \
378    {                                                                       \
379       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \
380       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 1); \
381       return rogue_build_backend11(b, ROGUE_BACKEND_OP_##op, dst0, src0);  \
382    }
383 
384 #define ROGUE_BUILDER_DEFINE_BACKEND13(op)                                 \
385    PUBLIC                                                                  \
386    rogue_backend_instr *rogue_##op(rogue_builder *b,                       \
387                                    rogue_ref dst0,                         \
388                                    rogue_ref src0,                         \
389                                    rogue_ref src1,                         \
390                                    rogue_ref src2)                         \
391    {                                                                       \
392       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \
393       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 3); \
394       return rogue_build_backend13(b,                                      \
395                                    ROGUE_BACKEND_OP_##op,                  \
396                                    dst0,                                   \
397                                    src0,                                   \
398                                    src1,                                   \
399                                    src2);                                  \
400    }
401 
402 #define ROGUE_BUILDER_DEFINE_BACKEND14(op)                                 \
403    PUBLIC                                                                  \
404    rogue_backend_instr *rogue_##op(rogue_builder *b,                       \
405                                    rogue_ref dst0,                         \
406                                    rogue_ref src0,                         \
407                                    rogue_ref src1,                         \
408                                    rogue_ref src2,                         \
409                                    rogue_ref src3)                         \
410    {                                                                       \
411       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \
412       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 4); \
413       return rogue_build_backend14(b,                                      \
414                                    ROGUE_BACKEND_OP_##op,                  \
415                                    dst0,                                   \
416                                    src0,                                   \
417                                    src1,                                   \
418                                    src2,                                   \
419                                    src3);                                  \
420    }
421 
422 #define ROGUE_BUILDER_DEFINE_BACKEND06(op)                                 \
423    PUBLIC                                                                  \
424    rogue_backend_instr *rogue_##op(rogue_builder *b,                       \
425                                    rogue_ref src0,                         \
426                                    rogue_ref src1,                         \
427                                    rogue_ref src2,                         \
428                                    rogue_ref src3,                         \
429                                    rogue_ref src4,                         \
430                                    rogue_ref src5)                         \
431    {                                                                       \
432       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 0); \
433       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 6); \
434       return rogue_build_backend06(b,                                      \
435                                    ROGUE_BACKEND_OP_##op,                  \
436                                    src0,                                   \
437                                    src1,                                   \
438                                    src2,                                   \
439                                    src3,                                   \
440                                    src4,                                   \
441                                    src5);                                  \
442    }
443 
444 #define ROGUE_BUILDER_DEFINE_BACKEND16(op)                                 \
445    PUBLIC                                                                  \
446    rogue_backend_instr *rogue_##op(rogue_builder *b,                       \
447                                    rogue_ref dst0,                         \
448                                    rogue_ref src0,                         \
449                                    rogue_ref src1,                         \
450                                    rogue_ref src2,                         \
451                                    rogue_ref src3,                         \
452                                    rogue_ref src4,                         \
453                                    rogue_ref src5)                         \
454    {                                                                       \
455       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \
456       assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 6); \
457       return rogue_build_backend16(b,                                      \
458                                    ROGUE_BACKEND_OP_##op,                  \
459                                    dst0,                                   \
460                                    src0,                                   \
461                                    src1,                                   \
462                                    src2,                                   \
463                                    src3,                                   \
464                                    src4,                                   \
465                                    src5);                                  \
466    }
467 
468 #include "rogue_backend_instrs.def"
469 
rogue_build_ctrl(rogue_builder * b,enum rogue_ctrl_op op,rogue_block * target_block,unsigned num_dsts,rogue_ref dsts[num_dsts],unsigned num_srcs,rogue_ref srcs[num_srcs])470 static inline rogue_ctrl_instr *rogue_build_ctrl(rogue_builder *b,
471                                                  enum rogue_ctrl_op op,
472                                                  rogue_block *target_block,
473                                                  unsigned num_dsts,
474                                                  rogue_ref dsts[num_dsts],
475                                                  unsigned num_srcs,
476                                                  rogue_ref srcs[num_srcs])
477 {
478    rogue_ctrl_instr *ctrl =
479       rogue_ctrl_instr_create(rogue_cursor_block(b->cursor), op);
480 
481    ctrl->target_block = target_block;
482 
483    for (unsigned i = 0; i < num_dsts; ++i) {
484       ctrl->dst[i].ref = dsts[i];
485       ctrl->dst[i].index = i;
486    }
487 
488    for (unsigned i = 0; i < num_srcs; ++i) {
489       ctrl->src[i].ref = srcs[i];
490       ctrl->src[i].index = i;
491    }
492 
493    rogue_builder_insert_instr(b, &ctrl->instr);
494    return ctrl;
495 }
496 
497 static inline rogue_ctrl_instr *
rogue_build_ctrlb(rogue_builder * b,enum rogue_ctrl_op op,rogue_block * block)498 rogue_build_ctrlb(rogue_builder *b, enum rogue_ctrl_op op, rogue_block *block)
499 {
500    return rogue_build_ctrl(b, op, block, 0, NULL, 0, NULL);
501 }
502 
rogue_build_ctrl00(rogue_builder * b,enum rogue_ctrl_op op)503 static inline rogue_ctrl_instr *rogue_build_ctrl00(rogue_builder *b,
504                                                    enum rogue_ctrl_op op)
505 {
506    return rogue_build_ctrl(b, op, NULL, 0, NULL, 0, NULL);
507 }
508 
509 static inline rogue_ctrl_instr *
rogue_build_ctrl01(rogue_builder * b,enum rogue_ctrl_op op,rogue_ref src0)510 rogue_build_ctrl01(rogue_builder *b, enum rogue_ctrl_op op, rogue_ref src0)
511 {
512    rogue_ref srcs[] = { src0 };
513    return rogue_build_ctrl(b, op, NULL, 0, NULL, 1, srcs);
514 }
515 
516 #define ROGUE_BUILDER_DEFINE_CTRLB(op)                                \
517    PUBLIC                                                             \
518    rogue_ctrl_instr *rogue_##op(rogue_builder *b, rogue_block *block) \
519    {                                                                  \
520       assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].has_target);     \
521       assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_dsts == 0);  \
522       assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_srcs == 0);  \
523       return rogue_build_ctrlb(b, ROGUE_CTRL_OP_##op, block);         \
524    }
525 
526 #define ROGUE_BUILDER_DEFINE_CTRL00(op)                              \
527    PUBLIC                                                            \
528    rogue_ctrl_instr *rogue_##op(rogue_builder *b)                    \
529    {                                                                 \
530       assert(!rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].has_target);   \
531       assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_dsts == 0); \
532       assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_srcs == 0); \
533       return rogue_build_ctrl00(b, ROGUE_CTRL_OP_##op);              \
534    }
535 
536 #define ROGUE_BUILDER_DEFINE_CTRL01(op)                              \
537    PUBLIC                                                            \
538    rogue_ctrl_instr *rogue_##op(rogue_builder *b, rogue_ref src0)    \
539    {                                                                 \
540       assert(!rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].has_target);   \
541       assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_dsts == 0); \
542       assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_srcs == 1); \
543       return rogue_build_ctrl01(b, ROGUE_CTRL_OP_##op, src0);        \
544    }
545 
546 #include "rogue_ctrl_instrs.def"
547 
rogue_build_bitwise(rogue_builder * b,enum rogue_bitwise_op op,unsigned num_dsts,rogue_ref dsts[num_dsts],unsigned num_srcs,rogue_ref srcs[num_srcs])548 static inline rogue_bitwise_instr *rogue_build_bitwise(rogue_builder *b,
549                                                        enum rogue_bitwise_op op,
550                                                        unsigned num_dsts,
551                                                        rogue_ref dsts[num_dsts],
552                                                        unsigned num_srcs,
553                                                        rogue_ref srcs[num_srcs])
554 {
555    rogue_bitwise_instr *bitwise =
556       rogue_bitwise_instr_create(rogue_cursor_block(b->cursor), op);
557 
558    for (unsigned i = 0; i < num_dsts; ++i) {
559       bitwise->dst[i].ref = dsts[i];
560       bitwise->dst[i].index = i;
561    }
562 
563    for (unsigned i = 0; i < num_srcs; ++i) {
564       bitwise->src[i].ref = srcs[i];
565       bitwise->src[i].index = i;
566    }
567 
568    rogue_builder_insert_instr(b, &bitwise->instr);
569    return bitwise;
570 }
571 
572 static inline rogue_bitwise_instr *
rogue_build_bitwise22(rogue_builder * b,enum rogue_bitwise_op op,rogue_ref dst0,rogue_ref dst1,rogue_ref src0,rogue_ref src1)573 rogue_build_bitwise22(rogue_builder *b,
574                       enum rogue_bitwise_op op,
575                       rogue_ref dst0,
576                       rogue_ref dst1,
577                       rogue_ref src0,
578                       rogue_ref src1)
579 {
580    rogue_ref dsts[] = { dst0, dst1 };
581    rogue_ref srcs[] = { src0, src1 };
582    return rogue_build_bitwise(b, op, 2, dsts, 2, srcs);
583 }
584 
585 #define ROGUE_BUILDER_DEFINE_BITWISE22(op)                                 \
586    PUBLIC                                                                  \
587    rogue_bitwise_instr *rogue_##op(rogue_builder *b,                       \
588                                    rogue_ref dst0,                         \
589                                    rogue_ref dst1,                         \
590                                    rogue_ref src0,                         \
591                                    rogue_ref src1)                         \
592    {                                                                       \
593       assert(rogue_bitwise_op_infos[ROGUE_BITWISE_OP_##op].num_dsts == 2); \
594       assert(rogue_bitwise_op_infos[ROGUE_BITWISE_OP_##op].num_srcs == 2); \
595       return rogue_build_bitwise22(b,                                      \
596                                    ROGUE_BITWISE_OP_##op,                  \
597                                    dst0,                                   \
598                                    dst1,                                   \
599                                    src0,                                   \
600                                    src1);                                  \
601    }
602 
603 #include "rogue_bitwise_instrs.def"
604