Hi, The following patch adds a new builtin function for rx ( __builtin_rx_bset) to make it possible for the user to use BSET whenever necessary. Please note this builtin function is dedicated only for the variant 32 bit variant of BSET (when destination is a register). For the 8 bit variant (when destination is a memory location) another builtin function is necessary.
The patch contains also a test case which I added in testsuite/gcc.target/rx. The patch also modifies extend.texi as necessary. Regression test is OK, tested with the following command: make -k check-gcc RUNTESTFLAGS=--target_board=rx-sim Please find below the changelog entries and patch. Best Regards, Sebastian --- ChangeLog 2018-10-23 Sebastian Perta <sebastian.pe...@renesas.com> * config/rx/rx.c (RX_BUILTIN_BSET): New enum. * config/rx/rx.c (rx_init_builtins): Added new builtin for BSET. * config/rx/rx.c (rx_expand_builtin_bit_manip): New function. * config/rx/rx.c (rx_expand_builtin): Added new case for BSET. * doc/extend.texi (RX Built-in Functions): Added declaration for __builtin_rx_bset. testsuite/ChangeLog 2018-10-23 Sebastian Perta <sebastian.pe...@renesas.com> * gcc.target/rx/testbset.c: New test. Index: config/rx/rx.c =================================================================== --- config/rx/rx.c (revision 265425) +++ config/rx/rx.c (working copy) @@ -2374,6 +2374,7 @@ RX_BUILTIN_ROUND, RX_BUILTIN_SETPSW, RX_BUILTIN_WAIT, + RX_BUILTIN_BSET, RX_BUILTIN_max }; @@ -2440,6 +2441,7 @@ ADD_RX_BUILTIN1 (ROUND, "round", intSI, float); ADD_RX_BUILTIN1 (REVW, "revw", intSI, intSI); ADD_RX_BUILTIN0 (WAIT, "wait", void); + ADD_RX_BUILTIN2 (BSET, "bset", intSI, intSI, intSI); } /* Return the RX builtin for CODE. */ @@ -2576,6 +2578,26 @@ return target; } +static rtx +rx_expand_builtin_bit_manip(tree exp, rtx target, rtx (* gen_func)(rtx, rtx, rtx)) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + if (! REG_P (arg1)) + arg1 = force_reg (SImode, arg1); + + if (! REG_P (arg2)) + arg2 = force_reg (SImode, arg2); + + if (target == NULL_RTX || ! REG_P (target)) + target = gen_reg_rtx (SImode); + + emit_insn(gen_func(target, arg2, arg1)); + + return target; +} + static int valid_psw_flag (rtx op, const char *which) { @@ -2653,6 +2675,7 @@ case RX_BUILTIN_REVW: return rx_expand_int_builtin_1_arg (op, target, gen_revw, false); case RX_BUILTIN_WAIT: emit_insn (gen_wait ()); return NULL_RTX; + case RX_BUILTIN_BSET: return rx_expand_builtin_bit_manip(exp, target, gen_bitset); default: internal_error ("bad builtin code"); Index: doc/extend.texi =================================================================== --- doc/extend.texi (revision 265425) +++ doc/extend.texi (working copy) @@ -19635,6 +19635,10 @@ Generates the @code{wait} machine instruction. @end deftypefn +@deftypefn {Built-in Function} int __builtin_rx_bset (int, int) +Generates the @code{bset} machine instruction. +@end deftypefn + @node S/390 System z Built-in Functions @subsection S/390 System z Built-in Functions @deftypefn {Built-in Function} int __builtin_tbegin (void*) Index: testsuite/ChangeLog Index: testsuite/gcc.target/rx/testbset.c =================================================================== --- testsuite/gcc.target/rx/testbset.c (nonexistent) +++ testsuite/gcc.target/rx/testbset.c (working copy) @@ -0,0 +1,53 @@ +/* { dg-do run } */ + +#include <stdlib.h> + +int f1(int a, int b) __attribute((noinline)); +int f1(int a, int b) +{ + return __builtin_rx_bset (a, b); +} + +int f2(int a) __attribute((noinline)); +int f2(int a) +{ + return __builtin_rx_bset (a, 1); +} + +int x, y; + +int f3() __attribute((noinline)); +int f3() +{ + return __builtin_rx_bset (x, 4); +} + +int f4() __attribute((noinline)); +int f4() +{ + return __builtin_rx_bset (x, y); +} + +void f5() __attribute((noinline)); +void f5() +{ + x = __builtin_rx_bset (x, 6); +} + +int main() +{ + if(f1(0xF, 8) != 0x10F) + abort(); + if(f2(0xC) != 0xE) + abort(); + x = 0xF; + if(f3() != 0x1F) + abort(); + y = 5; + if(f4() != 0x2F) + abort(); + f5(); + if(x != 0x4F) + abort(); + exit(0); +}