| /* |
| * Copyright © 2022 Imagination Technologies Ltd. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| */ |
| |
| #include "rogue.h" |
| #include "rogue_builder.h" |
| #include "util/macros.h" |
| |
| /** |
| * \file rogue_builder.c |
| * |
| * \brief Contains helper functions for building Rogue shaders. |
| */ |
| |
| /** |
| * \brief Inserts an instruction at the current builder context position. |
| * |
| * \param[in] b The builder context. |
| * \param[in] instr The instruction to insert. |
| */ |
| static inline void rogue_builder_insert_instr(rogue_builder *b, |
| rogue_instr *instr) |
| { |
| rogue_instr_insert(instr, b->cursor); |
| b->cursor = rogue_cursor_after_instr(instr); |
| } |
| |
| /* ALU instructions */ |
| |
| static inline rogue_alu_instr *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]) |
| { |
| rogue_alu_instr *alu = |
| rogue_alu_instr_create(rogue_cursor_block(b->cursor), op); |
| |
| for (unsigned i = 0; i < num_dsts; ++i) { |
| alu->dst[i].ref = dsts[i]; |
| alu->dst[i].index = i; |
| } |
| |
| for (unsigned i = 0; i < num_srcs; ++i) { |
| alu->src[i].ref = srcs[i]; |
| alu->src[i].index = i; |
| } |
| |
| rogue_builder_insert_instr(b, &alu->instr); |
| return alu; |
| } |
| |
| static inline rogue_alu_instr *rogue_build_alu11(rogue_builder *b, |
| enum rogue_alu_op op, |
| rogue_ref dst0, |
| rogue_ref src0) |
| { |
| rogue_ref dsts[] = { dst0 }; |
| rogue_ref srcs[] = { src0 }; |
| return rogue_build_alu(b, op, 1, dsts, 1, srcs); |
| } |
| |
| static inline rogue_alu_instr *rogue_build_alu12(rogue_builder *b, |
| enum rogue_alu_op op, |
| rogue_ref dst0, |
| rogue_ref src0, |
| rogue_ref src1) |
| { |
| rogue_ref dsts[] = { dst0 }; |
| rogue_ref srcs[] = { src0, src1 }; |
| return rogue_build_alu(b, op, 1, dsts, 2, srcs); |
| } |
| |
| static inline rogue_alu_instr *rogue_build_alu13(rogue_builder *b, |
| enum rogue_alu_op op, |
| rogue_ref dst0, |
| rogue_ref src0, |
| rogue_ref src1, |
| rogue_ref src2) |
| { |
| rogue_ref dsts[] = { dst0 }; |
| rogue_ref srcs[] = { src0, src1, src2 }; |
| return rogue_build_alu(b, op, 1, dsts, 3, srcs); |
| } |
| |
| static inline rogue_alu_instr *rogue_build_alu22(rogue_builder *b, |
| enum rogue_alu_op op, |
| rogue_ref dst0, |
| rogue_ref dst1, |
| rogue_ref src0, |
| rogue_ref src1) |
| { |
| rogue_ref dsts[] = { dst0, dst1 }; |
| rogue_ref srcs[] = { src0, src1 }; |
| return rogue_build_alu(b, op, 2, dsts, 2, srcs); |
| } |
| |
| static inline rogue_alu_instr *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) |
| { |
| rogue_ref dsts[] = { dst0, dst1 }; |
| rogue_ref srcs[] = { src0, src1, src2 }; |
| return rogue_build_alu(b, op, 2, dsts, 3, srcs); |
| } |
| |
| static inline rogue_alu_instr *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) |
| { |
| rogue_ref dsts[] = { dst0, dst1, dst2 }; |
| rogue_ref srcs[] = { src0, src1, src2, src3, src4 }; |
| return rogue_build_alu(b, op, 3, dsts, 5, srcs); |
| } |
| |
| /* TODO: Static inline in rogue.h? */ |
| #define ROGUE_BUILDER_DEFINE_ALU11(op) \ |
| PUBLIC \ |
| rogue_alu_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref src0) \ |
| { \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 1); \ |
| return rogue_build_alu11(b, ROGUE_ALU_OP_##op, dst0, src0); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_ALU12(op) \ |
| PUBLIC \ |
| rogue_alu_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref src0, \ |
| rogue_ref src1) \ |
| { \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \ |
| return rogue_build_alu12(b, ROGUE_ALU_OP_##op, dst0, src0, src1); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_ALU13(op) \ |
| PUBLIC \ |
| rogue_alu_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref src0, \ |
| rogue_ref src1, \ |
| rogue_ref src2) \ |
| { \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \ |
| return rogue_build_alu13(b, ROGUE_ALU_OP_##op, dst0, src0, src1, src2); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_ALU22(op) \ |
| PUBLIC \ |
| rogue_alu_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref dst1, \ |
| rogue_ref src0, \ |
| rogue_ref src1) \ |
| { \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 2); \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \ |
| return rogue_build_alu22(b, ROGUE_ALU_OP_##op, dst0, dst1, src0, src1); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_ALU23(op) \ |
| PUBLIC \ |
| rogue_alu_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref dst1, \ |
| rogue_ref src0, \ |
| rogue_ref src1, \ |
| rogue_ref src2) \ |
| { \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 2); \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \ |
| return rogue_build_alu23(b, \ |
| ROGUE_ALU_OP_##op, \ |
| dst0, \ |
| dst1, \ |
| src0, \ |
| src1, \ |
| src2); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_ALU35(op) \ |
| PUBLIC \ |
| rogue_alu_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref dst1, \ |
| rogue_ref dst2, \ |
| rogue_ref src0, \ |
| rogue_ref src1, \ |
| rogue_ref src2, \ |
| rogue_ref src3, \ |
| rogue_ref src4) \ |
| { \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 3); \ |
| assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 5); \ |
| return rogue_build_alu35(b, \ |
| ROGUE_ALU_OP_##op, \ |
| dst0, \ |
| dst1, \ |
| dst2, \ |
| src0, \ |
| src1, \ |
| src2, \ |
| src3, \ |
| src4); \ |
| } |
| |
| #include "rogue_alu_instrs.def" |
| |
| static inline rogue_backend_instr *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]) |
| { |
| rogue_backend_instr *backend = |
| rogue_backend_instr_create(rogue_cursor_block(b->cursor), op); |
| |
| for (unsigned i = 0; i < num_dsts; ++i) { |
| backend->dst[i].ref = dsts[i]; |
| backend->dst[i].index = i; |
| } |
| |
| for (unsigned i = 0; i < num_srcs; ++i) { |
| backend->src[i].ref = srcs[i]; |
| backend->src[i].index = i; |
| } |
| |
| rogue_builder_insert_instr(b, &backend->instr); |
| return backend; |
| } |
| |
| static inline rogue_backend_instr * |
| rogue_build_backend00(rogue_builder *b, enum rogue_backend_op op) |
| { |
| return rogue_build_backend(b, op, 0, NULL, 0, NULL); |
| } |
| |
| static inline rogue_backend_instr * |
| rogue_build_backend02(rogue_builder *b, |
| enum rogue_backend_op op, |
| rogue_ref src0, |
| rogue_ref src1) |
| { |
| rogue_ref srcs[] = { src0, src1 }; |
| return rogue_build_backend(b, op, 0, NULL, 2, srcs); |
| } |
| |
| static inline rogue_backend_instr * |
| rogue_build_backend11(rogue_builder *b, |
| enum rogue_backend_op op, |
| rogue_ref dst0, |
| rogue_ref src0) |
| { |
| rogue_ref dsts[] = { dst0 }; |
| rogue_ref srcs[] = { src0 }; |
| return rogue_build_backend(b, op, 1, dsts, 1, srcs); |
| } |
| |
| 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) |
| { |
| rogue_ref dsts[] = { dst0 }; |
| rogue_ref srcs[] = { src0, src1, src2 }; |
| return rogue_build_backend(b, op, 1, dsts, 3, srcs); |
| } |
| |
| 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) |
| { |
| rogue_ref dsts[] = { dst0 }; |
| rogue_ref srcs[] = { src0, src1, src2, src3 }; |
| return rogue_build_backend(b, op, 1, dsts, 4, srcs); |
| } |
| |
| 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) |
| { |
| rogue_ref srcs[] = { src0, src1, src2, src3, src4, src5 }; |
| return rogue_build_backend(b, op, 0, NULL, 6, srcs); |
| } |
| |
| 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) |
| { |
| rogue_ref dsts[] = { dst0 }; |
| rogue_ref srcs[] = { src0, src1, src2, src3, src4, src5 }; |
| return rogue_build_backend(b, op, 1, dsts, 6, srcs); |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BACKEND00(op) \ |
| PUBLIC \ |
| rogue_backend_instr *rogue_##op(rogue_builder *b) \ |
| { \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 0); \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 0); \ |
| return rogue_build_backend00(b, ROGUE_BACKEND_OP_##op); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BACKEND02(op) \ |
| PUBLIC \ |
| rogue_backend_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref src0, \ |
| rogue_ref src1) \ |
| { \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 0); \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 2); \ |
| return rogue_build_backend02(b, ROGUE_BACKEND_OP_##op, src0, src1); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BACKEND11(op) \ |
| PUBLIC \ |
| rogue_backend_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref src0) \ |
| { \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 1); \ |
| return rogue_build_backend11(b, ROGUE_BACKEND_OP_##op, dst0, src0); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BACKEND13(op) \ |
| PUBLIC \ |
| rogue_backend_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref src0, \ |
| rogue_ref src1, \ |
| rogue_ref src2) \ |
| { \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 3); \ |
| return rogue_build_backend13(b, \ |
| ROGUE_BACKEND_OP_##op, \ |
| dst0, \ |
| src0, \ |
| src1, \ |
| src2); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BACKEND14(op) \ |
| PUBLIC \ |
| rogue_backend_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref src0, \ |
| rogue_ref src1, \ |
| rogue_ref src2, \ |
| rogue_ref src3) \ |
| { \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 4); \ |
| return rogue_build_backend14(b, \ |
| ROGUE_BACKEND_OP_##op, \ |
| dst0, \ |
| src0, \ |
| src1, \ |
| src2, \ |
| src3); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BACKEND06(op) \ |
| PUBLIC \ |
| rogue_backend_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref src0, \ |
| rogue_ref src1, \ |
| rogue_ref src2, \ |
| rogue_ref src3, \ |
| rogue_ref src4, \ |
| rogue_ref src5) \ |
| { \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 0); \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 6); \ |
| return rogue_build_backend06(b, \ |
| ROGUE_BACKEND_OP_##op, \ |
| src0, \ |
| src1, \ |
| src2, \ |
| src3, \ |
| src4, \ |
| src5); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BACKEND16(op) \ |
| PUBLIC \ |
| rogue_backend_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref src0, \ |
| rogue_ref src1, \ |
| rogue_ref src2, \ |
| rogue_ref src3, \ |
| rogue_ref src4, \ |
| rogue_ref src5) \ |
| { \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_dsts == 1); \ |
| assert(rogue_backend_op_infos[ROGUE_BACKEND_OP_##op].num_srcs == 6); \ |
| return rogue_build_backend16(b, \ |
| ROGUE_BACKEND_OP_##op, \ |
| dst0, \ |
| src0, \ |
| src1, \ |
| src2, \ |
| src3, \ |
| src4, \ |
| src5); \ |
| } |
| |
| #include "rogue_backend_instrs.def" |
| |
| static inline rogue_ctrl_instr *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]) |
| { |
| rogue_ctrl_instr *ctrl = |
| rogue_ctrl_instr_create(rogue_cursor_block(b->cursor), op); |
| |
| ctrl->target_block = target_block; |
| |
| for (unsigned i = 0; i < num_dsts; ++i) { |
| ctrl->dst[i].ref = dsts[i]; |
| ctrl->dst[i].index = i; |
| } |
| |
| for (unsigned i = 0; i < num_srcs; ++i) { |
| ctrl->src[i].ref = srcs[i]; |
| ctrl->src[i].index = i; |
| } |
| |
| rogue_builder_insert_instr(b, &ctrl->instr); |
| return ctrl; |
| } |
| |
| static inline rogue_ctrl_instr * |
| rogue_build_ctrlb(rogue_builder *b, enum rogue_ctrl_op op, rogue_block *block) |
| { |
| return rogue_build_ctrl(b, op, block, 0, NULL, 0, NULL); |
| } |
| |
| static inline rogue_ctrl_instr *rogue_build_ctrl00(rogue_builder *b, |
| enum rogue_ctrl_op op) |
| { |
| return rogue_build_ctrl(b, op, NULL, 0, NULL, 0, NULL); |
| } |
| |
| static inline rogue_ctrl_instr * |
| rogue_build_ctrl01(rogue_builder *b, enum rogue_ctrl_op op, rogue_ref src0) |
| { |
| rogue_ref srcs[] = { src0 }; |
| return rogue_build_ctrl(b, op, NULL, 0, NULL, 1, srcs); |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_CTRLB(op) \ |
| PUBLIC \ |
| rogue_ctrl_instr *rogue_##op(rogue_builder *b, rogue_block *block) \ |
| { \ |
| assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].has_target); \ |
| assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_dsts == 0); \ |
| assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_srcs == 0); \ |
| return rogue_build_ctrlb(b, ROGUE_CTRL_OP_##op, block); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_CTRL00(op) \ |
| PUBLIC \ |
| rogue_ctrl_instr *rogue_##op(rogue_builder *b) \ |
| { \ |
| assert(!rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].has_target); \ |
| assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_dsts == 0); \ |
| assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_srcs == 0); \ |
| return rogue_build_ctrl00(b, ROGUE_CTRL_OP_##op); \ |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_CTRL01(op) \ |
| PUBLIC \ |
| rogue_ctrl_instr *rogue_##op(rogue_builder *b, rogue_ref src0) \ |
| { \ |
| assert(!rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].has_target); \ |
| assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_dsts == 0); \ |
| assert(rogue_ctrl_op_infos[ROGUE_CTRL_OP_##op].num_srcs == 1); \ |
| return rogue_build_ctrl01(b, ROGUE_CTRL_OP_##op, src0); \ |
| } |
| |
| #include "rogue_ctrl_instrs.def" |
| |
| static inline rogue_bitwise_instr *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]) |
| { |
| rogue_bitwise_instr *bitwise = |
| rogue_bitwise_instr_create(rogue_cursor_block(b->cursor), op); |
| |
| for (unsigned i = 0; i < num_dsts; ++i) { |
| bitwise->dst[i].ref = dsts[i]; |
| bitwise->dst[i].index = i; |
| } |
| |
| for (unsigned i = 0; i < num_srcs; ++i) { |
| bitwise->src[i].ref = srcs[i]; |
| bitwise->src[i].index = i; |
| } |
| |
| rogue_builder_insert_instr(b, &bitwise->instr); |
| return bitwise; |
| } |
| |
| 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) |
| { |
| rogue_ref dsts[] = { dst0, dst1 }; |
| rogue_ref srcs[] = { src0, src1 }; |
| return rogue_build_bitwise(b, op, 2, dsts, 2, srcs); |
| } |
| |
| #define ROGUE_BUILDER_DEFINE_BITWISE22(op) \ |
| PUBLIC \ |
| rogue_bitwise_instr *rogue_##op(rogue_builder *b, \ |
| rogue_ref dst0, \ |
| rogue_ref dst1, \ |
| rogue_ref src0, \ |
| rogue_ref src1) \ |
| { \ |
| assert(rogue_bitwise_op_infos[ROGUE_BITWISE_OP_##op].num_dsts == 2); \ |
| assert(rogue_bitwise_op_infos[ROGUE_BITWISE_OP_##op].num_srcs == 2); \ |
| return rogue_build_bitwise22(b, \ |
| ROGUE_BITWISE_OP_##op, \ |
| dst0, \ |
| dst1, \ |
| src0, \ |
| src1); \ |
| } |
| |
| #include "rogue_bitwise_instrs.def" |