GNURX用のCCRXmachine.hとCCRXmachine.cというソースがe2 studioフォルダにありました(内容は概ね名前から予想される通りのものでした)

こんにちは。NoMaYです。

e2 studio v6.3.0がリリースされていたので、インストールして幾つかプロジェクトを作成して、いつものようにe2 studioのインストールフォルダを眺めていたら、CCRXmachine.hとCCRXmachine.cというファイルがあることに気付きました。中を見てみると、概ねファイル名から予想される通りのソースファイルでした。(今までのe2 studioのインストールフォルダを見直してみたところ、以前からあったことが分かりましたが、今まで気付きませんでした。) ただ、一部コメントアウトされているものがあったり、以前に別スレッド『GUNRX用プロジェクトのスマートコンフィグレータのBSPを見ていて気付いた変な移植コード』で話題にしたことと同じ元のコードの意図を理解していない書き換えがあったり、ちょっと惜しいような気もしました。

e2 studioインストールフォルダ\internal\projectgen\rx\Generate\CCRXConversion\inc\CCRXmachine.h



e2 studioインストールフォルダ\internal\projectgen\rx\Generate\CCRXConversion\inc\CCRXmachine.c



  • こんにちは。NoMaYです。

    GNURX対応のCCRXmachine.cを見ていて、以下のコードの末尾にCC-RXのスタートアップルーチンで見掛けたChange_PSW_PM_to_UserMode()関数の末尾にあるNOP命令が無いことに気付きました。(もっとも、随分以前からCC-RXではビルトイン関数のchg_pmusr()関数が使われるようになっていますので、今はCC-RXでChange_PSW_PM_to_UserMode()関数を見掛けることは余りありませんが。) そのせいで、以下のGNURX対応のCCRXmachine.cのchg_pmusr()関数は誤動作すると思われます。

    CCRXmachine.c

    void chg_pmusr(void)
    {
        __asm("MVFC   PSW,R1" : : :"r1");
        __asm("OR     #00100000h,R1" : : :"r1");
        __asm("PUSH.L R1" : : :"r1");
        __asm("MVFC   PC,R1" : : :"r1");
        __asm("ADD    #10,R1" : : :"r1");
        __asm("PUSH.L R1" : : :"r1");
        __asm("RTE");
    }

    CC-RXのスタートアップルーチンで見掛けたChange_PSW_PM_to_UserMode()関数は以下のコードです。このコードはもともとトリッキーなもので、MVFC PC,R1命令の先頭アドレスに10(0xA)を足したアドレスにRTEして分岐するようになっていますが、その分岐先アドレスは末尾の2つ目のNOP命令の先頭アドレスになります。

    generate\resetprg.c

    #pragma inline_asm Change_PSW_PM_to_UserMode
    static void Change_PSW_PM_to_UserMode(void);

    static void Change_PSW_PM_to_UserMode(void)
    {
        MVFC   PSW,R1
        OR     #00100000h,R1
        PUSH.L R1
        MVFC   PC,R1
        ADD    #10,R1
        PUSH.L R1
        RTE
        NOP
        NOP
    }

    例えば、上のコードをCC-RX V2.03のresetprg.cに組み込んでコンパイルすると以下のようになります。

    generate\resetprg.lst

                                     ;     123 //   _CALL_INIT();                                   // Remove the comment when you use global class object
                                     ;     124
                                     ;     125      set_psw(PSW_init);                              // Set Ubit & Ibit for PSW
    00000031 FD68E0                                 MVTC R14, PSW
                                     ;     126      Change_PSW_PM_to_UserMode();                                    // Remove the comment when you need to change PSW PMbit (SuperVisor->User)
                                                    ._LINE_TOP  inline_asm
    00000034 FD6A01                      MVFC   PSW,R1
    00000037 7731000010                  OR     #00100000h,R1
    0000003C 7EA1                        PUSH.L R1
    0000003E FD6A11                      MVFC   PC,R1    メモ: 0x3E+0xA=0x48
    00000041 62A1                        ADD    #10,R1
    00000043 7EA1                        PUSH.L R1
    00000045 7F95                        RTE
    00000047 03                          NOP
    00000048 03                          NOP
                                                    ._LINE_END  inline_asm
                                     ;     127
                                     ;     128      main();
    00000049 05rrrrrr             A                 BSR _main

    ところが、GNURX対応のCCRXmachine.cのchg_pmusr()関数ではNOP命令がありませんので、GNURXの2018q1でコンパイルしてみると以下のように、分岐先アドレスがchg_pmusr()関数の最後のRTS命令の次のアドレスになってしまいます、、、

    CCRXmachine.lst

     242:../src/CCRXmachine.c **** void chg_pmusr(void)
     243:../src/CCRXmachine.c **** {
     244:../src/CCRXmachine.c ****     __asm("MVFC   PSW,R1" : : :"r1");
     307 00cf FD 6A 01                              MVFC   PSW,R1
     245:../src/CCRXmachine.c ****     __asm("OR     #00100000h,R1" : : :"r1");
     311 00d2 77 31 00 00 10                        OR     #00100000h,R1
     246:../src/CCRXmachine.c ****     __asm("PUSH.L R1" : : :"r1");
     315 00d7 7E A1                                 PUSH.L R1
     247:../src/CCRXmachine.c ****     __asm("MVFC   PC,R1" : : :"r1");
     319 00d9 FD 6A 11                              MVFC   PC,R1    メモ: 0xd9+0xa=0xe3
     248:../src/CCRXmachine.c ****     __asm("ADD    #10,R1" : : :"r1");
     323 00dc 62 A1                                 ADD    #10,R1
     249:../src/CCRXmachine.c ****     __asm("PUSH.L R1" : : :"r1");
     327 00de 7E A1                                 PUSH.L R1
     250:../src/CCRXmachine.c ****     __asm("RTE");
     331 00e0 7F 95                                 RTE
     333 00e2 02                                    rts

     253:../src/CCRXmachine.c **** void set_acc(signed long long data)
     254:../src/CCRXmachine.c **** {
     255:../src/CCRXmachine.c ****  __builtin_rx_mvtachi(data >> 32);
     343 00e3 FD 17 02                              mvtachi r2    メモ: ここはもうchg_pmusr()関数の外部です
     256:../src/CCRXmachine.c ****  __builtin_rx_mvtaclo(data & 0xFFFFFFFF);
     345 00e6 FD 17 11                              mvtaclo r1

    [追記]

    そういえば、以前に別スレッド『RX631のメモリプロテクションユニットの件』で経験しましたが、chg_pmusr()関数(というかChange_PSW_PM_to_UserMode()関数)はIスタックからUスタックへの切り替えが発生しますので、そもそも、インライン展開されない場合には使用方法が難しい関数でもあります。

    なお、CC-RXの場合ですが、これら2つの関数は実装が微妙に異なり、正直に言うと動作確認はしていないのですが、Change_PSW_PM_to_UserMode()関数(≒GNURX対応のCCRXmachine.cのchg_pmusr()関数)はユーザモード中に実行すると特権命令例外が発生すると思われるのに対し、もう一方のchg_pmusr()関数はユーザモード中に実行しても特権命令例外が発生しないと思われます。(理由は、chg_pmusr()関数の方はPSWを調べてユーザモード中だったら特権命令であるRTE命令を実行しないようになっていましたので、そのようになると考えています。)

  • ほやです。
    自己亀レスで済みません。

    > ただし-fltoを付けないと関数呼び出しになってしまうのは変わりません。 関数本体の宣言の前にalways_inline 付けても効きませんでした。
    これについて少し補足します。
    __attribute__((always_inline) の宣言は、これを宣言したソースの中に関数本体がある事を要求されます。
    現状のように xchg( )関数のプロトタイプをCCRXmachine.hに置き、本体をCCRXmachine.cに置いた状態では
    ヘッダ側にalways_inlineを付けて宣言できません。

    > 「ヘッダファイルに~」とある通り、CCRXmachine.c ではなく CCRXmachine.h に記述する話をしています。
    xchg関数1つならそれもアリなのですが、他の組み込み関数までヘッダに記述するのはムリがあるかと。

    だからと言ってCCRXmachine.cの中だけでalways_inlineを付けて宣言しても、
    別のソースからcallした場合はalways_inlineが見えていないので常にはinline展開されません。

    「always_inline 付けても効きませんでした」はそういう意味でした。

    xchg( )を関数の形でなくビルトイン関数を呼び出すマクロとして再定義した方が手間が減る気がします。
    CCRXmachine.hの中で、マクロに書き換えられるものをマクロに、
    関数でないと難しいものだけ関数で宣言してあれば良かったのではないかと思います。

    以上独り言でした。

  • > xchg関数1つならそれもアリなのですが、他の組み込み関数までヘッダに記述するのはムリがあるかと。

    えっなんで??

    > CCRXmachine.hの中で、マクロに書き換えられるものをマクロに、

    マクロよりはインライン関数の方が良いのでは。
    www.jpcert.or.jp/.../c-pre00-c.html
  • こんにちは。NoMaYです。

    別スレッド『Amazon FreeRTOSだそうです。ルネサスさんのRXは参加しないのかな?』でCC-RX用プロジェクトをGNURX用プロジェクトへ移植する際に作ろうと考えていたCCRXmachine2.hの作業を始めようとして気付きましたが、前の投稿のchg_pmusr()関数の他にCC-RXの特殊なビルトイン関数としてint_exception()関数がありました。

    このint_exception()関数はCC-RXで以下のような記述をするとエラーになります。

    void my_int_exception(signed long num);

    void my_int_exception(signed long num)
    {
        int_exception(num);
    }
    F0544802:The value of the parameter for the in-line function is outside the defined range.

    これは、作ろうとしているCCRXmachine2.hでは、以下のようなマクロにするしかないかなと考えています。

    #define int_exception( num ) _int_exception_cpp_step2( num )
    #define _int_exception_cpp_step2( num ) do{ __asm __volatile ("INT #" #num); } while(0)

    理由は、以下の通り、INT命令のオペランドに割り込み番号をイミディエート値で指定する必要があるからです。

    RXファミリ ユーザーズマニュアル ソフトウェア編
    www.renesas.com/ja-jp/doc/products/mpumcu/doc/rx_family/r01us0032jj0120_rxsm.pdf


    ちなみに、コメントアウトされていますが、GNURX対応のCCRXmachine.cでも以下の記述が見られ、特殊である予感はしていました。

    /*略
    #define INTN(N)\
        case N:\
            __builtin_rx_int(N);

    #define INTN5(N)\
        INTN(N)\
        INTN(N+1)\
        INTN(N+2)\
        INTN(N+3)\
        INTN(N+4)\

    #define INTN10(N)\
        INTN5(N)\
        INTN5(N+5)\

    #define INTN50(N)\
        INTN10(N)\
        INTN10(N+10)\
        INTN10(N+20)\
        INTN10(N+30)\
        INTN10(N+40)

    void int_exception(signed long num)
    {
        switch(num)
        {
        INTN50(0)
        INTN50(50)
        INTN50(100)
        INTN50(150)
        INTN50(200)
        INTN5(250)
        INTN(255)
        default:
            __builtin_rx_int(255);
        }
    }
    略*/

     ところで、CCRXmachine2.hの作業の手始めとして、以下のCソースをCC-RX V2.03でコンパイルしてアセンブラソースを出力させてみました。

    CCRX_machine_h.c

    4666.CCRX_machine_h_c_20180608.txt
    #include <machine.h>
    
    /*
     * https://www.renesas.com/ja-jp/doc/products/tool/doc/011/r20ut3248jj0105-ccrx.pdf
     * 表4.26 (356頁 ~ 359頁 / 全970頁)
     */
    void _dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_(void) { ;                                                 }
    signed long        _max(signed long data1, signed long data2)                                          { return _builtin_max(data1, data2);                }
    signed long        _min(signed long data1, signed long data2)                                          { return _builtin_min(data1, data2);                }
    unsigned long      _revl(unsigned long data)                                                           { return _builtin_revl(data);                       }
    unsigned long      _revw(unsigned long data)                                                           { return _builtin_revw(data);                       }
    void               _xchg(signed long *data1, signed long *data2)                                       {        _builtin_xchg(data1, data2);               }
    long long          _rmpab(long long init, unsigned long count, signed char *addr1, signed char *addr2) { return _builtin_rmpab(init, count, addr1, addr2); }
    long long          _rmpaw(long long init, unsigned long count, short *addr1, short *addr2)             { return _builtin_rmpaw(init, count, addr1, addr2); }
    long long          _rmpal(long long init, unsigned long count, long *addr1, long *addr2)               { return _builtin_rmpal(init, count, addr1, addr2); }
    unsigned long      _rolc(unsigned long data)                                                           { return _builtin_rolc(data);                       }
    unsigned long      _rorc(unsigned long data)                                                           { return _builtin_rorc(data);                       }
    unsigned long      _rotl(unsigned long data, unsigned long num)                                        { return _builtin_rotl(data, num);                  }
    unsigned long      _rotr(unsigned long data, unsigned long num)                                        { return _builtin_rotr(data, num);                  }
    void               _brk(void)                                                                          {        _builtin_brk();                            }
    // void               _int_exception(signed long num)                                                     {        _builtin_int_exception(num);               }
    // F0544802:The value of the parameter for the in-line function is outside the defined range.
    void               _wait(void)                                                                         {        _builtin_wait();                           }
    void               _nop(void)                                                                          {        _builtin_nop();                            }
    void               _set_ipl(signed long level)                                                         {        _builtin_set_ipl(level);                   }
    unsigned char      _get_ipl(void)                                                                      { return _builtin_get_ipl();                        }
    void               _set_psw(unsigned long data)                                                        {        _builtin_set_psw(data);                    }
    unsigned long      _get_psw(void)                                                                      { return _builtin_get_psw();                        }
    void               _set_fpsw(unsigned long data)                                                       {        _builtin_set_fpsw(data);                   }
    unsigned long      _get_fpsw(void)                                                                     { return _builtin_get_fpsw();                       }
    void               _set_usp(void *data)                                                                {        _builtin_set_usp(data);                    }
    void *             _get_usp(void)                                                                      { return _builtin_get_usp();                        }
    void               _set_isp(void *data)                                                                {        _builtin_set_isp(data);                    }
    void *             _get_isp(void)                                                                      { return _builtin_get_isp();                        }
    void               _set_intb(void *data)                                                               {        _builtin_set_intb(data);                   }
    void *             _get_intb(void)                                                                     { return _builtin_get_intb();                       }
    void               _set_bpsw(unsigned long data)                                                       {        _builtin_set_bpsw(data);                   }
    unsigned long      _get_bpsw(void)                                                                     { return _builtin_get_bpsw();                       }
    void               _set_bpc(void *data)                                                                {        _builtin_set_bpc(data);                    }
    void *             _get_bpc(void)                                                                      { return _builtin_get_bpc();                        }
    void               _set_fintv(void *data)                                                              {        _builtin_set_fintv(data);                  }
    void *             _get_fintv(void)                                                                    { return _builtin_get_fintv();                      }
    signed long long   _emul(signed long data1, signed long data2)                                         { return _builtin_emul(data1, data2);               }
    unsigned long long _emulu(unsigned long data1, unsigned long data2)                                    { return _builtin_emulu(data1, data2);              }
    short              _macw1(short *data1, short *data2, unsigned long count)                             { return _builtin_macw1(data1, data2, count);       }
    short              _macw2(short *data1, short *data2, unsigned long count)                             { return _builtin_macw2(data1, data2, count);       }
    long               _macl(short *data1, short *data2, unsigned long count)                              { return _builtin_macl(data1, data2, count);        }
    void               _chg_pmusr(void)                                                                    {        _builtin_chg_pmusr();                      }
    void               _set_acc(signed long long data)                                                     {        _builtin_set_acc(data);                    }
    signed long long   _get_acc(void)                                                                      { return _builtin_get_acc();                        }
    void               _setpsw_i(void)                                                                     {        _builtin_setpsw_i();                       }
    void               _clrpsw_i(void)                                                                     {        _builtin_clrpsw_i();                       }
    void               _set_extb(void *data)                                                               {        _builtin_set_extb(data);                   }
    void *             _get_extb(void)                                                                     { return _builtin_get_extb();                       }
    
    /*
     * 表4.26の最後の3項目 (CC-RX V2.05 or later)
     */
    #if __RENESAS_VERSION__ >= 0x02050000
    void _dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy2(void) { ;                                                 }
    void               _bclr(unsigned char *data, unsigned long bit)                                       {        __bclr(data, bit);                         }
    void               _bnot(unsigned char *data, unsigned long bit)                                       {        __bnot(data, bit);                         }
    void               _bset(unsigned char *data, unsigned long bit)                                       {        __bset(data, bit);                         }
    #endif
    


    CCRX_machine_h.src
    4010.CCRX_machine_h_src_20180608.txt
    ;RX Family C/C++ Compiler (V2.03.00.03 [04 Dec 2014])  08-Jun-2018 18:56:32
    
    ;*** CPU TYPE ***
    
    ;-ISA=RXV2
    
    ;*** COMMAND PARAMETER ***
    
    ;-output=src=CCRX_machine_h.src
    ;-isa=rxv2
    ;-fpu
    ;-include=C:\Renesas\CS_~1\CC\CC-RX\V203~1.00\include,C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\generate
    ;-lang=c
    ;-nomessage
    ;-obj_path=src
    ;-debug
    ;-listfile=src/CCRX_machine_h.lst
    ;-show=source,conditionals,definitions,expansions
    ;-asm_path=src
    ;-nologo
    ;CCRX_machine_h.c
    
    		.glb	__dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_
    		.glb	__max
    		.glb	__min
    		.glb	__revl
    		.glb	__revw
    		.glb	__xchg
    		.glb	__rmpab
    		.glb	__rmpaw
    		.glb	__rmpal
    		.glb	__rolc
    		.glb	__rorc
    		.glb	__rotl
    		.glb	__rotr
    		.glb	__brk
    		.glb	__wait
    		.glb	__nop
    		.glb	__set_ipl
    		.glb	__get_ipl
    		.glb	__set_psw
    		.glb	__get_psw
    		.glb	__set_fpsw
    		.glb	__get_fpsw
    		.glb	__set_usp
    		.glb	__get_usp
    		.glb	__set_isp
    		.glb	__get_isp
    		.glb	__set_intb
    		.glb	__get_intb
    		.glb	__set_bpsw
    		.glb	__get_bpsw
    		.glb	__set_bpc
    		.glb	__get_bpc
    		.glb	__set_fintv
    		.glb	__get_fintv
    		.glb	__emul
    		.glb	__emulu
    		.glb	__macw1
    		.glb	__macw2
    		.glb	__macl
    		.glb	__chg_pmusr
    		.glb	__set_acc
    		.glb	__get_acc
    		.glb	__setpsw_i
    		.glb	__clrpsw_i
    		.glb	__set_extb
    		.glb	__get_extb
    ;LineNo. C-SOURCE STATEMENT
    
    		.SECTION	P,CODE
    __dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_:
    		.STACK	__dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_=4
    ;       1 #include <machine.h>
    ;       2 
    ;       3 /*
    ;       4  * https://www.renesas.com/ja-jp/doc/products/tool/doc/011/r20ut3248jj0105-ccrx.pdf
    ;       5  * 表4.26 (356頁 ~ 359頁 / 全970頁)
    ;       6  */
    ;       7 void _dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_(void) { ;                                                 }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",7
    		RTS
    __max:
    		.STACK	__max=4
    ;       8 signed long        _max(signed long data1, signed long data2)                                          { return _builtin_max(data1, data2);                }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",8
    		MAX R2, R1
    		RTS
    __min:
    		.STACK	__min=4
    ;       9 signed long        _min(signed long data1, signed long data2)                                          { return _builtin_min(data1, data2);                }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",9
    		MIN R2, R1
    		RTS
    __revl:
    		.STACK	__revl=4
    ;      10 unsigned long      _revl(unsigned long data)                                                           { return _builtin_revl(data);                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",10
    		REVL R1, R1
    		RTS
    __revw:
    		.STACK	__revw=4
    ;      11 unsigned long      _revw(unsigned long data)                                                           { return _builtin_revw(data);                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",11
    		REVW R1, R1
    		RTS
    __xchg:
    		.STACK	__xchg=4
    ;      12 void               _xchg(signed long *data1, signed long *data2)                                       {        _builtin_xchg(data1, data2);               }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",12
    		MOV.L [R1], R14
    		XCHG [R2].L, R14
    		MOV.L R14, [R1]
    		RTS
    __rmpab:
    		.STACK	__rmpab=8
    ;      13 long long          _rmpab(long long init, unsigned long count, signed char *addr1, signed char *addr2) { return _builtin_rmpab(init, count, addr1, addr2); }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",13
    		PUSH.L R6
    		MOV.L R1, R14
    		MOV.L R2, R5
    		MOV.L 08H[R0], R2
    		SHAR #1FH, R5, R6
    		MOV.L R4, R1
    		MOV.L R14, R4
    		RMPA.B
    		MOV.L R5, R2
    		MOV.L R4, R1
    		RTSD #04H, R6-R6
    __rmpaw:
    		.STACK	__rmpaw=8
    ;      14 long long          _rmpaw(long long init, unsigned long count, short *addr1, short *addr2)             { return _builtin_rmpaw(init, count, addr1, addr2); }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",14
    		PUSH.L R6
    		MOV.L R1, R14
    		MOV.L R2, R5
    		MOV.L 08H[R0], R2
    		SHAR #1FH, R5, R6
    		MOV.L R4, R1
    		MOV.L R14, R4
    		RMPA.W
    		MOV.L R5, R2
    		MOV.L R4, R1
    		RTSD #04H, R6-R6
    __rmpal:
    		.STACK	__rmpal=8
    ;      15 long long          _rmpal(long long init, unsigned long count, long *addr1, long *addr2)               { return _builtin_rmpal(init, count, addr1, addr2); }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",15
    		PUSH.L R6
    		MOV.L R1, R14
    		MOV.L R2, R5
    		MOV.L 08H[R0], R2
    		SHAR #1FH, R5, R6
    		MOV.L R4, R1
    		MOV.L R14, R4
    		RMPA.L
    		MOV.L R5, R2
    		MOV.L R4, R1
    		RTSD #04H, R6-R6
    __rolc:
    		.STACK	__rolc=4
    ;      16 unsigned long      _rolc(unsigned long data)                                                           { return _builtin_rolc(data);                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",16
    		ROLC R1
    		RTS
    __rorc:
    		.STACK	__rorc=4
    ;      17 unsigned long      _rorc(unsigned long data)                                                           { return _builtin_rorc(data);                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",17
    		RORC R1
    		RTS
    __rotl:
    		.STACK	__rotl=4
    ;      18 unsigned long      _rotl(unsigned long data, unsigned long num)                                        { return _builtin_rotl(data, num);                  }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",18
    		ROTL R2, R1
    		RTS
    __rotr:
    		.STACK	__rotr=4
    ;      19 unsigned long      _rotr(unsigned long data, unsigned long num)                                        { return _builtin_rotr(data, num);                  }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",19
    		ROTR R2, R1
    		RTS
    __brk:
    		.STACK	__brk=4
    ;      20 void               _brk(void)                                                                          {        _builtin_brk();                            }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",20
    		BRK
    		RTS
    __wait:
    		.STACK	__wait=4
    ;      21 // void               _int_exception(signed long num)                                                     {        _builtin_int_exception(num);               }
    ;      22 // F0544802:The value of the parameter for the in-line function is outside the defined range.
    ;      23 void               _wait(void)                                                                         {        _builtin_wait();                           }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",23
    		WAIT
    		RTS
    __nop:
    		.STACK	__nop=4
    ;      24 void               _nop(void)                                                                          {        _builtin_nop();                            }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",24
    		NOP
    		RTS
    __set_ipl:
    		.STACK	__set_ipl=4
    ;      25 void               _set_ipl(signed long level)                                                         {        _builtin_set_ipl(level);                   }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",25
    		MVFC PSW, R14
    		SHLL #1CH, R1
    		SHLR #04H, R1
    		AND #0F0FFFFFFH, R14
    		OR R14, R1
    		MVTC R1, PSW
    		RTS
    __get_ipl:
    		.STACK	__get_ipl=4
    ;      26 unsigned char      _get_ipl(void)                                                                      { return _builtin_get_ipl();                        }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",26
    		MVFC PSW, R14
    		REVL R14, R1
    		AND #0FH, R1
    		RTS
    __set_psw:
    		.STACK	__set_psw=4
    ;      27 void               _set_psw(unsigned long data)                                                        {        _builtin_set_psw(data);                    }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",27
    		MVTC R1, PSW
    		RTS
    __get_psw:
    		.STACK	__get_psw=4
    ;      28 unsigned long      _get_psw(void)                                                                      { return _builtin_get_psw();                        }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",28
    		MVFC PSW, R1
    		RTS
    __set_fpsw:
    		.STACK	__set_fpsw=4
    ;      29 void               _set_fpsw(unsigned long data)                                                       {        _builtin_set_fpsw(data);                   }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",29
    		MVTC R1, FPSW
    		RTS
    __get_fpsw:
    		.STACK	__get_fpsw=4
    ;      30 unsigned long      _get_fpsw(void)                                                                     { return _builtin_get_fpsw();                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",30
    		MVFC FPSW, R1
    		RTS
    __set_usp:
    		.STACK	__set_usp=4
    ;      31 void               _set_usp(void *data)                                                                {        _builtin_set_usp(data);                    }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",31
    		MVTC R1, USP
    		RTS
    __get_usp:
    		.STACK	__get_usp=4
    ;      32 void *             _get_usp(void)                                                                      { return _builtin_get_usp();                        }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",32
    		MVFC USP, R1
    		RTS
    __set_isp:
    		.STACK	__set_isp=4
    ;      33 void               _set_isp(void *data)                                                                {        _builtin_set_isp(data);                    }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",33
    		MVTC R1, ISP
    		RTS
    __get_isp:
    		.STACK	__get_isp=4
    ;      34 void *             _get_isp(void)                                                                      { return _builtin_get_isp();                        }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",34
    		MVFC ISP, R1
    		RTS
    __set_intb:
    		.STACK	__set_intb=4
    ;      35 void               _set_intb(void *data)                                                               {        _builtin_set_intb(data);                   }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",35
    		MVTC R1, INTB
    		RTS
    __get_intb:
    		.STACK	__get_intb=4
    ;      36 void *             _get_intb(void)                                                                     { return _builtin_get_intb();                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",36
    		MVFC INTB, R1
    		RTS
    __set_bpsw:
    		.STACK	__set_bpsw=4
    ;      37 void               _set_bpsw(unsigned long data)                                                       {        _builtin_set_bpsw(data);                   }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",37
    		MVTC R1, BPSW
    		RTS
    __get_bpsw:
    		.STACK	__get_bpsw=4
    ;      38 unsigned long      _get_bpsw(void)                                                                     { return _builtin_get_bpsw();                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",38
    		MVFC BPSW, R1
    		RTS
    __set_bpc:
    		.STACK	__set_bpc=4
    ;      39 void               _set_bpc(void *data)                                                                {        _builtin_set_bpc(data);                    }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",39
    		MVTC R1, BPC
    		RTS
    __get_bpc:
    		.STACK	__get_bpc=4
    ;      40 void *             _get_bpc(void)                                                                      { return _builtin_get_bpc();                        }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",40
    		MVFC BPC, R1
    		RTS
    __set_fintv:
    		.STACK	__set_fintv=4
    ;      41 void               _set_fintv(void *data)                                                              {        _builtin_set_fintv(data);                  }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",41
    		MVTC R1, FINTV
    		RTS
    __get_fintv:
    		.STACK	__get_fintv=4
    ;      42 void *             _get_fintv(void)                                                                    { return _builtin_get_fintv();                      }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",42
    		MVFC FINTV, R1
    		RTS
    __emul:
    		.STACK	__emul=4
    ;      43 signed long long   _emul(signed long data1, signed long data2)                                         { return _builtin_emul(data1, data2);               }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",43
    		MOV.L R1, R4
    		EMUL R2, R4
    		MOV.L R5, R2
    		MOV.L R4, R1
    		RTS
    __emulu:
    		.STACK	__emulu=4
    ;      44 unsigned long long _emulu(unsigned long data1, unsigned long data2)                                    { return _builtin_emulu(data1, data2);              }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",44
    		MOV.L R1, R4
    		EMULU R2, R4
    		MOV.L R5, R2
    		MOV.L R4, R1
    		RTS
    __macw1:
    		.STACK	__macw1=4
    ;      45 short              _macw1(short *data1, short *data2, unsigned long count)                             { return _builtin_macw1(data1, data2, count);       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",45
    		CMP #00H, R3
    		MOV.L #00000000H, R14
    		MULLO R14, R14
    		BEQ L52
    L47:	; entry
    		BTST #00H, R3
    		BGEU L49
    L48:	; entry
    		SUB #02H, R3
    		MOV.L [R1+], R14
    		MOV.L [R2+], R5
    		MACLO R14, R5
    		MACHI R14, R5
    		BNE L48
    		BRA L52
    L49:	; entry
    		SUB #01H, R3
    		BEQ L51
    L50:	; entry
    		SUB #02H, R3
    		MOV.L [R1+], R14
    		MOV.L [R2+], R5
    		MACLO R14, R5
    		MACHI R14, R5
    		BNE L50
    L51:	; entry
    		MOV.W [R1], R14
    		MOV.W [R2], R5
    		MACLO R14, R5
    L52:	; entry
    		RACW #01H
    		MVFACHI R1
    		RTS
    __macw2:
    		.STACK	__macw2=4
    ;      46 short              _macw2(short *data1, short *data2, unsigned long count)                             { return _builtin_macw2(data1, data2, count);       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",46
    		CMP #00H, R3
    		MOV.L #00000000H, R14
    		MULLO R14, R14
    		BEQ L59
    L54:	; entry
    		BTST #00H, R3
    		BGEU L56
    L55:	; entry
    		SUB #02H, R3
    		MOV.L [R1+], R14
    		MOV.L [R2+], R5
    		MACLO R14, R5
    		MACHI R14, R5
    		BNE L55
    		BRA L59
    L56:	; entry
    		SUB #01H, R3
    		BEQ L58
    L57:	; entry
    		SUB #02H, R3
    		MOV.L [R1+], R14
    		MOV.L [R2+], R5
    		MACLO R14, R5
    		MACHI R14, R5
    		BNE L57
    L58:	; entry
    		MOV.W [R1], R14
    		MOV.W [R2], R5
    		MACLO R14, R5
    L59:	; entry
    		RACW #02H
    		MVFACHI R1
    		RTS
    __macl:
    		.STACK	__macl=4
    ;      47 long               _macl(short *data1, short *data2, unsigned long count)                              { return _builtin_macl(data1, data2, count);        }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",47
    		CMP #00H, R3
    		MOV.L #00000000H, R14
    		MULLO R14, R14
    		BEQ L66
    L61:	; entry
    		BTST #00H, R3
    		BGEU L63
    L62:	; entry
    		SUB #02H, R3
    		MOV.L [R1+], R14
    		MOV.L [R2+], R5
    		MACLO R14, R5
    		MACHI R14, R5
    		BNE L62
    		BRA L66
    L63:	; entry
    		SUB #01H, R3
    		BEQ L65
    L64:	; entry
    		SUB #02H, R3
    		MOV.L [R1+], R14
    		MOV.L [R2+], R5
    		MACLO R14, R5
    		MACHI R14, R5
    		BNE L64
    L65:	; entry
    		MOV.W [R1], R14
    		MOV.W [R2], R5
    		MACLO R14, R5
    L66:	; entry
    		MVFACMI R1
    		RTS
    __chg_pmusr:
    		.STACK	__chg_pmusr=12
    ;      48 void               _chg_pmusr(void)                                                                    {        _builtin_chg_pmusr();                      }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",48
    		MVFC PSW, R14
    		BTST #14H, R14
    		BNE L69
    L68:	; entry
    		OR #00100000H, R14
    		PUSH.L R14
    L70:
    		MVFC PC, R14
    		ADD #L69-L70, R14
    		PUSH.L R14
    		RTE
    L69:	; entry
    		RTS
    __set_acc:
    		.STACK	__set_acc=4
    ;      49 void               _set_acc(signed long long data)                                                     {        _builtin_set_acc(data);                    }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",49
    		MVTACLO R1
    		MVTACHI R2
    		RTS
    __get_acc:
    		.STACK	__get_acc=4
    ;      50 signed long long   _get_acc(void)                                                                      { return _builtin_get_acc();                        }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",50
    		MVFACMI R1
    		SHLL #10H, R1
    		MVFACHI R2
    		RTS
    __setpsw_i:
    		.STACK	__setpsw_i=4
    ;      51 void               _setpsw_i(void)                                                                     {        _builtin_setpsw_i();                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",51
    		SETPSW I
    		RTS
    __clrpsw_i:
    		.STACK	__clrpsw_i=4
    ;      52 void               _clrpsw_i(void)                                                                     {        _builtin_clrpsw_i();                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",52
    		CLRPSW I
    		RTS
    __set_extb:
    		.STACK	__set_extb=4
    ;      53 void               _set_extb(void *data)                                                               {        _builtin_set_extb(data);                   }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",53
    		MVTC R1, EXTB
    		RTS
    __get_extb:
    		.STACK	__get_extb=4
    ;      54 void *             _get_extb(void)                                                                     { return _builtin_get_extb();                       }
    		.LINE  "C:\Renesas\e2_studio_63_rl78rxrza\workspace_e2_v630\TestCCRX_machine_h\src\CCRX_machine_h.c",54
    		MVFC EXTB, R1
    		RTS
    ;      55 
    ;      56 /*
    ;      57  * 表4.26の最後の3項目 (CC-RX V2.05 or later)
    ;      58  */
    ;      59 #if __RENESAS_VERSION__ >= 0x02050000
    ;      60 void _dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy_dummy2(void) { ;                                                 }
    ;      61 void               _bclr(unsigned char *data, unsigned long bit)                                       {        __bclr(data, bit);                         }
    ;      62 void               _bnot(unsigned char *data, unsigned long bit)                                       {        __bnot(data, bit);                         }
    ;      63 void               _bset(unsigned char *data, unsigned long bit)                                       {        __bset(data, bit);                         }
    ;      64 #endif
    		.END
    


    思うに、無用なバグ混入を防止する為、そもそもこういう仕事は以下のような作業をすると良かったのかな、という気がしないこともないような気がしました、、、

    ・CC-RXの開発チームにビルトイン関数のアセンブラソースを貰えないか相談する
    (貰えなかったら上のようにCC-RXでアセンブラソースを出力させる)
    ・引数と戻り値の規約をGNURXに合わせる
    ・インライン展開の記法に合わせる
    [追記]
    ・コード生成機能のr_cg_macrodriver.h(ここでnop(), brk(), wait()が#defineされている)との整合を図る

  • 以下のようなマクロにするしかないかなと考えています。
    #define int_exception( num ) _int_exception_cpp_step2( num )
    #define _int_exception_cpp_step2( num ) do{ __asm __volatile ("INT #" #num); } while(0)
    

    ↑ だと、

    $ cat -n intexception.c
         1  #define int_exception( num ) _int_exception_cpp_step2( num )
         2  #define _int_exception_cpp_step2( num ) do{ __asm __volatile ("INT #" #num); } while(0)
         3
         4  void hoge(void)
         5  {
         6      int_exception(0);
         7      int_exception(1);
         8      int_exception(2);
         9      int_exception(255);
        10      int num = 123;
        11      int_exception(num);
        12      extern int ext;
        13      int_exception(ext);
        14  }
    
    $
    

    ↑のようなソースを書いた場合、

    $ rx-elf-gcc -Wall -Wextra -O2 intexception.c -S -o -
            .file   "intexception.c"
    intexception.c: In function 'hoge':
    intexception.c:12:16: warning: unused variable 'ext' [-Wunused-variable]
         extern int ext;
                    ^
    intexception.c:10:9: warning: unused variable 'num' [-Wunused-variable]
         int num = 123;
             ^
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
     ; 6 "intexception.c" 1
            INT #0
     ; 0 "" 2
     ; 7 "intexception.c" 1
            INT #1
     ; 0 "" 2
     ; 8 "intexception.c" 1
            INT #2
     ; 0 "" 2
     ; 9 "intexception.c" 1
            INT #255
     ; 0 "" 2
     ; 11 "intexception.c" 1
            INT #num
     ; 0 "" 2
     ; 13 "intexception.c" 1
            INT #ext
     ; 0 "" 2
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $

    引数に変数を使用した場合に期待した命令が出力されません。

    マクロをちょっと書き換えて

    $ cat -n intexception.c
         1  #define int_exception( num ) _int_exception_cpp_step2( num )
         2  #define _int_exception_cpp_step2( num ) \
         3  do { \
         4      if (__builtin_constant_p(num)) { \
         5          __asm __volatile("INT %0 \n"::"i"(num)); \
         6      } else { \
         7          switch ((num) & 255) { \
         8          case 0: __asm __volatile("INT #0 \n"); break; \
         9          case 1: __asm __volatile("INT #1 \n"); break; \
        10          case 2: __asm __volatile("INT #2 \n"); break; \
    

    ~ 長いので略 ~

       263          case 255: __asm __volatile("INT #255 \n"); break; \
       264          } \
       265      } \
       266  } while (0);
       267
       268  void hoge(void)
       269  {
       270      int_exception(0);
       271      int_exception(1);
       272      int_exception(2);
       273      int_exception(255);
       274      int num = 123;
       275      int_exception(num);
       276      extern int ext;
       277      int_exception(ext);
       278  }
    
    

    等とすると、

    $ rx-elf-gcc -Wall -Wextra -O2 intexception.c -S -o -
            .file   "intexception.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
     ; 270 "intexception.c" 1
            INT #0
    
     ; 0 "" 2
     ; 271 "intexception.c" 1
            INT #1
    
     ; 0 "" 2
     ; 272 "intexception.c" 1
            INT #2
    
     ; 0 "" 2
     ; 273 "intexception.c" 1
            INT #0xff
    
     ; 0 "" 2
     ; 275 "intexception.c" 1
            INT #0x7b
    
     ; 0 "" 2
            mov.L   #_ext, r5
            movu.B  [r5], r4
            mov.L   #.L4, r5
            mov.L   [r4,r5], r5
    
    1:jmp   r5
            .section C,"a",@progbits
            .p2align 2
            .balign 4
            .balign 4
    .L4:
            .long .L2
            .long .L3
            .long .L5
    

    ~ 長いので略 ~

    .L5:
     ; 277 "intexception.c" 1
            INT #2
    
     ; 0 "" 2
            rts
    .L3:
     ; 277 "intexception.c" 1
            INT #1
    
     ; 0 "" 2
            rts
    .L2:
     ; 277 "intexception.c" 1
            INT #0
    
     ; 0 "" 2
            rts
    .L258:
     ; 277 "intexception.c" 1
            INT #255
    
     ; 0 "" 2
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $
    

    とするとまあまあ良いんじゃないでしょうか。

    変数を使用した場合に展開されるのが嫌という場合には引数が定数か変数かで場合分けをして変数の場合には関数を呼び出す形にすれば良いと思います。

  • ちなみに、コメントアウトされていますが、

    成る程、こういう書き方もできるのか。勉強になるな。

    #define INTN(N)\
        case N:\
            __asm __volatile("INT #" #N "\n"); break;
    
    #define INTN5(N)\
        INTN(N)\
        INTN(N+1)\
        INTN(N+2)\
        INTN(N+3)\
        INTN(N+4)\
    
    #define INTN10(N)\
        INTN5(N)\
        INTN5(N+5)\
    
    #define INTN50(N)\
        INTN10(N)\
        INTN10(N+10)\
        INTN10(N+20)\
        INTN10(N+30)\
        INTN10(N+40)
    
    #define int_exception( num ) _int_exception_cpp_step2( num )
    #define _int_exception_cpp_step2( num ) \
    do { \
        if (__builtin_constant_p(num)) { \
            __asm __volatile("INT %0 \n"::"i"(num)); \
        } else { \
            switch (num) { \
            INTN50(0) \
            INTN50(50) \
            INTN50(100) \
            INTN50(150) \
            INTN50(200) \
            INTN5(250) \
            INTN(255) \
            default: \
                __asm __volatile("INT #255\n"); break; \
            } \
        } \
    } while (0);
    
  • 自己書き換えコードで行けるのかな?

    $ cat -n intexception.c
         1  #include 
         2
         3  #define int_exception( num ) _int_exception_cpp_step2( num )
         4  #define _int_exception_cpp_step2( num ) \
         5  do { \
         6      if (__builtin_constant_p(num)) { \
         7          __asm __volatile("INT %0 \n"::"i"(num)); \
         8      } else { \
         9          volatile uint8_t int_rts[] = {0x75, 0x60, num, 0x02}; \
        10          ((void (*)(void))int_rts)(); \
        11      } \
        12  } while (0);
        13
        14  void hoge(void)
        15  {
        16      int_exception(0);
        17      int_exception(1);
        18      int_exception(2);
        19      int_exception(255);
        20      int num = 123;
        21      int_exception(num);
        22      extern int ext;
        23      int_exception(ext);
        24  }
    
    $ rx-elf-gcc -Wall -Wextra -O2 intexception.c -S -o -
            .file   "intexception.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            sub     #4, r0
     ; 16 "intexception.c" 1
            INT #0
    
     ; 0 "" 2
     ; 17 "intexception.c" 1
            INT #1
    
     ; 0 "" 2
     ; 18 "intexception.c" 1
            INT #2
    
     ; 0 "" 2
     ; 19 "intexception.c" 1
            INT #0xff
    
     ; 0 "" 2
     ; 21 "intexception.c" 1
            INT #0x7b
    
     ; 0 "" 2
            mov.L   #_ext, r5
            movu.B  [r5], r5
            shll    #16, r5
            or      #0x2006075, r5
            mov.L   r5, [r0]
            jsr     r0
            rtsd    #4
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $
  • fujitaさん、こんにちは。NoMaYです。

    アドバイス、どうも有難う御座います。デフォルトで変数時に自己書き換えコード、オプションで変数時に関数呼び出しコード、いずれも定数時は__builtin_rx_int()関数、としてみようと思います。オプションを用意する理由は、自己書き換えコードをスタック上で実行する方式はリエントラント性の点から良いと思ったのですが、以前にメモリプロテクションユニットに関して色々と投稿した身としては、このことでスタック領域全域に実行許可属性を付けないといけなくなってしまうのが気になってしまったからです。あと、コードを書いて気付いたのですが、そういえば__builtin_rx_int()関数があるのだから素朴に使えば良いよな、と我ながら思いました。今、こんな感じに書いています。

    #ifdef DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK

    void int_exception_switch_case_function(signed long num);

    #define int_exception(num) \
    do { \
        if (__builtin_constant_p(num)) { \
            __builtin_rx_int(num); \
        } else { \
            int_exception_switch_case_function(num); \
        } \
    } while (0)

    #else /* DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK */

    #define int_exception(num) \
    do { \
        if (__builtin_constant_p(num)) { \
            __builtin_rx_int(num); \
        } else { \
            unsigned char int_rts[] = {0x75, 0x60, num, 0x02}; \
            ((void (*)(void*))int_rts)(int_rts); \
        } \
    } while (0)

    #endif /* DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK */

     

  • こんにちは。NoMaYです。

    試しにCCRXmachine2.hとCCRXmachine2.c(追加した理由は前の投稿にて説明)と確認用コードを書いてみました。

    CCRXmachine2.h

    6507.CCRXmachine2_h_20180610.txt
    /*
    License:
    The MIT License will be used.
    https://opensource.org/licenses/MIT
    */
    
    /*
    Docments:
    https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
    and
    https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html
    https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html
    https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html
    (https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html)
    https://gcc.gnu.org/onlinedocs/gcc/Constraints.html
    https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html
    https://gcc.gnu.org/onlinedocs/gcc/Explicit-Register-Variables.html
    https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html
    and
    https://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html
    */
    
    /*
    Use switch case function instead of RX INT instruction execution on stack.
    #define DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK
    */
    
    #ifndef CCRXMACHINE2_H
    #define CCRXMACHINE2_H
    
    static __inline__ signed long max(signed long data1, signed long data2) __attribute__((always_inline));
    static __inline__ signed long max(signed long data1, signed long data2)
    {
    /* CC-RX V2.03
            MAX R2, R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MAX %[R2], %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data1)
            : /* InputOperands */
                [R2] "r" (data2)
        );
        return data1;
    /* GNURX 2018q1
      16 0000 FC 13 21                      MAX r2, r1
      22 0003 02                            rts
    */
    }
    
    static __inline__ signed long min(signed long data1, signed long data2) __attribute__((always_inline));
    static __inline__ signed long min(signed long data1, signed long data2)
    {
    /* CC-RX V2.03
            MIN R2, R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MIN %[R2], %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data1)
            : /* InputOperands */
                [R2] "r" (data2)
        );
        return data1;
    /* GNURX 2018q1
      35 0004 FC 17 21                      MIN r2, r1
      41 0007 02                            rts
    */
    }
    
    static __inline__ signed long revl(signed long data) __attribute__((always_inline));
    static __inline__ signed long revl(signed long data)
    {
    /* CC-RX V2.03
            REVL R1, R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "REVL %[R1], %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data)
        );
        return data;
    /* GNURX 2018q1
      54 0008 FD 67 11                      REVL r1, r1
      60 000b 02                            rts
    */
    }
    
    static __inline__ signed long revw(signed long data) __attribute__((always_inline));
    static __inline__ signed long revw(signed long data)
    {
    /* CC-RX V2.03
            REVW R1, R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "REVW %[R1], %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data)
        );
        return data;
    /* GNURX 2018q1
      73 000c FD 65 11                      REVW r1, r1
      79 000f 02                            rts
    */
    }
    
    static __inline__ void xchg(signed long *data1, signed long *data2) __attribute__((always_inline));
    static __inline__ void xchg(signed long *data1, signed long *data2)
    {
    /* CC-RX V2.03
            MOV.L [R1], R14
            XCHG [R2].L, R14
            MOV.L R14, [R1]
            RTS
    */
        signed long temp = *data1;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "XCHG [%[R2]].L, %[R14]"
            : /* OutputOperands */
                [R14] "+r" (temp)
            : /* InputOperands */
                [R2] "r" (data2)
        );
        *data1 = temp;
        return;
    /* GNURX 2018q1
      91 0010 EC 15                         mov.L   [r1], r5
      95 0012 06 A0 10 25                   XCHG [r2].L, r5
      99 0016 E3 15                         mov.L   r5, [r1]
     100 0018 02                            rts
    */
    }
    
    static __inline__ long long rmpab(long long init, unsigned long count, signed char *addr1, signed char *addr2) __attribute__((always_inline));
    static __inline__ long long rmpab(long long init, unsigned long count, signed char *addr1, signed char *addr2)
    {
    /* CC-RX V2.03
            ARG init = R2:R1
            ARG count = R3
            ARG addr1 = R4
            ARG addr2 = 04H[R0](08H[R0] after PUSH R6)
            RET R2:R1
    
            PUSH.L R6
            MOV.L R1, R14
            MOV.L R2, R5
            MOV.L 08H[R0], R2
            SHAR #1FH, R5, R6
            MOV.L R4, R1
            MOV.L R14, R4
            RMPA.B
            MOV.L R5, R2
            MOV.L R4, R1
            RTSD #04H, R6-R6
    */
        register signed char *r1 __asm("r1") = addr1;
        register signed char *r2 __asm("r2") = addr2;
        register unsigned long r3 __asm("r3") = count;
        register long long r5r4 __asm("r4") = init;
        register signed long r6 __asm("r6") = (signed long)(init >> 63);
    
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "RMPA.B"
            : /* OutputOperands */
                "+r" (r5r4),
                "+r" (r6)
            : /* InputOperands */
                "X" (r1),
                "X" (r2),
                "X" (r3)
        );
        return r5r4;
    /* GNURX 2018q1
     111 0019 7E A6                       push.l  r6
     113 001b 60 40                       sub #4, r0
     116 001d EF 25                       mov.L r2, r5
     117 001f EF 1E                       mov.L r1, r14
     122 0021 EF 41                       mov.L r4, r1
     125 0023 A8 8A                       mov.L 12[r0], r2
     128 0025 EF E4                       mov.L r14, r4
     131 0027 FD BF 56                    shar  #31, r5, r6
     134 002a 7F 8C                       rmpa.b
     139 002c EF 41                       mov.L r4, r1
     141 002e EF 52                       mov.L r5, r2
     142 0030 3F 66 02                    rtsd  #8, r6-r6
    */
    }
    
    static __inline__ long long rmpaw(long long init, unsigned long count, short *addr1, short *addr2) __attribute__((always_inline));
    static __inline__ long long rmpaw(long long init, unsigned long count, short *addr1, short *addr2)
    {
    /* CC-RX V2.03
            ARG init = R2:R1
            ARG count = R3
            ARG addr1 = R4
            ARG addr2 = 04H[R0](08H[R0] after PUSH R6)
            RET R2:R1
    
            PUSH.L R6
            MOV.L R1, R14
            MOV.L R2, R5
            MOV.L 08H[R0], R2
            SHAR #1FH, R5, R6
            MOV.L R4, R1
            MOV.L R14, R4
            RMPA.W
            MOV.L R5, R2
            MOV.L R4, R1
            RTSD #04H, R6-R6
    */
        register short *r1 __asm("r1") = addr1;
        register short *r2 __asm("r2") = addr2;
        register unsigned long r3 __asm("r3") = count;
        register long long r5r4 __asm("r4") = init;
        register signed long r6 __asm("r6") = (signed long)(init >> 63);
    
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "RMPA.W"
            : /* OutputOperands */
                "+r" (r5r4),
                "+r" (r6)
            : /* InputOperands */
                "X" (r1),
                "X" (r2),
                "X" (r3)
        );
        return r5r4;
    /* GNURX 2018q1
     151 0033 7E A6                         push.l  r6
     153 0035 60 40                         sub #4, r0
     156 0037 EF 25                         mov.L   r2, r5
     157 0039 EF 1E                         mov.L   r1, r14
     162 003b EF 41                         mov.L   r4, r1
     165 003d A8 8A                         mov.L   12[r0], r2
     168 003f EF E4                         mov.L   r14, r4
     171 0041 FD BF 56                      shar    #31, r5, r6
     174 0044 7F 8D                         RMPA.W
     179 0046 EF 41                         mov.L   r4, r1
     181 0048 EF 52                         mov.L   r5, r2
     182 004a 3F 66 02                      rtsd    #8, r6-r6
    */
    }
    
    static __inline__ long long rmpal(long long init, unsigned long count, long *addr1, long *addr2) __attribute__((always_inline));
    static __inline__ long long rmpal(long long init, unsigned long count, long *addr1, long *addr2)
    {
    /* CC-RX V2.03
            ARG init = R2:R1
            ARG count = R3
            ARG addr1 = R4
            ARG addr2 = 04H[R0](08H[R0] after PUSH R6)
            RET R2:R1
    
            PUSH.L R6
            MOV.L R1, R14
            MOV.L R2, R5
            MOV.L 08H[R0], R2
            SHAR #1FH, R5, R6
            MOV.L R4, R1
            MOV.L R14, R4
            RMPA.L
            MOV.L R5, R2
            MOV.L R4, R1
            RTSD #04H, R6-R6
    */
        register long *r1 __asm("r1") = addr1;
        register long *r2 __asm("r2") = addr2;
        register unsigned long r3 __asm("r3") = count;
        register long long r5r4 __asm("r4") = init;
        register signed long r6 __asm("r6") = (signed long)(init >> 63);
    
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "RMPA.L"
            : /* OutputOperands */
                "+r" (r5r4),
                "+r" (r6)
            : /* InputOperands */
                "X" (r1),
                "X" (r2),
                "X" (r3)
        );
        return r5r4;
    /* GNURX 2018q1
     191 004d 7E A6                         push.l  r6
     193 004f 60 40                         sub #4, r0
     196 0051 EF 25                         mov.L   r2, r5
     197 0053 EF 1E                         mov.L   r1, r14
     202 0055 EF 41                         mov.L   r4, r1
     205 0057 A8 8A                         mov.L   12[r0], r2
     208 0059 EF E4                         mov.L   r14, r4
     211 005b FD BF 56                      shar    #31, r5, r6
     214 005e 7F 8E                         RMPA.L
     219 0060 EF 41                         mov.L   r4, r1
     221 0062 EF 52                         mov.L   r5, r2
     222 0064 3F 66 02                      rtsd    #8, r6-r6
    */
    }
    
    static __inline__ long rolc(unsigned long data) __attribute__((always_inline));
    static __inline__ long rolc(unsigned long data)
    {
    /* CC-RX V2.03
            ROLC R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "ROLC %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data)
        );
        return data;
    /* GNURX 2018q1
     235 0067 7E 51                         ROLC r1
     241 0069 02                            rts
    */
    }
    
    static __inline__ long rorc(unsigned long data) __attribute__((always_inline));
    static __inline__ long rorc(unsigned long data)
    {
    /* CC-RX V2.03
            RORC R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "RORC %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data)
        );
        return data;
    /* GNURX 2018q1
     254 006a 7E 41                         RORC r1
     260 006c 02                            rts
    */
    }
    
    static __inline__ long rotl(unsigned long data, unsigned long num) __attribute__((always_inline));
    static __inline__ long rotl(unsigned long data, unsigned long num)
    {
    /* CC-RX V2.03
            ROTL R2, R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "ROTL %[R2], %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data)
            : /* InputOperands */
                [R2] "r" (num)
        );
        return data;
    /* GNURX 2018q1
     292 0071 FD 64 21                      ROTR r2, r1
     298 0074 02                            rts
    */
    }
    
    static __inline__ long rotr(unsigned long data, unsigned long num) __attribute__((always_inline));
    static __inline__ long rotr(unsigned long data, unsigned long num)
    {
    /* CC-RX V2.03
            ROTR R2, R1
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "ROTR %[R2], %[R1]"
            : /* OutputOperands */
                [R1] "+r" (data)
            : /* InputOperands */
                [R2] "r" (num)
        );
        return data;
    /* GNURX 2018q1
     292 0071 FD 64 21                      ROTR r2, r1
     298 0074 02                            rts
    */
    }
    
    #ifndef brk
    static __inline__ void brk(void) __attribute__((always_inline));
    static __inline__ void brk(void)
    {
    /* CC-RX V2.03
            BRK
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "BRK"
            : /* OutputOperands */
                /* No outputs. */
        );
        return;
    /* GNURX 2018q1
     310 0075 00                            BRK
     312 0076 02                            rts
    */
    }
    #endif /* #ifndef brk */
    
    #ifdef DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK
    
    void int_exception_switch_case_function(signed long num);
    
    #if 1
    #define int_exception(num) \
    do { \
        if (__builtin_constant_p(num)) { \
            __builtin_rx_int(num); \
        } else { \
            int_exception_switch_case_function(num); \
        } \
    } while (0)
    #else
    #define int_exception(num) \
    do { \
        if (__builtin_constant_p(num)) { \
            __asm__ volatile \
            ( \
                /* AssemblerTemplate */ \
                "INT %[NUM]" \
                : /* OutputOperands */ \
                    /* No outputs. */ \
                : /* InputOperands */ \
                    [NUM] "i" (num) \
            ); \
        } else { \
            int_exception_switch_case_function(num); \
        } \
    } while (0)
    #endif
    
    #else /* DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK */
    
    #if 1
    #define int_exception(num) \
    do { \
        if (__builtin_constant_p(num)) { \
            __builtin_rx_int(num); \
        } else { \
            unsigned char int_rts[] = {0x75, 0x60, num, 0x02}; \
            ((void (*)(void*))int_rts)(int_rts); \
        } \
    } while (0)
    #else
    #define int_exception(num) \
    do { \
        if (__builtin_constant_p(num)) { \
            __asm__ volatile \
            ( \
                /* AssemblerTemplate */ \
                "INT %[NUM]" \
                : /* OutputOperands */ \
                    /* No outputs. */ \
                : /* InputOperands */ \
                    [NUM] "i" (num) \
            ); \
        } else { \
            unsigned char int_rts[] = {0x75, 0x60, num, 0x02}; \
            ((void (*)(void*))int_rts)(int_rts); \
        } \
    } while (0)
    #endif
    
    #endif /* DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK */
    
    #ifndef wait
    static __inline__ void wait(void) __attribute__((always_inline));
    static __inline__ void wait(void)
    {
    /* CC-RX V2.03
            WAIT
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "WAIT"
            : /* OutputOperands */
                /* No outputs. */
        );
        return;
    /* GNURX 2018q1
     372 0092 7F 96                         WAIT
     374 0094 02                            rts
    */
    }
    #endif /* #ifndef wait */
    
    #ifndef nop
    static __inline__ void nop(void) __attribute__((always_inline));
    static __inline__ void nop(void)
    {
    /* CC-RX V2.03
            NOP
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "NOP"
            : /* OutputOperands */
                /* No outputs. */
        );
        return;
    /* GNURX 2018q1
     388 0095 03                            NOP
     390 0096 02                            rts
    */
    }
    #endif /* #ifndef nop */
    
    static __inline__ void set_ipl(signed long level) __attribute__((always_inline));
    static __inline__ void set_ipl(signed long level)
    {
    /* CC-RX V2.03
            MVFC PSW, R14
            SHLL #1CH, R1
            SHLR #04H, R1
            AND #0F0FFFFFFH, R14
            OR R14, R1
            MVTC R1, PSW
            RTS
    */
        signed long temp;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC PSW, %[R14]\n\t"
            "SHLL #0x1C, %[R1]\n\t"
            "SHLR #0x04, %[R1]\n\t"
            "AND #0xF0FFFFFF, %[R14]\n\t"
            "OR %[R14], %[R1]\n\t"
            "MVTC %[R1], PSW"
            : /* OutputOperands */
                [R1] "+r" (level),
                [R14] "=r" (temp)
        );
        return;
    /* GNURX 2018q1
     405 0097 FD 6A 05                      MVFC PSW, r5
     406 009a 6D C1                         SHLL #0x1C, r1
     407 009c 68 41                         SHLR #0x04, r1
     408 009e 74 25 FF FF FF F0             AND #0xF0FFFFFF, r5
     409 00a4 57 51                         OR r5, r1
     410 00a6 FD 68 10                      MVTC r1, PSW
     413 00a9 02                            rts
    */
    }
    
    static __inline__ unsigned char get_ipl(void) __attribute__((always_inline));
    static __inline__ unsigned char get_ipl(void)
    {
    /* CC-RX V2.03
            MVFC PSW, R14
            REVL R14, R1
            AND #0FH, R1
            RTS
    */
        signed long temp;
        unsigned char level;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC PSW, %[R14]\n\t"
            "REVL %[R14], %[R1]\n\t"
            "AND #0x0F, %[R1]"
            : /* OutputOperands */
                [R14] "=r" (temp),
                [R1] "=r" (level)
        );
        return level;
    /* GNURX 2018q1
     427 00aa FD 6A 05                      MVFC PSW, r5
     428 00ad FD 67 51                      REVL r5, r1
     429 00b0 64 F1                         AND #0x0F, r1
     435 00b2 5B 11                         movu.B  r1, r1
     436 00b4 02                            rts
    */
    }
    
    static __inline__ void set_psw(unsigned long data) __attribute__((always_inline));
    static __inline__ void set_psw(unsigned long data)
    {
    /* CC-RX V2.03
            MVTC R1, PSW
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], PSW"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     449 00b5 FD 68 10                      MVTC r1, PSW
     451 00b8 02                            rts
    */
    }
    
    static __inline__ unsigned long get_psw(void) __attribute__((always_inline));
    static __inline__ unsigned long get_psw(void)
    {
    /* CC-RX V2.03
            MVFC PSW, R1
            RTS
    */
        unsigned long data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC PSW, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     465 00b9 FD 6A 01                      MVFC PSW, r1
     471 00bc 02                            rts
    */
    }
    
    static __inline__ void set_fpsw(unsigned long data) __attribute__((always_inline));
    static __inline__ void set_fpsw(unsigned long data)
    {
    /* CC-RX V2.03
            MVTC R1, FPSW
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], FPSW"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     484 00bd FD 68 13                      MVTC r1, FPSW
     486 00c0 02                            rts
    */
    }
    
    static __inline__ unsigned long get_fpsw(void) __attribute__((always_inline));
    static __inline__ unsigned long get_fpsw(void)
    {
    /* CC-RX V2.03
            MVFC FPSW, R1
            RTS
    */
        unsigned long data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC FPSW, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     500 00c1 FD 6A 31                      MVFC FPSW, r1
     506 00c4 02                            rts
    */
    }
    
    static __inline__ void set_usp(void *data) __attribute__((always_inline));
    static __inline__ void set_usp(void *data)
    {
    /* CC-RX V2.03
            MVTC R1, USP
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], USP"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     519 00c5 FD 68 12                      MVTC r1, USP
     521 00c8 02                            rts
    */
    }
    
    static __inline__ void *get_usp(void) __attribute__((always_inline));
    static __inline__ void *get_usp(void)
    {
    /* CC-RX V2.03
            MVFC USP, R1
            RTS
    */
        void *data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC USP, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     535 00c9 FD 6A 21                      MVFC USP, r1
     541 00cc 02                            rts
    */
    }
    
    static __inline__ void set_isp(void *data) __attribute__((always_inline));
    static __inline__ void set_isp(void *data)
    {
    /* CC-RX V2.03
            MVTC R1, ISP
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], ISP"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     554 00cd FD 68 1A                      MVTC r1, ISP
     556 00d0 02                            rts
    */
    }
    
    static __inline__ void *get_isp(void) __attribute__((always_inline));
    static __inline__ void *get_isp(void)
    {
    /* CC-RX V2.03
            MVFC ISP, R1
            RTS
    */
        void *data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC ISP, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     570 00d1 FD 6A A1                      MVFC ISP, r1
     576 00d4 02                            rts
    */
    }
    
    static __inline__ void set_intb(void *data) __attribute__((always_inline));
    static __inline__ void set_intb(void *data)
    {
    /* CC-RX V2.03
            MVTC R1, INTB
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], INTB"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     589 00d5 FD 68 1C                      MVTC r1, INTB
     591 00d8 02                            rts
    */
    }
    
    static __inline__ void *get_intb(void) __attribute__((always_inline));
    static __inline__ void *get_intb(void)
    {
    /* CC-RX V2.03
            MVFC INTB, R1
            RTS
    */
        void *data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC INTB, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     605 00d9 FD 6A C1                      MVFC INTB, r1
     611 00dc 02                            rts
    */
    }
    
    static __inline__ void set_bpsw(unsigned long data) __attribute__((always_inline));
    static __inline__ void set_bpsw(unsigned long data)
    {
    /* CC-RX V2.03
            MVTC R1, BPSW
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], BPSW"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     624 00dd FD 68 18                      MVTC r1, BPSW
     626 00e0 02                            rts
    */
    }
    
    static __inline__ unsigned long get_bpsw(void) __attribute__((always_inline));
    static __inline__ unsigned long get_bpsw(void)
    {
    /* CC-RX V2.03
            MVFC BPSW, R1
            RTS
    */
        unsigned long data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC BPSW, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     640 00e1 FD 6A 81                      MVFC BPSW, r1
     646 00e4 02                            rts
    */
    }
    
    static __inline__ void set_bpc(void *data) __attribute__((always_inline));
    static __inline__ void set_bpc(void *data)
    {
    /* CC-RX V2.03
            MVTC R1, BPC
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], BPC"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     659 00e5 FD 68 19                      MVTC r1, BPC
     661 00e8 02                            rts
    */
    }
    
    static __inline__ void *get_bpc(void) __attribute__((always_inline));
    static __inline__ void *get_bpc(void)
    {
    /* CC-RX V2.03
            MVFC BPC, R1
            RTS
    */
        void *data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC BPC, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     675 00e9 FD 6A 91                      MVFC BPC, r1
     681 00ec 02                            rts
    */
    }
    
    static __inline__ void set_fintv(void *data) __attribute__((always_inline));
    static __inline__ void set_fintv(void *data)
    {
    /* CC-RX V2.03
            MVTC R1, FINTV
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], FINTV"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     694 00ed FD 68 1B                      MVTC r1, FINTV
     696 00f0 02                            rts
    */
    }
    
    static __inline__ void *get_fintv(void) __attribute__((always_inline));
    static __inline__ void *get_fintv(void)
    {
    /* CC-RX V2.03
            MVFC FINTV, R1
            RTS
    */
        void *data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC FINTV, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     710 00f1 FD 6A B1                      MVFC FINTV, r1
     716 00f4 02                            rts
    */
    }
    
    static __inline__ signed long long emul(signed long data1, signed long data2) __attribute__((always_inline));
    static __inline__ signed long long emul(signed long data1, signed long data2)
    {
    /* CC-RX V2.03
            MOV.L R1, R4
            EMUL R2, R4
            MOV.L R5, R2
            MOV.L R4, R1
            RTS
    */
        return (signed long long)data1 * data2;
    /* GNURX 2018q1
     728 00f5 FC 1B 12                      emul    r1, r2
     733 00f8 EF 21                         mov.L   r2, r1
     735 00fa EF 32                         mov.L   r3, r2
     736 00fc 02                            rts
    */
    }
    
    static __inline__ unsigned long long emulu(unsigned long data1, unsigned long data2) __attribute__((always_inline));
    static __inline__ unsigned long long emulu(unsigned long data1, unsigned long data2)
    {
    /* CC-RX V2.03
            MOV.L R1, R4
            EMULU R2, R4
            MOV.L R5, R2
            MOV.L R4, R1
            RTS
    */
        return (unsigned long long)data1 * data2;
    /* GNURX 2018q1
     748 00fd FC 1F 12                      emulu   r1, r2
     753 0100 EF 21                         mov.L   r2, r1
     755 0102 EF 32                         mov.L   r3, r2
     756 0104 02                            rts
    */
    }
    
    static __inline__ void chg_pmusr(void) __attribute__((always_inline));
    static __inline__ void chg_pmusr(void)
    {
    /* CC-RX V2.03
            MVFC PSW, R14
            BTST #14H, R14
            BNE L48
    L47:    ; entry
            OR #00100000H, R14
            PUSH.L R14
    L49:
            MVFC PC, R14
            ADD #L48-L49, R14
            PUSH.L R14
            RTE
    L48:    ; entry
            RTS
    */
        signed long temp;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC PSW, %[R14]\n\t"
            "BTST #0x14, %[R14]\n\t"
            "BNE 3f\n"
    "1:\n\t"
            "OR #0x00100000, %[R14]\n\t"
            "PUSH.L %[R14]\n"
    "2:\n\t"
            "MVFC PC, %[R14]\n\t"
            "ADD #3f-2b, %[R14]\n\t"
            "PUSH.L %[R14]\n\t"
            "RTE\n"
    "3:"
            : /* OutputOperands */
                [R14] "=r" (temp)
        );
        return;
    /* GNURX 2018q1
     768 0105 FD 6A 05                      MVFC PSW, r5
     769 0108 7D 45                         BTST #0x14, r5
     770 010a 21 13                         BNE 3f
     771                                1:
     772 010c 77 35 00 00 10                OR #0x00100000, r5
     773 0111 7E A5                         PUSH.L r5
     774                                2:
     775 0113 FD 6A 15                      MVFC PC, r5
     776 0116 71 55 0A                      ADD #3f-2b, r5
     777 0119 7E A5                         PUSH.L r5
     778 011b 7F 95                         RTE
     779                                3:
     783 011d 02                            rts
    */
    }
    
    static __inline__ void set_acc(signed long long data) __attribute__((always_inline));
    static __inline__ void set_acc(signed long long data)
    {
    /* CC-RX V2.03
            MVTACLO R1
            MVTACHI R2
            RTS
    */
        signed long temp1 = (signed long)data;
        signed long temp2 = (signed long)(data >> 32);
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTACLO R1\n\t"
            "MVTACHI R2"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (temp1),
                [R2] "r" (temp2)
        );
        return;
    /* GNURX 2018q1
     797 011e FD 17 11                      MVTACLO R1
     798 0121 FD 17 02                      MVTACHI R2
     800 0124 02                            rts
    */
    }
    
    static __inline__ signed long long get_acc(void) __attribute__((always_inline));
    static __inline__ signed long long get_acc(void)
    {
    /* CC-RX V2.03
            MVFACMI R1
            SHLL #10H, R1
            MVFACHI R2
            RTS
    */
        unsigned long temp1;
        unsigned long temp2;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFACMI R1\n\t"
            "SHLL #0x10, R1\n\t"
            "MVFACHI R2"
            : /* OutputOperands */
                [R1] "=r" (temp1),
                [R2] "=r" (temp2)
        );
        return (unsigned long long)((((unsigned long long)temp2) << 32) | temp1);
    /* GNURX 2018q1
     813 0125 FD 1F 21                      MVFACMI R1
     814 0128 6D 01                         SHLL #0x10, R1
     815 012a FD 1F 02                      MVFACHI R2
     817 012d 02                            rts
    */
    }
    
    static __inline__ void setpsw_i(void) __attribute__((always_inline));
    static __inline__ void setpsw_i(void)
    {
    /* CC-RX V2.03
            SETPSW I
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "SETPSW I"
            : /* OutputOperands */
                /* No outputs. */
        );
        return;
    /* GNURX 2018q1
     829 012e 7F A8                         SETPSW I
     831 0130 02                            rts
    */
    }
    
    static __inline__ void clrpsw_i(void) __attribute__((always_inline));
    static __inline__ void clrpsw_i(void)
    {
    /* CC-RX V2.03
            CLRPSW I
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "CLRPSW I"
            : /* OutputOperands */
                /* No outputs. */
        );
        return;
    /* GNURX 2018q1
     845 0131 7F B8                         CLRPSW I
     847 0133 02                            rts
    */
    }
    
    static __inline__ long macl(short *data1, short *data2, unsigned long count) __attribute__((always_inline));
    static __inline__ long macl(short *data1, short *data2, unsigned long count)
    {
    /* CC-RX V2.03
            CMP #00H, R3
            MOV.L #00000000H, R14
            MULLO R14, R14
            BEQ L60
    L55:    ; entry
            BTST #00H, R3
            BGEU L57
    L56:    ; entry
            SUB #02H, R3
            MOV.L [R1+], R14
            MOV.L [R2+], R5
            MACLO R14, R5
            MACHI R14, R5
            BNE L56
            BRA L60
    L57:    ; entry
            SUB #01H, R3
            BEQ L59
    L58:    ; entry
            SUB #02H, R3
            MOV.L [R1+], R14
            MOV.L [R2+], R5
            MACLO R14, R5
            MACHI R14, R5
            BNE L58
    L59:    ; entry
            MOV.W [R1], R14
            MOV.W [R2], R5
            MACLO R14, R5
    L60:    ; entry
            MVFACMI R1
            RTS
    */
        long temp1;
        long temp2;
        long result;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "CMP #0x00, %[R3]\n\t"
            "MOV.L #0x00000000, %[R14]\n\t"
            "MULLO %[R14], %[R14]\n\t"
            "BEQ 6f\n\t"
    "1:\n\t"
            "BTST #0x00, %[R3]\n\t"
            "BGEU 3f\n\t"
    "2:\n\t"
            "SUB #0x02, %[R3]\n\t"
            "MOV.L [%[R1]+], %[R14]\n\t"
            "MOV.L [%[R2]+], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
            "MACHI %[R14], %[R5]\n\t"
            "BNE 2b\n\t"
            "BRA 6f\n\t"
    "3:\n\t"
            "SUB #0x01, %[R3]\n\t"
            "BEQ 5f\n\t"
    "4:\n\t"
            "SUB #0x02, %[R3]\n\t"
            "MOV.L [%[R1]+], %[R14]\n\t"
            "MOV.L [%[R2]+], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
            "MACHI %[R14], %[R5]\n\t"
            "BNE 4b\n\t"
    "5:\n\t"
            "MOV.W [%[R1]], %[R14]\n\t"
            "MOV.W [%[R2]], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
    "6:\n\t"
            "MVFACMI %[R99]"
            : /* OutputOperands */
                [R5] "+r" (temp1),
                [R14] "+r" (temp2),
                [R99] "=r" (result)
            : /* InputOperands */
                [R1] "r" (data1),
                [R2] "r" (data2),
                [R3] "r" (count)
        );
        return result;
    /* GNURX 2018q1
     859 0134 66 05                         mov.L   #0, r5
     860 0136 EF 54                         mov.L   r5, r4
     862 0138 61 03                         CMP #0x00, r3
     863 013a 66 04                         MOV.L #0x00000000, r4
     864 013c FD 01 44                      MULLO r4, r4
     865 013f 20 33                         BEQ 6f
     866                                    1:
     867 0141 7C 03                         BTST #0x00, r3
     868 0143 22 14                         BGEU 3f
     869                                    2:
     870 0145 60 23                         SUB #0x02, r3
     871 0147 FD 2A 14                      MOV.L [r1+], r4
     872 014a FD 2A 25                      MOV.L [r2+], r5
     873 014d FD 05 45                      MACLO r4, r5
     874 0150 FD 04 45                      MACHI r4, r5
     875 0153 21 F2                         BNE 2b
     876 0155 2E 1D                         BRA 6f
     877                                    3:
     878 0157 60 13                         SUB #0x01, r3
     879 0159 20 12                         BEQ 5f
     880                                    4:
     881 015b 60 23                         SUB #0x02, r3
     882 015d FD 2A 14                      MOV.L [r1+], r4
     883 0160 FD 2A 25                      MOV.L [r2+], r5
     884 0163 FD 05 45                      MACLO r4, r5
     885 0166 FD 04 45                      MACHI r4, r5
     886 0169 21 F2                         BNE 4b
     887                                    5:
     888 016b DC 14                         MOV.W [r1], r4
     889 016d DC 25                         MOV.W [r2], r5
     890 016f FD 05 45                      MACLO r4, r5
     891                                    6:
     892 0172 FD 1F 21                      MVFACMI r1
     895 0175 02                            rts
    */
    }
    
    static __inline__ short macw1(short *data1, short *data2, unsigned long count) __attribute__((always_inline));
    static __inline__ short macw1(short *data1, short *data2, unsigned long count)
    {
    /* CC-RX V2.03
            CMP #00H, R3
            MOV.L #00000000H, R14
            MULLO R14, R14
            BEQ L67
    L62:    ; entry
            BTST #00H, R3
            BGEU L64
    L63:    ; entry
            SUB #02H, R3
            MOV.L [R1+], R14
            MOV.L [R2+], R5
            MACLO R14, R5
            MACHI R14, R5
            BNE L63
            BRA L67
    L64:    ; entry
            SUB #01H, R3
            BEQ L66
    L65:    ; entry
            SUB #02H, R3
            MOV.L [R1+], R14
            MOV.L [R2+], R5
            MACLO R14, R5
            MACHI R14, R5
            BNE L65
    L66:    ; entry
            MOV.W [R1], R14
            MOV.W [R2], R5
            MACLO R14, R5
    L67:    ; entry
            RACW #01H
            MVFACHI R1
            RTS
    */
        long temp1;
        long temp2;
        short result;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "CMP #0x00, %[R3]\n\t"
            "MOV.L #0x00000000, %[R14]\n\t"
            "MULLO %[R14], %[R14]\n\t"
            "BEQ 6f\n\t"
    "1:\n\t"
            "BTST #0x00, %[R3]\n\t"
            "BGEU 3f\n\t"
    "2:\n\t"
            "SUB #0x02, %[R3]\n\t"
            "MOV.L [%[R1]+], %[R14]\n\t"
            "MOV.L [%[R2]+], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
            "MACHI %[R14], %[R5]\n\t"
            "BNE 2b\n\t"
            "BRA 6f\n\t"
    "3:\n\t"
            "SUB #0x01, %[R3]\n\t"
            "BEQ 5f\n\t"
    "4:\n\t"
            "SUB #0x02, %[R3]\n\t"
            "MOV.L [%[R1]+], %[R14]\n\t"
            "MOV.L [%[R2]+], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
            "MACHI %[R14], %[R5]\n\t"
            "BNE 4b\n\t"
    "5:\n\t"
            "MOV.W [%[R1]], %[R14]\n\t"
            "MOV.W [%[R2]], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
    "6:\n\t"
            "RACW #0x01\n\t"
            "MVFACMI %[R99]"
            : /* OutputOperands */
                [R5] "+r" (temp1),
                [R14] "+r" (temp2),
                [R99] "=r" (result)
            : /* InputOperands */
                [R1] "r" (data1),
                [R2] "r" (data2),
                [R3] "r" (count)
        );
        return result;
    /* GNURX 2018q1
     907 0176 66 05                         mov.L   #0, r5
     908 0178 EF 54                         mov.L   r5, r4
     910 017a 61 03                         CMP #0x00, r3
     911 017c 66 04                         MOV.L #0x00000000, r4
     912 017e FD 01 44                      MULLO r4, r4
     913 0181 20 33                         BEQ 6f
     914                                    1:
     915 0183 7C 03                         BTST #0x00, r3
     916 0185 22 14                         BGEU 3f
     917                                    2:
     918 0187 60 23                         SUB #0x02, r3
     919 0189 FD 2A 14                      MOV.L [r1+], r4
     920 018c FD 2A 25                      MOV.L [r2+], r5
     921 018f FD 05 45                      MACLO r4, r5
     922 0192 FD 04 45                      MACHI r4, r5
     923 0195 21 F2                         BNE 2b
     924 0197 2E 1D                         BRA 6f
     925                                    3:
     926 0199 60 13                         SUB #0x01, r3
     927 019b 20 12                         BEQ 5f
     928                                    4:
     929 019d 60 23                         SUB #0x02, r3
     930 019f FD 2A 14                      MOV.L [r1+], r4
     931 01a2 FD 2A 25                      MOV.L [r2+], r5
     932 01a5 FD 05 45                      MACLO r4, r5
     933 01a8 FD 04 45                      MACHI r4, r5
     934 01ab 21 F2                         BNE 4b
     935                                    5:
     936 01ad DC 14                         MOV.W [r1], r4
     937 01af DC 25                         MOV.W [r2], r5
     938 01b1 FD 05 45                      MACLO r4, r5
     939                                    6:
     940 01b4 FD 18 00                      RACW #0x01
     941 01b7 FD 1F 21                      MVFACMI r1
     947 01ba DF 11                         mov.W   r1, r1
     948 01bc 02                            rts
    */
    }
    
    static __inline__ short macw2(short *data1, short *data2, unsigned long count) __attribute__((always_inline));
    static __inline__ short macw2(short *data1, short *data2, unsigned long count)
    {
    /* CC-RX V2.03
            CMP #00H, R3
            MOV.L #00000000H, R14
            MULLO R14, R14
            BEQ L74
    L69:    ; entry
            BTST #00H, R3
            BGEU L71
    L70:    ; entry
            SUB #02H, R3
            MOV.L [R1+], R14
            MOV.L [R2+], R5
            MACLO R14, R5
            MACHI R14, R5
            BNE L70
            BRA L74
    L71:    ; entry
            SUB #01H, R3
            BEQ L73
    L72:    ; entry
            SUB #02H, R3
            MOV.L [R1+], R14
            MOV.L [R2+], R5
            MACLO R14, R5
            MACHI R14, R5
            BNE L72
    L73:    ; entry
            MOV.W [R1], R14
            MOV.W [R2], R5
            MACLO R14, R5
    L74:    ; entry
            RACW #02H
            MVFACHI R1
            RTS
    */
        long temp1;
        long temp2;
        short result;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "CMP #0x00, %[R3]\n\t"
            "MOV.L #0x00000000, %[R14]\n\t"
            "MULLO %[R14], %[R14]\n\t"
            "BEQ 6f\n\t"
    "1:\n\t"
            "BTST #0x00, %[R3]\n\t"
            "BGEU 3f\n\t"
    "2:\n\t"
            "SUB #0x02, %[R3]\n\t"
            "MOV.L [%[R1]+], %[R14]\n\t"
            "MOV.L [%[R2]+], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
            "MACHI %[R14], %[R5]\n\t"
            "BNE 2b\n\t"
            "BRA 6f\n\t"
    "3:\n\t"
            "SUB #0x01, %[R3]\n\t"
            "BEQ 5f\n\t"
    "4:\n\t"
            "SUB #0x02, %[R3]\n\t"
            "MOV.L [%[R1]+], %[R14]\n\t"
            "MOV.L [%[R2]+], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
            "MACHI %[R14], %[R5]\n\t"
            "BNE 4b\n\t"
    "5:\n\t"
            "MOV.W [%[R1]], %[R14]\n\t"
            "MOV.W [%[R2]], %[R5]\n\t"
            "MACLO %[R14], %[R5]\n\t"
    "6:\n\t"
            "RACW #02H\n\t"
            "MVFACMI %[R99]"
            : /* OutputOperands */
                [R5] "+r" (temp1),
                [R14] "+r" (temp2),
                [R99] "=r" (result)
            : /* InputOperands */
                [R1] "r" (data1),
                [R2] "r" (data2),
                [R3] "r" (count)
        );
        return result;
    /* GNURX 2018q1
     960 01bd 66 05                         mov.L   #0, r5
     961 01bf EF 54                         mov.L   r5, r4
     963 01c1 61 03                         CMP #0x00, r3
     964 01c3 66 04                         MOV.L #0x00000000, r4
     965 01c5 FD 01 44                      MULLO r4, r4
     966 01c8 20 33                         BEQ 6f
     967                                    1:
     968 01ca 7C 03                         BTST #0x00, r3
     969 01cc 22 14                         BGEU 3f
     970                                    2:
     971 01ce 60 23                         SUB #0x02, r3
     972 01d0 FD 2A 14                      MOV.L [r1+], r4
     973 01d3 FD 2A 25                      MOV.L [r2+], r5
     974 01d6 FD 05 45                      MACLO r4, r5
     975 01d9 FD 04 45                      MACHI r4, r5
     976 01dc 21 F2                         BNE 2b
     977 01de 2E 1D                         BRA 6f
     978                                    3:
     979 01e0 60 13                         SUB #0x01, r3
     980 01e2 20 12                         BEQ 5f
     981                                    4:
     982 01e4 60 23                         SUB #0x02, r3
     983 01e6 FD 2A 14                      MOV.L [r1+], r4
     984 01e9 FD 2A 25                      MOV.L [r2+], r5
     985 01ec FD 05 45                      MACLO r4, r5
     986 01ef FD 04 45                      MACHI r4, r5
     987 01f2 21 F2                         BNE 4b
     988                                    5:
     989 01f4 DC 14                         MOV.W [r1], r4
     990 01f6 DC 25                         MOV.W [r2], r5
     991 01f8 FD 05 45                      MACLO r4, r5
     992                                    6:
     993 01fb FD 18 10                      RACW #02H
     994 01fe FD 1F 21                      MVFACMI r1
     1000 0201 DF 11                        mov.W   r1, r1
     1001 0203 02                           rts
    */
    }
    
    static __inline__ void set_extb(void *data) __attribute__((always_inline));
    static __inline__ void set_extb(void *data)
    {
    /* CC-RX V2.03
            MVTC R1, EXTB
            RTS
    */
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVTC %[R1], EXTB"
            : /* OutputOperands */
                /* No outputs. */
            : /* InputOperands */
                [R1] "r" (data)
        );
        return;
    /* GNURX 2018q1
     1014 0204 FD 68 1D                     MVTC r1, EXTB
     1016 0207 02                           rts
     */
    }
    
    static __inline__ void *get_extb(void) __attribute__((always_inline));
    static __inline__ void *get_extb(void)
    {
    /* CC-RX V2.03
            MVFC EXTB, R1
            RTS
    */
        void *data;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MVFC EXTB, %[R1]"
            : /* OutputOperands */
                [R1] "=r" (data)
        );
        return data;
    /* GNURX 2018q1
     1030 0208 FD 6A D1                     MVFC EXTB, r1
     1036 020b 02                           rts
    */
    }
    
    #endif /* CCRXMACHINE2_H */
    


    CCRXmachine2.c
    5342.CCRXmachine2_c_20180610.txt
    #define DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK
    
    #ifdef DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK
    
    #if 1
    #define INTNUM(num)\
        __builtin_rx_int(num)
    #else
    #define INTNUM(num)\
        __asm__ volatile\
        (\
            /* AssemblerTemplate */\
            "INT #" #num \
            : /* OutputOperands */\
                /* No outputs. */\
        )
    #endif
    
    #define INTN(N)\
        case N:\
        INTNUM(N);\
        break;
    
    #define INTN5(N)\
        INTN(N)\
        INTN(N+1)\
        INTN(N+2)\
        INTN(N+3)\
        INTN(N+4)
    
    #define INTN10(N)\
        INTN5(N)\
        INTN5(N+5)
    
    #define INTN50(N)\
        INTN10(N)\
        INTN10(N+10)\
        INTN10(N+20)\
        INTN10(N+30)\
        INTN10(N+40)
    
    void int_exception_switch_case_function(signed long num);
    void int_exception_switch_case_function(signed long num)
    {
        switch(num)
        {
        INTN50(0)
        INTN50(50)
        INTN50(100)
        INTN50(150)
        INTN50(200)
        INTN5(250)
        INTN(255)
        default:
        INTNUM(255);
        }
    }
    
    #endif /* DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK */
    


    TestGNURX_CCRXmachine2_h.c
    6685.TestGNURX_CCRXmachine2_h_c_20180610.txt
    //#include "r_smc_entry.h"
    //#define DONT_EXECUTE_RX_INT_INSTRUCTION_ON_STACK
    #include "CCRXmachine2.h"
    
    signed long        _max(signed long data1, signed long data2)                                          { return max(data1, data2);                }
    signed long        _min(signed long data1, signed long data2)                                          { return min(data1, data2);                }
    unsigned long      _revl(unsigned long data)                                                           { return revl(data);                       }
    unsigned long      _revw(unsigned long data)                                                           { return revw(data);                       }
    void               _xchg(signed long *data1, signed long *data2)                                       {        xchg(data1, data2);               }
    long long          _rmpab(long long init, unsigned long count, signed char *addr1, signed char *addr2) { return rmpab(init, count, addr1, addr2); }
    long long          _rmpaw(long long init, unsigned long count, short *addr1, short *addr2)             { return rmpaw(init, count, addr1, addr2); }
    long long          _rmpal(long long init, unsigned long count, long *addr1, long *addr2)               { return rmpal(init, count, addr1, addr2); }
    unsigned long      _rolc(unsigned long data)                                                           { return rolc(data);                       }
    unsigned long      _rorc(unsigned long data)                                                           { return rorc(data);                       }
    unsigned long      _rotl(unsigned long data, unsigned long num)                                        { return rotl(data, num);                  }
    unsigned long      _rotr(unsigned long data, unsigned long num)                                        { return rotr(data, num);                  }
    void               _brk(void)                                                                          {        brk();                            }
    void               _int_exception(signed long num)                                                     {        int_exception(num);               }
    void               _my_int_exception_0(void)                                                           {        int_exception(0);                 }
    void               _my_int_exception_255(void)                                                         {        int_exception(255);               }
    void               _wait(void)                                                                         {        wait();                           }
    void               _nop(void)                                                                          {        nop();                            }
    void               _set_ipl(signed long level)                                                         {        set_ipl(level);                   }
    unsigned char      _get_ipl(void)                                                                      { return get_ipl();                        }
    void               _set_psw(unsigned long data)                                                        {        set_psw(data);                    }
    unsigned long      _get_psw(void)                                                                      { return get_psw();                        }
    void               _set_fpsw(unsigned long data)                                                       {        set_fpsw(data);                   }
    unsigned long      _get_fpsw(void)                                                                     { return get_fpsw();                       }
    void               _set_usp(void *data)                                                                {        set_usp(data);                    }
    void *             _get_usp(void)                                                                      { return get_usp();                        }
    void               _set_isp(void *data)                                                                {        set_isp(data);                    }
    void *             _get_isp(void)                                                                      { return get_isp();                        }
    void               _set_intb(void *data)                                                               {        set_intb(data);                   }
    void *             _get_intb(void)                                                                     { return get_intb();                       }
    void               _set_bpsw(unsigned long data)                                                       {        set_bpsw(data);                   }
    unsigned long      _get_bpsw(void)                                                                     { return get_bpsw();                       }
    void               _set_bpc(void *data)                                                                {        set_bpc(data);                    }
    void *             _get_bpc(void)                                                                      { return get_bpc();                        }
    void               _set_fintv(void *data)                                                              {        set_fintv(data);                  }
    void *             _get_fintv(void)                                                                    { return get_fintv();                      }
    signed long long   _emul(signed long data1, signed long data2)                                         { return emul(data1, data2);               }
    unsigned long long _emulu(unsigned long data1, unsigned long data2)                                    { return emulu(data1, data2);              }
    void               _chg_pmusr(void)                                                                    {        chg_pmusr();                      }
    void               _set_acc(signed long long data)                                                     {        set_acc(data);                    }
    signed long long   _get_acc(void)                                                                      { return get_acc();                        }
    void               _setpsw_i(void)                                                                     {        setpsw_i();                       }
    void               _clrpsw_i(void)                                                                     {        clrpsw_i();                       }
    long               _macl(short *data1, short *data2, unsigned long count)                              { return macl(data1, data2, count);        }
    short              _macw1(short *data1, short *data2, unsigned long count)                             { return macw1(data1, data2, count);       }
    short              _macw2(short *data1, short *data2, unsigned long count)                             { return macw2(data1, data2, count);       }
    void               _set_extb(void *data)                                                               {        set_extb(data);                   }
    void *             _get_extb(void)                                                                     { return get_extb();                       }
    
    void main(void);
    void main(void)
    {
    	nop();
    	chg_pmusr();
    	nop();
    	for (;;) ;
    }
    

     

  • fujitaさん
    ほやです。

    >> xchg関数1つならそれもアリなのですが、他の組み込み関数までヘッダに記述するのはムリがあるかと。
    >えっなんで??
    >> CCRXmachine.hの中で、マクロに書き換えられるものをマクロに、
    >マクロよりはインライン関数の方が良いのでは。

    「関数本体をヘッダに」含めるのを嫌がる人は更に多いのでは。
    そもそもCCRXmachine.h/.cはCCRXの記述をできるだけ変更しないでGNURXに置き換えるためにあるのだから、
    関数名だけすげ替えれば済むものは、それで留めるべきだったと思います。xchg関数もその一つ。