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



  • fujitaさん、NoMaYさん
    検証による証明、ご指摘、ありがとうございます。
    お手数をおかけしました。

    本来のテーマから若干のずれは把握してましたが、
    一時変数を使用せず、変数の整数データを交換をするだけ。
    の意図でした。すみません。
  • ヘッダファイルに
    static inline void xchg(signed long *data1, signed long *data2) __attribute__((always_inline));
    static inline void xchg(signed long *data1, signed long *data2)
    {
        signed long temp = *data1;
        __asm __volatile(
            "    xchg [%1], %0\n"
            : "+r"(temp)
            : "r"(data2)
        );
        *data1 = temp;
    }
    
    とかあれば、

    ↑のコード宜しくないので数日中に修正版を投稿します。

  • ほやです。

    GCC for Renesas RX のMigration guideにビルトイン関数の記述がありました。
    参照: <toolchainのインストールフォルダ>/Doc/Renesas-GNURX Migration Guide.html#_Builtin_Functions
    GCC本家に掲載されているRX対応関数より増えてます。

    で、CCRXmachine.cのxchg関数を素直に書き換えたら XCHG命令が吐かれました。

    void xchg(signed long *data1, signed long *data2)
    {
    __builtin_rx_xchg (data1, data2);
    }
    初めにこれを試すべきでした。

    ただし-fltoを付けないと関数呼び出しになってしまうのは変わりません。 関数本体の宣言の前にalways_inline 付けても効きませんでした。
    良く考えてみれば、個別に作成済みのobj同士をリンカにポイっと渡して埋め込めと言っても、それは難しいかも...
  • ほやさん、fujitaさん、NoMaYさん、LEONさん

    こんにちは、シェルティです。

    種々ご検討ありがとうございます。内部検討状況を報告します。

    課題は以下3点と認識しています。

    ①GCCRX用のBSPに内蔵されるlocking.c (のR_BSP_SoftwareLock()実装)のxchg()実装
    ②CCRXmachine.cのxchg()実装
     -1: ローカル変数を使ったデータ交換形式になっている
     -2: 関数呼び出し形式なのでオーバヘッドがある
    ③GCCRXはXCHG命令を出力できない

    いくつかは対策をすでに皆様に出していただいているものがありますね。
    以下方向で進めてまいります。

    ①GCCRXでも xchg() を呼び出す
    ②-1:XCHG用のビルトイン関数を利用する
     -2:インライン展開を利用するなど性能面に気を遣った実装を考える
    ③実はGCCRXはXCHG命令を出力できる

    以上です
  • > ②-1:XCHG用のビルトイン関数を利用する

    __builtin_rx_xchg() は GCCRX の版によっては使えないので、複数の版の GCCRX をサポートしてる筈の e2studio では使用が難しいのではないかと思います。

    少なくとも手許の PC にインストールされていた 14.01 では機能せず、なんかわからん関数としてコンパイルされました。

    $ cat -n hogera.c
         1  void hogera(int* data1, int* data2)
         2  {
         3      __builtin_rx_xchg(data1, data2);
         4  }
    $ rx-elf-gcc -v
    Using built-in specs.
    COLLECT_GCC=C:\PROGRA~2\Renesas\Hew\Tools\KPIT\GNURX-~1\v14.01\rx-elf\bin\rx-elf-gcc.exe
    COLLECT_LTO_WRAPPER=c:/progra~2/renesas/hew/tools/kpit/gnurx-~1/v14.01/rx-elf/bin/../libexec/gcc/rx-elf/4.7-GNURX_v14.01/lto-wrapper.exe
    Target: rx-elf
    Configured with: /home/kpit/fsfsrc/elf-v14.01-src//gcc-4.7.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpfr=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpc=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --prefix=/usr/share/mingwgnurx_v14.01_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch : (reconfigured) /home/kpit/fsfsrc/elf-v14.01-src//gcc-4.7.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpfr=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpc=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --prefix=/usr/share/mingwgnurx_v14.01_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch : (reconfigured) /home/kpit/fsfsrc/elf-v14.01-src//gcc-4.7.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpfr=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpc=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --prefix=/usr/share/mingwgnurx_v14.01_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch : (reconfigured) /home/kpit/fsfsrc/elf-v14.01-src//gcc-4.7.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpfr=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --with-mpc=/home/kpit/pre-requisite/gcc-4.5.x/mingw/prefix --prefix=/usr/share/mingwgnurx_v14.01_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch
    Thread model: single
    gcc version 4.7-GNURX_v14.01 (GCC)
    
    $ rx-elf-gcc -Wall -Wextra -O2 -S -o - hogera.c
            .file   "hogera.c"
    hogera.c: In function 'hogera':
    hogera.c:3:5: warning: implicit declaration of function '__builtin_rx_xchg' [-Wimplicit-function-declaration]
            .section P,"ax"
            .global _hogera
            .type   _hogera, @function
    _hogera:
            bra     ___builtin_rx_xchg
            .size   _hogera, .-_hogera
            .ident  "GCC: (GNU) 4.7-GNURX_v14.01"
    
    $
    

    14.03 では通った。

    $ rx-elf-gcc -v
    Using built-in specs.
    COLLECT_GCC=C:\Renesas\e2studio\GNURXV~1.03-\rx-elf\rx-elf\bin\rx-elf-gcc.exe
    COLLECT_LTO_WRAPPER=c:/renesas/e2studio/gnurxv~1.03-/rx-elf/rx-elf/bin/../libexec/gcc/rx-elf/4.8-GNURX_v14.03/lto-wrapper.exe
    Target: rx-elf
    Configured with: /home/kpit/fsfsrc/elf-v14.03-src//gcc-4.8.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpfr=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpc=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --prefix=/usr/share//mingwgnurx_v14.03_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC : (reconfigured) /home/kpit/fsfsrc/elf-v14.03-src//gcc-4.8.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpfr=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpc=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --prefix=/usr/share//mingwgnurx_v14.03_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC : (reconfigured) /home/kpit/fsfsrc/elf-v14.03-src//gcc-4.8.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpfr=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpc=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --prefix=/usr/share//mingwgnurx_v14.03_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC : (reconfigured) /home/kpit/fsfsrc/elf-v14.03-src//gcc-4.8.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpfr=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpc=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --prefix=/usr/share//mingwgnurx_v14.03_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC : (reconfigured) /home/kpit/fsfsrc/elf-v14.03-src//gcc-4.8.3/configure --disable-shared --build=i686-pc-linux-gnu --host=i386-pc-mingw32msvc --enable-languages=c,c++ --target=rx-elf --with-newlib --with-gmp=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpfr=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --with-mpc=/home/vinayk/utilities/mingw_gmp_mpfr/prefix/ --prefix=/usr/share//mingwgnurx_v14.03_elf-1 --enable-lto --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC_Build_1.01
    Thread model: single
    gcc version 4.8-GNURX_v14.03 (GCC_Build_1.01)
    
    $ rx-elf-gcc -Wall -Wextra -O2 -S -o - hogera.c
            .file   "hogera.c"
            .section P,"ax"
            .global _hogera
            .type   _hogera, @function
    _hogera:
            mov.L   [r1], r14
            xchg    [r2].L, r14
            mov.L   r14, [r1]
            rts
            .size   _hogera, .-_hogera
            .ident  "GCC: (GCC_Build_1.01) 4.8-GNURX_v14.03"
    
    $
    
  • > で、CCRXmachine.cのxchg関数を素直に書き換えたら XCHG命令が吐かれました。

    > ただし-fltoを付けないと関数呼び出しになってしまうのは変わりません。 関数本体の宣言の前にalways_inline 付けても効きませんでした。

    > 良く考えてみれば、個別に作成済みのobj同士をリンカにポイっと渡して埋め込めと言っても、それは難しいかも...

    https://japan.renesasrulz.com/cafe_rene/f/forum5/5046/gnurx-ccrxmachine-h-ccrxmachine-c-e2-studio/28376#28376 の投稿で「ヘッダファイルに~」とある通り、CCRXmachine.c ではなく CCRXmachine.h に記述する話をしています。

  • fujitaさん

    シェルティです。ありがとうございます。

    なるほど、コンパイラバージョンのプリデファインマクロで切り分けて
    特定バージョン以下の場合はビルトイン関数を使わない(インライン展開でXCHG命令埋め込み)対策コード、
    特定バージョン以上はビルトイン関数を使う対策コード、とすべきですね。

    いま、専門の人が調べてくれてます。何らか対策が定まってきましたら、また報告させていただきます。

    以上です
  • こんにちは。NoMaYです。

    今朝、ちょっと頭に浮かんだ言葉があります。今回の件がどうなのかは分かりませんが、、、

    「GNURXへの愛ゆえに仕方が無いと現状のコードを擁護するか、GNURXへの愛ゆえにもっと良いコードが書けるのにと批判するか」

    それはそれとして、xchg()関数の他にmacl()関数を調べてみました。CC-RXでは、ループアンローリングまでして実行性能に気を使っているようですね。 [訂正]すみません、違っていました。でも、何だろう、、、 [再度訂正]再度すみません。素朴なループアンローリングではありませんでしたが、RXマイコンのMACLO命令とMACHI命令の動作をうまく利用してループ回数を半分にする技巧が使われていました。[ここまで] GNURX対応のCCRXmachine.cでは、呼び出しているビルトイン関数の事情で無駄なレジスタ操作が増えてしまっているのと、returnの部分の非効率さが、目に付きますね、、、([追記] CC-RXのmacl()関数のコードを理解した後で見るとCCRXmachine.cのmacl()関数のコードは変な気がします。)

    ●CC-RXの記述

    machine.h

    #ifndef _MACHINE
    #define _MACHINE
    #include <macro.h>

    #include <builtin.h>

    ・・・
    #define macl(data1, data2, count)        _builtin_macl(data1, data2, count)
    ・・・

    #endif

    builtin.h

    #ifndef _BUILTIN
    #define _BUILTIN
    #include <macro.h>

    #ifdef __cplusplus
    extern "C" {
    #endif

    /* follow machine.h */
    ・・・
    extern long           _builtin_macl(short *, short *, unsigned long);
    ・・・

    #ifdef __cplusplus
    }
    #endif /* #ifdef __cplusplus */

    #endif /* #ifndef _BUILTIN */

    ●GNURX対応のCCRXmachin.hとCCRXmachin.cの記述

    CCRXmachin.h

    ・・・
    long macl(short* data1, short* data2, unsigned long count);
    ・・・

    CCRXmachin.c

    signed long long get_acc(void)
    {
        signed long long result = ((signed long long)__builtin_rx_mvfachi()) << 32;
        result |= (((signed long long)__builtin_rx_mvfacmi()) << 16) & 0xFFFF0000;
        return result;
    }
    ・・・
    long macl(short* data1, short* data2, unsigned long count)
    {
        unsigned long index;
        __builtin_rx_mullo(0, 0);
        for(index = 0; index < count; index++)
        {
            __builtin_rx_maclo(data1[index], data2[index]);
            __builtin_rx_machi(data1[index], data2[index]);
        }
        return (long)(get_acc() >> 16);
    }

    ●CC-RXでの生成コード(当方特有の事情でCC-RX V2.03を使用)

    Cソース

    long macl__(short* data1, short* data2, unsigned long count);

    long macl__(short *data1, short *data2, unsigned long count )
    {
        return macl(data1, data2, count);
    }

    リストファイル

                                     ;      31 long macl__(short *data1, short *data2, unsigned long count )
    00000001 6103                                   CMP #00H, R3
                                     ;      32 {
                                     ;      33      return macl(data1, data2, count);
    00000003 660E                                   MOV.L #00000000H, R14
    00000005 FD01EE                                 MULLO R14, R14
    00000008 20rr                                   BEQ L17
    0000000A                         L12:   ; entry
    0000000A 7C03                                   BTST #00H, R3
    0000000C 22rr                                   BGEU L14
    0000000E                         L13:   ; entry
    0000000E 6023                                   SUB #02H, R3
    00000010 FD2A1E                                 MOV.L [R1+], R14
    00000013 FD2A25                                 MOV.L [R2+], R5
    00000016 FD05E5                                 MACLO R14, R5
    00000019 FD04E5                                 MACHI R14, R5
    0000001C 21rr                                   BNE L13
    0000001E 2Err                 B                 BRA L17
    00000020                         L14:   ; entry
    00000020 6013                                   SUB #01H, R3
    00000022 20rr                                   BEQ L16
    00000024                         L15:   ; entry
    00000024 6023                                   SUB #02H, R3
    00000026 FD2A1E                                 MOV.L [R1+], R14
    00000029 FD2A25                                 MOV.L [R2+], R5
    0000002C FD05E5                                 MACLO R14, R5
    0000002F FD04E5                                 MACHI R14, R5
    00000032 21rr                                   BNE L15
    00000034                         L16:   ; entry
    00000034 DC1E                                   MOV.W [R1], R14
    00000036 DC25                                   MOV.W [R2], R5
    00000038 FD05E5                                 MACLO R14, R5
    0000003B                         L17:   ; entry
    0000003B FD1F21                                 MVFACMI R1
                                     ;      34 }
    0000003E 02                                     RTS

    ●GNURXでの生成コード(2018q1を使用)

    リストファイル

     280:../src/CCRXmachine.c **** long macl(short* data1, short* data2, unsigned long count)
     281:../src/CCRXmachine.c **** {
     401 0105 7E A7                                 push.l  r7
     282:../src/CCRXmachine.c ****  unsigned long index;
     283:../src/CCRXmachine.c ****  __builtin_rx_mullo(0, 0);
     404 0107 66 05                                 mov.L   #0, r5
     405 0109 FD 01 55                              mullo   r5, r5
     284:../src/CCRXmachine.c ****  for(index = 0; index < count; index++)
     408 010c 47 53                                 cmp     r5, r3
     409 010e 20 1C                                 beq     .L41
     411                                            .balign 8,3,1
     412                                    .L42:
     413 0110 EF 14                                 mov.L   r1, r4
     414 0112 EF 2E                                 mov.L   r2, r14
     285:../src/CCRXmachine.c ****  {
     286:../src/CCRXmachine.c ****          __builtin_rx_maclo(data1[index], data2[index]);
     416 0114 FD 29 1F                              mov.W   [r1+], r15
     417 0117 FD 29 27                              mov.W   [r2+], r7
     418 011a FD 05 F7                              maclo   r15, r7
     287:../src/CCRXmachine.c ****          __builtin_rx_machi(data1[index], data2[index]);
     420 011d DC 44                                 mov.W   [r4], r4
     421 011f DC EE                                 mov.W   [r14], r14
     422 0121 FD 04 4E                              machi   r4, r14
     284:../src/CCRXmachine.c ****  for(index = 0; index < count; index++)
     424 0124 62 15                                 add     #1, r5
     426 0126 47 35                                 cmp     r3, r5
     427 0128 21 E8                                 bne     .L42
     429                                            .balign 8,3,2
     430                                    .L41:
     261:../src/CCRXmachine.c ****  result |= (((signed long long)__builtin_rx_mvfacmi()) << 16) & 0xFFFF0000;
     434 012a FD 1F 07                              mvfachi r7
     262:../src/CCRXmachine.c ****  return result;
     436 012d FD 1F 21                              mvfacmi r1
     288:../src/CCRXmachine.c ****  }
     289:../src/CCRXmachine.c ****  return (long)(get_acc() >> 16);
     440 0130 6D 07                                 shll    #16, r7
     441 0132 5F 11                                 movu.W  r1, r1
     442 0134 57 71                                 or      r7, r1
     290:../src/CCRXmachine.c **** }
     444 0136 3F 77 01                              rtsd    #4, r7-r7

     

  • こんにちは。NoMaYです。

    前の投稿でmacl()関数を調べてみて、何か腑に落ちない、という感覚があったのですが、どうもGNURX対応のCCRXmachine.cのmacl()関数はバグっていると思われます。

    以下のデータで結果を求めてみると、CC-RXのmacl()関数とGNURX対応のCCRXmachine.cのmacl()関数では結果が異なってしまいました。

    データ:
    short data1[3] = {-1, -2, -3};
    short data2[3] = {-1, -2, -3};

    プログラム:
    long result;
    result = macl(data1, data2, 3);

    期待値:
    (-1)*(-1) + (-2)*(-2) + (-3)*(-3) = 14

    結果:
    CC-RXのmacl()関数 → 14
    GNURX対応のCCRXmachine.cのmacl()関数 → 17

    これは私の推測なのですが、CC-RXのmacl()関数で使われているループ回数を半減させる技法をきちんと理解せずにコードを真似たことにより、GNURX対応のCCRXmachine.cのmacl()関数のコードにバグが入ってしまったのではないかと思われます、、、

  • ソース中 __builtin_rx_machi() が余計で
    (-1)*(-1) + (-2)*(-2) + (-3)*(-3) + (-1)*(-1) + (-1)*(-1) + (-1)*(-1) = 17
    を計算しているようです。
    データの値が全て正だと答えは合うはずなので、恐らくはそういうテストしかしてない気がしますね。