こんにちは。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.he2 studioインストールフォルダ\internal\projectgen\rx\Generate\CCRXConversion\inc\CCRXmachine.c
> この実装は駄目ですね
一時変数を使用した単なる交換では排他制御に使えないのも勿論ですが、実行効率を上げる等の目的で特別な命令を吐かせたいところで用意されてる組み込み関数をただの関数として用意している時点で呼び出しコストも発生するし何考えてんのかという感じですね。
$ cat -n hoge.c 1 #include <CCRXmachine.h> 2 3 extern signed long var0, var1, var2; 4 5 void hoge(void) 6 { 7 xchg(&var0, &var1); 8 xchg(&var1, &var2); 9 xchg(&var2, &var0); 10 } $ rx-elf-gcc -O2 -c hoge.c ; rx-elf-objdump -d hoge.o CCRXmachine.o hoge.o: file format elf32-rx-le Disassembly of section P: 00000000 <_hoge>: 0: fb 12 00 00 00 00 mov.l #0, r1 6: fb 22 00 00 00 00 mov.l #0, r2 c: 05 00 00 00 bsr.a c <_hoge+0xc> 10: fb 12 00 00 00 00 mov.l #0, r1 16: fb 22 00 00 00 00 mov.l #0, r2 1c: 05 00 00 00 bsr.a 1c <_hoge+0x1c> 20: fb 12 00 00 00 00 mov.l #0, r1 26: fb 22 00 00 00 00 mov.l #0, r2 2c: 04 00 00 00 bra.a 2c <_hoge+0x2c> CCRXmachine.o: file format elf32-rx-le Disassembly of section P: 00000000 <_xchg>: 0: ec 15 mov.l [r1], r5 2: e0 21 mov.l [r2], [r1] 4: e3 25 mov.l r5, [r2] 6: 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) { signed long temp = *data1; __asm __volatile( " xchg [%1], %0\n" : "+r"(temp) : "r"(data2) ); *data1 = temp; }
とかあれば、
$ cat -n piyo.c 1 #include <CCRXmachine.h> 2 3 extern signed long var0, var1, var2; 4 5 void piyo(void) 6 { 7 xchg(&var0, &var1); 8 xchg(&var1, &var2); 9 xchg(&var2, &var0); 10 } $ rx-elf-gcc -O2 -c piyo.c ; rx-elf-objdump -d piyo.o piyo.o: file format elf32-rx-le Disassembly of section P: 00000000 <_piyo>: 0: fb 32 00 00 00 00 mov.l #0, r3 6: ec 32 mov.l [r3], r2 8: fb 42 00 00 00 00 mov.l #0, r4 e: 06 a0 10 42 xchg [r4].l, r2 12: fb 52 00 00 00 00 mov.l #0, r5 18: e3 32 mov.l r2, [r3] 1a: ec 42 mov.l [r4], r2 1c: 06 a0 10 52 xchg [r5].l, r2 20: e3 42 mov.l r2, [r4] 22: ec 54 mov.l [r5], r4 24: 06 a0 10 34 xchg [r3].l, r4 28: e3 54 mov.l r4, [r5] 2a: 02 rts $
低コストで xchg 命令も吐けて良いと思うのだけどなあ。
ヘッダファイルに 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; } とかあれば、
↑のコード宜しくないので数日中に修正版を投稿します。
> ②-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 に記述する話をしています。
ほやです。自己亀レスで済みません。
> ただし-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の中で、マクロに書き換えられるものをマクロに、関数でないと難しいものだけ関数で宣言してあれば良かったのではないかと思います。
以上独り言でした。
fujitaさんほやです。
>> xchg関数1つならそれもアリなのですが、他の組み込み関数までヘッダに記述するのはムリがあるかと。>えっなんで??>> CCRXmachine.hの中で、マクロに書き換えられるものをマクロに、>マクロよりはインライン関数の方が良いのでは。
「関数本体をヘッダに」含めるのを嫌がる人は更に多いのでは。そもそもCCRXmachine.h/.cはCCRXの記述をできるだけ変更しないでGNURXに置き換えるためにあるのだから、関数名だけすげ替えれば済むものは、それで留めるべきだったと思います。xchg関数もその一つ。
> そもそもCCRXmachine.h/.cはCCRXの記述をできるだけ変更しないでGNURXに置き換えるためにあるのだから、 > 関数名だけすげ替えれば済むものは、それで留めるべきだったと思います。xchg関数もその一つ。
__builtin_rx_xchg() は GNURX の版によっては使えず、使える場合でも出力コードに問題があるようなので使うべきでないと思います。インラインアセンブラを使う他ないのでは。
例えばマクロで次のように書くと
#include <assert.h> #define xchg(data1, data2) \ do { \ _Static_assert(sizeof(typeof(*(data1))) == sizeof(signed long), "passing argument 1 of 'xchg' from incompatible pointer type"); \ _Static_assert(sizeof(typeof(*(data2))) == sizeof(signed long), "passing argument 2 of 'xchg' from incompatible pointer type"); \ signed long temp = *data1; \ __asm __volatile( \ "\n" \ "\txchg\t%1, %0 \n" \ : "+&r"(temp) \ : "m"(*data2) \ : \ ); \ *data1 = temp; \ } while (0)
引数 data1 や data2 に渡されるシンボル名が内部で使用する一時変数(↑の例ではtemp)とかち合わない運用ルールが発生します。
あるいは次のように書いた場合、
#include <assert.h> #define xchg(data1, data2) \ do { \ _Static_assert(sizeof(typeof(*(data1))) == sizeof(signed long), "passing argument 1 of 'xchg' from incompatible pointer type"); \ _Static_assert(sizeof(typeof(*(data2))) == sizeof(signed long), "passing argument 2 of 'xchg' from incompatible pointer type"); \ __asm __volatile( \ "\n" \ "\tmov.l\t%0, r5 \n" \ "\txchg\t%1, r5 \n" \ "\tmov.l\tr5, %0 \n" \ : \ : "m"(*data1), "m"(*data2) \ : "r5" \ ); \ } while (0)
一時変数に使用するレジスタに r5 (あるいはその他でも) を使用していますが、関数内でのレジスタの割り振りはコンパイラに任せた方が効率の良いコードを吐いてくれそうな気がする点が惜しいところですね。
インライン関数で
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( "\n" "\txchg\t%1, %0 \n" : "+&r"(temp) : "m"(*data2) : ); *data1 = temp; }
のように書けば先に挙げたマクロの問題もなく、記述もシンプルで幾らかマシなんではないでしょうか。
>>マクロよりはインライン関数の方が良いのでは。 >「関数本体をヘッダに」含めるのを嫌がる人は更に多いのでは。
上記のような理屈もないところでの好き嫌いの多数決に意味はないと思います。