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