こんにちは。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 命令も吐けて良いと思うのだけどなあ。
> Myマクロですがどうでしょうか。
個人的にはオブジェクトの交換を行いたい機会がさほどあるわけではないのでそれ用のマクロを用意する意義は感じないのですが、なんらかの理由で用意をするとして、抽象化を目的とするのであれば XOR 交換アルゴリズムは使用すべきではなく一時変数を使用する方法にすべきと思います。XOR 交換アルゴリズムは整数のオブジェクトにしか使用できず浮動小数点型や構造体等に対応できません。また、GNURX では上手く最適化できないようで、一時変数を使用する方法と比べて効率も良くないようです。
$ cat -n hoge.c 1 #define SWAP(a, b) (a)^=(b); (b)^=(a); (a)^=(b); // スワップ (a ⇔ b) 2 3 void charSwap(void) 4 { 5 extern char c0, c1; 6 SWAP(c0, c1); 7 } 8 9 void shortSwap(void) 10 { 11 extern short s0, s1; 12 SWAP(s0, s1); 13 } 14 15 void longSwap(void) 16 { 17 extern long l0, l1; 18 SWAP(l0, l1); 19 } 20 21 void longLongSwap(void) 22 { 23 extern long long ll0, ll1; 24 SWAP(ll0, ll1); 25 } $ rx-elf-gcc -O2 -S hoge.c -o - .file "hoge.c" .section P,"ax" .global _charSwap .type _charSwap, @function _charSwap: mov.L #_c1, r4 mov.L #_c0, r5 mov.B [r4], r3 mov.B [r5], r2 xor r3, r2 xor r2, r3 xor r3, r2 mov.B r3, [r4] mov.B r2, [r5] rts .size _charSwap, .-_charSwap .global _shortSwap .type _shortSwap, @function _shortSwap: mov.L #_s1, r4 mov.L #_s0, r5 mov.W [r4], r3 mov.W [r5], r2 xor r3, r2 xor r2, r3 xor r3, r2 mov.W r3, [r4] mov.W r2, [r5] rts .size _shortSwap, .-_shortSwap .global _longSwap .type _longSwap, @function _longSwap: mov.L #_l1, r4 mov.L #_l0, r5 mov.L [r4], r3 mov.L [r5], r2 xor r3, r2 xor r2, r3 xor r3, r2 mov.L r3, [r4] mov.L r2, [r5] rts .size _longSwap, .-_longSwap .global _longLongSwap .type _longLongSwap, @function _longLongSwap: mov.L #_ll1, r4 mov.L #_ll0, r5 mov.L [r4], r14 mov.L 4[r4], r1 mov.L [r5], r2 mov.L 4[r5], r3 xor r14, r2 xor r1, r3 xor r2, r14 xor r3, r1 xor r14, r2 xor r1, r3 mov.L r14, [r4] mov.L r1, 4[r4] mov.L r2, [r5] mov.L r3, 4[r5] rts .size _longLongSwap, .-_longLongSwap .ident "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX" $ cat -n piyo.c 1 #define SWAP(a, b) \ 2 do { \ 3 typeof(a) _temporaryVariableForSwapping_ = (a); \ 4 (a) = (b); \ 5 (b) = _temporaryVariableForSwapping_; \ 6 } while (0) 7 8 void charSwap(void) 9 { 10 extern char c0, c1; 11 SWAP(c0, c1); 12 } 13 14 void shortSwap(void) 15 { 16 extern short s0, s1; 17 SWAP(s0, s1); 18 } 19 20 void longSwap(void) 21 { 22 extern long l0, l1; 23 SWAP(l0, l1); 24 } 25 26 void longLongSwap(void) 27 { 28 extern long long ll0, ll1; 29 SWAP(ll0, ll1); 30 } $ rx-elf-gcc -O2 -S piyo.c -o - .file "piyo.c" .section P,"ax" .global _charSwap .type _charSwap, @function _charSwap: mov.L #_c0, r4 mov.B [r4], r3 mov.L #_c1, r5 mov.B [r5], [r4] mov.B r3, [r5] rts .size _charSwap, .-_charSwap .global _shortSwap .type _shortSwap, @function _shortSwap: mov.L #_s0, r4 mov.W [r4], r3 mov.L #_s1, r5 mov.W [r5], [r4] mov.W r3, [r5] rts .size _shortSwap, .-_shortSwap .global _longSwap .type _longSwap, @function _longSwap: mov.L #_l0, r4 mov.L [r4], r3 mov.L #_l1, r5 mov.L [r5], [r4] mov.L r3, [r5] rts .size _longSwap, .-_longSwap .global _longLongSwap .type _longLongSwap, @function _longLongSwap: mov.L #_ll0, r4 mov.L [r4], r2 mov.L 4[r4], r3 mov.L #_ll1, r5 mov.L [r5], [r4] mov.L 4[r5], 4[r4] mov.L r2, [r5] mov.L r3, 4[r5] rts .size _longLongSwap, .-_longLongSwap .ident "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX" $
> 逆に-fltoがないとinline宣言してもインライン展開されないこともあったり、 関数宣言時に __attribute__((always_inline)) を指定しすると -flto に関係なくインライン展開が強制されると思いますが上手く行かないことがあるでしょうか? あるいは、インラインアセンブラを関数風のマクロで使用するというのも手だと思います。
ヘッダファイルに 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 に記述する話をしています。