こんにちは。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
こんにちは。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
#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
;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
以下のようなマクロにするしかないかなと考えています。 #define int_exception( num ) _int_exception_cpp_step2( num ) #define _int_exception_cpp_step2( num ) do{ __asm __volatile ("INT #" #num); } while(0)
#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_STACKvoid 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 */