Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page

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(というかGCC)のインラインアセンブラは難しいですね。以下のドキュメントを読みながら書いているのですが、(当たり前ですが)書き方を間違えると期待したコードが生成されませんね、、、(悲しいことに、まだ私は何が間違っていて何が正しい書き方なのかを理解出来るレベルに到達していない、、、)

    6.45.2 Extended Asm - Assembler Instructions with C Expression Operands
    gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

    今までのコード ⇒ OK

    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
    */
    }

    試しに書き換えてみた ⇒ NG

    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 */
            "MOV.L [%[R1]], %[R14]\n\t"
            "XCHG [%[R2]].L, %[R14]\n\t"
            "MOV.L %[R14], [%[R1]]"
            : /* OutputOperands */
                [R14] "=r" (temp)
            : /* InputOperands */
                [R1] "r" (data1),
                [R2] "r" (data2)

        );
        /* *data1 = temp; */
        return;
    /* GNURX 2018q1
      92 0010 EC 12                         MOV.L [r1], r2 ← r2を壊してしまった
      93 0012 06 A0 10 22                   XCHG [r2].L, r2
      94 0016 E3 12                         MOV.L r2, [r1]
      97 0018 02                            rts
    */
    }

    更に書き換えてみた ⇒ OK

    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;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MOV.L %[mR1], %[R14]\n\t"
            "XCHG %[mR2].L, %[R14]\n\t"
            "MOV.L %[R14], %[mR1]"
            : /* OutputOperands */
                [R14] "=r" (temp),
                [mR1] "+m" (*data1),
                [mR2] "+m" (*data2)
        );
        return;
    /* GNURX 2018q1
      92 0010 EC 15                         MOV.L [r1], r5
      93 0012 06 A0 10 25                   XCHG [r2].L, r5
      94 0016 E3 15                         MOV.L r5, [r1]
      97 0018 02                            rts
    */
    }

    ちなみに、まだ試行錯誤中ですが、CC-RXで積和演算を行うrmpab()関数は積和演算命令のレジスタの使い方が特徴的だったせいで苦し紛れにGNURXで以下のように記述してみたのですが、コンパイラの最適化処理の足枷になってしまうのでしょうが、他の関数でも同様に変数に割り当てるレジスタを強制的に指定しておいてから他のコンパイラでインラインアセンブラを使う時と同様の感覚で記述する(たぶん記述出来るのではないかと思う)、というやり方にも心惹かれます。(でも、今回のCCRXmachine2.hではやらないつもりですが、、、)

    (補
    GNURXで%r0のようなレジスタ表記も出来るのですね。

    GNURX Migration Guide : Inline_Assembly
    gcc-renesas.com/migration-guides/rx/index.html#Inline_Assembly

    以下のコードは以下のドキュメントを読みながら書いていました。

    6.45.5.2 Specifying Registers for Local Variables
    gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html
    )

    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
    */
    }

    積和演算命令のレジスタの使い方は以下のようにストリング操作命令同様(というかそれ以上)に特徴的ですね。

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


    なお、GNURX対応のCCRXmachin.cのrmpab()関数は以下のように積和演算命令は使わずに記述されていました。

    long long rmpab(long long init, unsigned long count, signed char *addr1, signed char *addr2)
    {
        long long result = init;
        unsigned long index;
        for(index = 0; index < count; index++)
        {
            result += addr1[index] * addr2[index];
        }
        return result;
    }

     

  • GNURX の __builtin_rx_xchg() を確認してみましたが

     $ cat -n xchgTest.c
         1  extern int a, b;
         2
         3  void hoge(void)
         4  {
         5      __builtin_rx_xchg(&a, &b);
         6  }
    
    $ rx-elf-gcc -v
    Using built-in specs.
    COLLECT_GCC=C:\Renesas\e2studio\GCC for Renesas RX 4.8.4.201801-GNURX-ELF\rx-elf\rx-elf\bin\rx-elf-gcc.exe
    COLLECT_LTO_WRAPPER=c:/renesas/e2studio/gcc\ for\ renesas\ rx\ 4.8.4.201801-gnurx-elf/rx-elf/rx-elf/bin/../libexec/gcc/rx-elf/4.8.4.201801-GNURX/lto-wrapper.exe
    Target: rx-elf
    Configured with: /builder/AutomatedBuilds/rx/builds/2018q1_RX_RC3/rx/source/gcc/configure --target=rx-elf --host=i586-mingw32msvc --enable-languages=c,c++ --disable-shared --with-newlib --enable-lto --enable-libssp --enable-plugins --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC_Build_20180316 --prefix=/builder/AutomatedBuilds/rx/builds/2018q1_RX_RC3/rx/rx_win
    Thread model: single
    gcc version 4.8.4.201801-GNURX (GCC_Build_20180316)
    
    $ rx-elf-gcc -O2 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            mov.L   #_a, r2
            mov.L   [r2], r3
            mov.L   #_b, r5
            mov.L   [r5], r4
            mov.L   r3, [r2]
            xchg    r4, r3
            mov.L   r4, [r5]
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $   
    

    ちょっと排他制御には使えない感じですね。

  • In reply to fujita nozomu:

    つーか、ただの交換も機能しない罠。
  • こんにちは。NoMaYです。

    私の前の投稿のxchg()関数のインラインアセンブラ記述の件は、何か腑に落ちない、という感じがしていたのですが、今朝目が覚めて暫くして、GCCの気持ちとして、ひょっとして以下のようなことなのかな?というのが頭に思い浮かびました。

    ● インラインアセンブラ記述部のInputOperandとしてポインタの値だけというのは変だよね。少なくとも以下の何れか1つは一緒に指定されていないと変だよね。
    (1) OutputOperandにポインタの値を加工した値の出力
    (2) InputOperandにポインタの値(もしくは加工した値)によるメモリのリード
    (3) OutputOperandにポインタの値(もしくは加工した値)によるメモリのライト(もしくはリードモデファイライト)
    ●この何れも指定されていないのであれば、ポインタの値は実質使われていない、ということだから壊しても構わないよね。

    そこで、以下のように記述してみたところ、意図したコードが生成されました。

    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;
        __asm__ volatile
        (
            /* AssemblerTemplate */
            "MOV.L [%[R1]], %[R14]\n\t"
            "XCHG [%[R2]].L, %[R14]\n\t"
            "MOV.L %[R14], [%[R1]]"
            : /* OutputOperands */
                [R14] "=r" (temp),
                      "+m" (*data1),
                      "+m" (*data2)
            : /* InputOperands */
                [R1] "r" (data1),
                [R2] "r" (data2)

        );
        return;
    /* GNURX 2018q1
      92 0010 EC 15                         MOV.L [r1], r5
      93 0012 06 A0 10 25                   XCHG [r2].L, r5
      94 0016 E3 15                         MOV.L r5, [r1]
      97 0018 02                            rts
    */
    }

     

  • In reply to fujita nozomu:

    こんにちは。NoMaYです。

    fujita nozomu
    つーか、ただの交換も機能しない罠。

    GNURXの__builtin_rx_xchg()関数のソースをGNURXのGCCのソースの中から探してみると、以下の通りでした。何か場合分けもされているようです。[追記] 今回のはelse節の方だと思うのですが、ひょっとして、後続の最適化処理で命令の順番が入れ替わってしまったのでは? もしそうなら、別の部分(命令定義部?)にヤバイ不具合があるのではないかという予感がします、、、[ここまで追記]

    rx_gcc4.8.4_2018q1\gcc\gcc\config\rx\rx.c

    static rtx
    rx_expand_builtin_xchg (tree exp)
    {
        rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
        rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));

        /* if arg2 is a reg than we can safely use the form xchg [Rs].memex, Rd, othewise only xchg Rs, Rd */
        if(REG_P(arg2))
        {
            rtx mem1 = gen_rtx_MEM (SImode, arg1);
            rtx mem2 = gen_rtx_MEM (SImode, arg2);

            rtx mem1toreg = copy_to_reg(mem1);

            MEM_VOLATILE_P (mem1) = 1;
            MEM_VOLATILE_P (mem2) = 1;

            emit_insn (gen_exchangesi (mem1toreg, mem2));
            emit_move_insn(mem1, mem1toreg);
        }
        else
        {
            rtx mem1 = gen_rtx_MEM (SImode, arg1);
            rtx mem2 = gen_rtx_MEM (SImode, arg2);

            rtx mem1toreg = copy_to_reg(mem1);
            rtx mem2toreg = copy_to_reg(mem2);

            MEM_VOLATILE_P (mem1) = 1;
            MEM_VOLATILE_P (mem2) = 1;

            emit_insn (gen_exchangesi (mem1toreg, mem2toreg));
            emit_move_insn(mem1, mem1toreg);
            emit_move_insn(mem2, mem2toreg);
        }

        return NULL_RTX;
    }

     

  • In reply to NoMaY:

    > ひょっとして、後続の最適化処理で命令の順番が入れ替わってしまったのでは?

    最適化レベル 0 や 1 でコンパイルすると効率は悪いものゝ交換自体には問題がないっぽいコードを吐くのでそれっぽい感じですね。

    $ rx-elf-gcc -O0 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            push.l  r6
            mov.L   r0, r6
            mov.L   #_a, r5
            mov.L   [r5], r4
            mov.L   #_b, r5
            mov.L   [r5], r5
            xchg    r5, r4
            mov.L   #_a, r3
            mov.L   r4, [r3]
            mov.L   #_b, r4
            mov.L   r5, [r4]
            rtsd    #4, r6-r6
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $ rx-elf-gcc -O1 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            mov.L   #_a, r3
            mov.L   [r3], r2
            mov.L   #_b, r5
            mov.L   [r5], r4
            xchg    r4, r2
            mov.L   r2, [r3]
            mov.L   r4, [r5]
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $
    
  • In reply to fujita nozomu:

    こんにちは。NoMaYです。

    fujita nozomu
    ちょっと排他制御には使えない感じですね。

    幾つか前の私の投稿で引用したGNURXのGCCの__builtin_rx_xchg()関数のソースですが、if節の方が気になりましたので、CC-RXの場合のRTOS対応版FITのBSPモジュールとCMT_RXモジュールから以下のようにコードを抜き出してコンパイル(-O2)してみると、__builtin_rx_xchg()関数でセマフォのロックに使用出来る命令列が生成されていました。(とはいえ、複雑難解な最適化処理との兼ね合いでどちらに転ぶか分からない不安があって悩ましいですが。)

    以下のソースの赤字箇所で__builtin_rx_xchg()関数を使用してみた

    #define bool _Bool
    #define false 0
    #define true 1

    typedef signed char int8_t;
    typedef unsigned char uint8_t;
    typedef signed short int16_t;
    typedef unsigned short uint16_t;
    typedef signed long int32_t;
    typedef unsigned long uint32_t;
    typedef signed long long int64_t;
    typedef unsigned long long uint64_t;
    typedef unsigned long size_t;

    /* By default modules will use global locks found in mcu_locks.c. If the user is using a RTOS and would rather use its
       locking mechanisms then they can change this macro.
       NOTE: If '1' is chosen for this macro then the user must also change the next macro 'BSP_CFG_USER_LOCKING_TYPE'.
       0 = Use default locking (non-RTOS)
       1 = Use user defined locking mechanism.
    */
    #define BSP_CFG_USER_LOCKING_ENABLED    (0)

    /* If the user decides to use their own locking mechanism with FIT modules then they will need to redefine the typedef
       that is used for the locks. If the user is using a RTOS then they would likely redefine the typedef to be
       a semaphore/mutex type of their RTOS. Use the macro below to set the type that will be used for the locks.
       NOTE: If BSP_CFG_USER_LOCKING_ENABLED == 0 then this typedef is ignored.
       NOTE: Do not surround the type with parentheses '(' ')'.
    */
    #define BSP_CFG_USER_LOCKING_TYPE       bsp_lock_t

    typedef enum
    {
        BSP_LOCK_BSC = 0,
        BSP_LOCK_CAC,
        BSP_LOCK_CAN0,
        BSP_LOCK_CAN1,
        BSP_LOCK_CMT,
        BSP_LOCK_CMT0,
        BSP_LOCK_CMT1,
        BSP_LOCK_CMT2,
        BSP_LOCK_CMT3,
        /* 略 */
        BSP_LOCK_GLCDC,
        BSP_LOCK_DRW2D,
        BSP_NUM_LOCKS //This entry is not a valid lock. It is used for sizing g_bsp_Locks[] array below. Do not touch!
    } mcu_lock_t;

    typedef struct
    {
        /* The actual lock. int32_t is used because this is what the xchg() instruction takes as parameters. */
        int32_t     lock;
        /* Could add a ID for locking and unlocking. In this could protect against any function being able to unlock. */
    } bsp_lock_t;

    BSP_CFG_USER_LOCKING_TYPE g_bsp_Locks[BSP_NUM_LOCKS];    

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {
    #if BSP_CFG_USER_LOCKING_ENABLED == 0
        bool ret = false;

        /* Variable used in trying to acquire lock. Using the xchg instruction makes this atomic */
        int32_t is_locked = true;
        
        /* This example uses the RX MCU's atomic xchg() instruction. plock->lock is the lock we are trying to reserve.
           The way this works is that 'is_locked' gets the value of the plock->lock and plock->lock gets the value of
           'is_locked' which we just set to 'true'. Basically this is an atomic 'swap' command. If the lock had not yet been
           reserved then its value would be 'false' and after the xchg() instruction finished 'is_locked' would have
           'false'. If it had already been reserved then 'is_locked' would have 'true' after the xchg() instruction. Since
           plock->lock was already 'true' and we just set it back to 'true' everything is ok. To see if we reserved the lock
           we just need to check the value of 'is_locked' after this instruction finishes. */

        /* Try to acquire semaphore to obtain lock */
        __builtin_rx_xchg((int *)&is_locked, (int *)&plock->lock); /* xchg(&is_locked, &plock->lock); */
        
        /* Check to see if semaphore was successfully taken */
        if (is_locked == false)
        {        
            /* Lock obtained, return success. */
            ret = true;
        }
        else
        {
            /* Lock was not obtained, another task already has it. */
        }

        return ret;   
    #else
        /* User is going to handle the locking themselves. */
        return BSP_CFG_USER_LOCKING_SW_LOCK_FUNCTION(plock);
    #endif
    } /* End of function R_BSP_SoftwareLock() */

    bool R_BSP_HardwareLock (mcu_lock_t const hw_index)
    {
    #if BSP_CFG_USER_LOCKING_ENABLED == 0
        /* Pass actual lock to software lock function. */
        return R_BSP_SoftwareLock(&g_bsp_Locks[hw_index]);
    #else
        /* User is going to handle the locking themselves. */
        return BSP_CFG_USER_LOCKING_HW_LOCK_FUNCTION(hw_index);
    #endif
    } /* End of function R_BSP_HardwareLock() */

    #define CMT_RX_NUM_CHANNELS 4

    /*static*/ bool cmt_find_channel (uint32_t * channel)
    {
        bool     channel_found = false;
        uint32_t i;

        /* Look for an available channel. */
        for (i = 0; i < CMT_RX_NUM_CHANNELS; i++)
        {
    #if BSP_CFG_RTOS_USED == 0      // Non-OS
    #elif BSP_CFG_RTOS_USED == 1    // FreeRTOS
            if (i == BSP_CFG_RTOS_SYSTEM_TIMER)
            {
                /* Found CMT channel is being used for RTOS. */
                continue;
            }
    #elif BSP_CFG_RTOS_USED == 2    // SEGGER embOS
    #elif BSP_CFG_RTOS_USED == 3    // Micrium MicroC/OS
    #elif BSP_CFG_RTOS_USED == 4    // Renesas RI600V4 & RI600PX
    #endif
            if (true == R_BSP_HardwareLock((mcu_lock_t)(BSP_LOCK_CMT0 + i)))
            {
                /* Channel found. */
                *channel = i;
                channel_found = true;
                
                break;            
            }
        }        

        return channel_found;
    }

    以下のリストの赤字箇所でセマフォのロックに使用出来る命令列が生成されていた

     1035                                   .global _R_BSP_SoftwareLock
     1037                               _R_BSP_SoftwareLock:
     1041 020c 60 40                        sub #4, r0
     1045 020e F8 06 01                     mov.L   #1, [r0]
     1047 0211 EC 05                        mov.L   [r0], r5
     1048 0213 06 A0 10 15                  xchg    [r1].L, r5
     1049 0217 E3 05                        mov.L   r5, [r0]
     1051 0219 EC 01                        mov.L   [r0], r1
     1054 021b 61 01                        cmp #0, r1
     1055 021d FC DB 10                     sceq.L  r1
     1057 0220 67 01                        rtsd    #4

     1060                                   .global _R_BSP_HardwareLock
     1062                               _R_BSP_HardwareLock:
     1066 0222 60 40                        sub #4, r0
     1072 0224 F8 06 01                     mov.L   #1, [r0]
     1076 0227 6C 21                        shll    #2, r1
     1081 0229 EC 05                        mov.L   [r0], r5
     1085 022b 70 11 00 00 00 00            add #_g_bsp_Locks, r1
     1090 0231 06 A0 10 15                  xchg    [r1].L, r5
     1091 0235 E3 05                        mov.L   r5, [r0]
     1093 0237 EC 01                        mov.L   [r0], r1
     1098 0239 61 01                        cmp #0, r1
     1099 023b FC DB 10                     sceq.L  r1
     1101 023e 67 01                        rtsd    #4

     1104                                   .global _cmt_find_channel
     1106                               _cmt_find_channel:
     1110 0240 60 40                        sub #4, r0
     1113 0242 FB 32 00 00 00 00            mov.L   #_g_bsp_Locks+20, r3
     1115 0248 66 04                        mov.L   #0, r4
     1117                                   .balign 8,3,4
     1123 024a F8 06 01                     mov.L   #1, [r0]
     1125 024d EC 05                        mov.L   [r0], r5
     1126 024f 06 A0 10 35                  xchg    [r3].L, r5
     1127 0253 E3 05                        mov.L   r5, [r0]
     1129 0255 EC 05                        mov.L   [r0], r5
     1130 0257 61 05                        cmp #0, r5
     1131 0259 19                           bne .L67
     1137 025a E3 14                        mov.L   r4, [r1]
     1140 025c 66 11                        mov #1, r1
     1143 025e 5B 11                        movu.B  r1, r1
     1146 0260 67 01                        rtsd    #4
     1150 0262 62 14                        add #1, r4
     1152 0264 62 43                        add #4, r3
     1154 0266 61 44                        cmp #4, r4
     1155 0268 21 E2                        bne .L61
     1157 026a 66 01                        mov #0, r1
     1160 026c 5B 11                        movu.B  r1, r1
     1163 026e 67 01                        rtsd    #4

     

  • In reply to NoMaY:

    こんにちは。NoMaYです。

    すみません。__builtin_rx_xchg()関数の引数を入れ替えたところ、セマフォのロックには使用出来ませんが、メモリオペランドを伴う命令列が生成されていましたので、GNURXのGCCの__builtin_rx_xchg()関数のソースのif節かelse節かは関係無いようですね。すみません。

    __builtin_rx_xchg()関数の引数を入れ替えてみた

    //    __builtin_rx_xchg((int *)&is_locked, (int *)&plock->lock); /* xchg(&is_locked, &plock->lock); */
        __builtin_rx_xchg((int *)&plock->lock, (int *)&is_locked); /* xchg(&is_locked, &plock->lock); */

    セマフォのロックには使用出来ないがメモリオペランドを伴う命令列が生成されていた

       4                                    .global _R_BSP_SoftwareLock
      11 0000 60 40                         sub #4, r0
      15 0002 EF 15                         mov.L   r1, r5
      17 0004 EC 14                         mov.L   [r1], r4
      19 0006 F8 06 01                      mov.L   #1, [r0]
      21 0009 06 A0 10 04                   xchg    [r0].L, r4
      23 000d 66 01                         mov.L   #0, r1
      26 000f E3 54                         mov.L   r4, [r5]
      28 0011 67 01                         rtsd    #4

      31                                    .global _R_BSP_HardwareLock
      33                                _R_BSP_HardwareLock:
      37 0013 60 40                         sub #4, r0
      41 0015 6C 21                         shll    #2, r1
      43 0017 70 15 00 00 00 00             add #_g_bsp_Locks, r1, r5
      48 001d EC 54                         mov.L   [r5], r4
      50 001f F8 06 01                      mov.L   #1, [r0]
      52 0022 06 A0 10 04                   xchg    [r0].L, r4
      56 0026 66 01                         mov.L   #0, r1
      60 0028 E3 54                         mov.L   r4, [r5]
      64 002a 67 01                         rtsd    #4

      67                                    .global _cmt_find_channel
      69                                _cmt_find_channel:
      73 002c 60 40                         sub #4, r0
      76 002e FB 42 00 00 00 00             mov.L   #_g_bsp_Locks+20, r4
      78 0034 66 05                         mov.L   #0, r5
      80                                    .balign 8,3,1
      86 0036 EC 43                         mov.L   [r4], r3
      88 0038 F8 06 01                      mov.L   #1, [r0]
      90 003b 06 A0 10 03                   xchg    [r0].L, r3
      95 003f 62 15                         add #1, r5
     101 0041 FD 22 43                      mov.L   r3, [r4+]
     107 0044 61 45                         cmp #4, r5
     108 0046 21 F0                         bne .L9
     110 0048 66 01                         mov.L   #0, r1
     112 004a 67 01                         rtsd    #4

     

  • In reply to NoMaY:

    こんにちは。NoMaYです。

    度々すみません。私が前々回と前回に試したケースは何れもGNURXのGCCの__builtin_rx_xchg()関数のソースのif節に該当していたようです。スタック上の変数のアドレスを&で取得した場合にもif文のREG_P(arg2)は真になるようです。よくよく考えてみれば、R0レジスタ相対になるのですから、そうなって然るべきものでした。今回、以下の4つの場合を試してみて、そのことを理解しました。

    (1) リエントラント性は脇において試しにis_locked変数をstatic宣言してみたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        static int32_t is_locked = true;

        __builtin_rx_xchg((int *)&is_locked, (int *)&plock->lock);

    (2) 上記(1)で__builtin_rx_xchg()関数の引数を入れ替えたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        static int32_t is_locked = true;

        __builtin_rx_xchg((int *)&plock->lock, (int *)&is_locked);

    (3) 上位関数から渡されたplock変数は脇において試しに&g_bsp_Locks[BSP_LOCK_CMT0 + 0]を書いたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        int32_t is_locked = true;

        __builtin_rx_xchg((int *)&g_bsp_Locks[BSP_LOCK_CMT0 + 0], (int *)&is_locked);

    (4) 上記(3)で__builtin_rx_xchg()関数の引数を入れ替えたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        int32_t is_locked = true;

        __builtin_rx_xchg((int *)&is_locked, (int *)&g_bsp_Locks[BSP_LOCK_CMT0 + 0]);

    結果は以下の通りでした。

    (1) リエントラント性は脇において試しにis_locked変数をstatic宣言してみたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        static int32_t is_locked = true;

        __builtin_rx_xchg((int *)&is_locked, (int *)&plock->lock);


       4                                    .global _R_BSP_SoftwareLock
       6                                _R_BSP_SoftwareLock:
      12 0000 FB 52 00 00 00 00             mov.L   #_is_locked.1408, r5
      13 0006 EC 54                         mov.L   [r5], r4
      14 0008 06 A0 10 14                   xchg    [r1].L, r4
      15 000c E3 54                         mov.L   r4, [r5]
      18 000e EC 51                         mov.L   [r5], r1
      21 0010 61 01                         cmp #0, r1
      22 0012 FC DB 10                      sceq.L  r1
      23 0015 02                            rts

    (2) 上記(1)で__builtin_rx_xchg()関数の引数を入れ替えたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        static int32_t is_locked = true;

        __builtin_rx_xchg((int *)&plock->lock, (int *)&is_locked);


       4                                    .global _R_BSP_SoftwareLock
       6                                _R_BSP_SoftwareLock:
      12 0000 EC 14                         mov.L   [r1], r4
      13 0002 FB 52 00 00 00 00             mov.L   #_is_locked.1408, r5
      14 0008 EC 53                         mov.L   [r5], r3
      15 000a E3 14                         mov.L   r4, [r1]
      16 000c E3 53                         mov.L   r3, [r5]
      19 000e EC 51                         mov.L   [r5], r1
      22 0010 FC 43 34                      xchg    r3, r4
      24 0013 61 01                         cmp #0, r1
      25 0015 FC DB 10                      sceq.L  r1
      26 0018 02                            rts

    (3) 上位関数から渡されたplock変数は脇において試しに&g_bsp_Locks[BSP_LOCK_CMT0 + 0]を書いたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        int32_t is_locked = true;

        __builtin_rx_xchg((int *)&g_bsp_Locks[BSP_LOCK_CMT0 + 0], (int *)&is_locked);


       6                                _R_BSP_SoftwareLock:
      11 0000 60 40                         sub #4, r0
      15 0002 FB 52 00 00 00 00             mov.L   #_g_bsp_Locks+20, r5
      16 0008 EC 54                         mov.L   [r5], r4
      18 000a F8 06 01                      mov.L   #1, [r0]
      20 000d 06 A0 10 04                   xchg    [r0].L, r4
      22 0011 66 01                         mov.L   #0, r1
      25 0013 E3 54                         mov.L   r4, [r5]
      27 0015 67 01                         rtsd    #4

    (4) 上記(3)で__builtin_rx_xchg()関数の引数を入れ替えたもの

    bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
    {

        int32_t is_locked = true;

        __builtin_rx_xchg((int *)&is_locked, (int *)&g_bsp_Locks[BSP_LOCK_CMT0 + 0]);


       4                                    .global _R_BSP_SoftwareLock
       6                                _R_BSP_SoftwareLock:
      11 0000 60 40                         sub #4, r0
      15 0002 F8 06 01                      mov.L   #1, [r0]
      17 0005 EC 03                         mov.L   [r0], r3
      18 0007 FB 52 00 00 00 00             mov.L   #_g_bsp_Locks+20, r5
      19 000d E3 03                         mov.L   r3, [r0]
      20 000f EC 54                         mov.L   [r5], r4
      22 0011 FC 43 43                      xchg    r4, r3
      23 0014 E3 54                         mov.L   r4, [r5]
      26 0016 EC 01                         mov.L   [r0], r1
      28 0018 61 01                         cmp #0, r1
      29 001a FC DB 10                      sceq.L  r1
      31 001d 67 01                         rtsd    #4

     

  • In reply to NoMaY:

    こんにちは。NoMaYです。

    幾つか前の私の投稿でGNURXのGCCの__builtin_rx_xchg()関数のソースについて「複雑難解な最適化処理との兼ね合いでどちらに転ぶか分からない不安があって悩ましい」と書きましたが、1つ例が思い浮かびました。

    今まで上位側で以下のようにしていたら期待したセマフォのロックに使用出来る命令列が生成されていた

    /*static*/ bool cmt_find_channel (uint32_t * channel)
    {
        bool     channel_found = false;
        uint32_t i;
        bool     cmt_locked;

        /* Look for an available channel. */
        for (i = 0; i < CMT_RX_NUM_CHANNELS; i++)
        {
    #if BSP_CFG_RTOS_USED == 0      // Non-OS
    #elif BSP_CFG_RTOS_USED == 1    // FreeRTOS
            if (i == BSP_CFG_RTOS_SYSTEM_TIMER)
            {
                /* Found CMT channel is being used for RTOS. */
                continue;
            }
    #elif BSP_CFG_RTOS_USED == 2    // SEGGER embOS
    #elif BSP_CFG_RTOS_USED == 3    // Micrium MicroC/OS
    #elif BSP_CFG_RTOS_USED == 4    // Renesas RI600V4 & RI600PX
    #endif
            if (true == R_BSP_HardwareLock((mcu_lock_t)(BSP_LOCK_CMT0 + i)))
            {
                /* Channel found. */
                *channel = i;
                channel_found = true;
                
                break;            
            }
        }        

        return channel_found;
    }
     1104                                   .global _cmt_find_channel
     1106                               _cmt_find_channel:
     1110 0240 60 40                        sub #4, r0
     1113 0242 FB 32 00 00 00 00            mov.L   #_g_bsp_Locks+20, r3
     1115 0248 66 04                        mov.L   #0, r4
     1117                                   .balign 8,3,4
     1123 024a F8 06 01                     mov.L   #1, [r0]
     1125 024d EC 05                        mov.L   [r0], r5
     1126 024f 06 A0 10 35                  xchg    [r3].L, r5
     1127 0253 E3 05                        mov.L   r5, [r0]
     1129 0255 EC 05                        mov.L   [r0], r5
     1130 0257 61 05                        cmp #0, r5
     1131 0259 19                           bne .L67
     1137 025a E3 14                        mov.L   r4, [r1]
     1140 025c 66 11                        mov #1, r1
     1143 025e 5B 11                        movu.B  r1, r1
     1146 0260 67 01                        rtsd    #4
     1150 0262 62 14                        add #1, r4
     1152 0264 62 43                        add #4, r3
     1154 0266 61 44                        cmp #4, r4
     1155 0268 21 E2                        bne .L61
     1157 026a 66 01                        mov #0, r1
     1160 026c 5B 11                        movu.B  r1, r1
     1163 026e 67 01                        rtsd    #4

    ところが以下のように書き換えたらそのような命令列が生成されなくなってしまった(ただの交換も機能しない)

    /*static*/ bool cmt_find_channel (uint32_t * channel)
    {
        bool     channel_found = false;
        uint32_t i;
        bool     cmt_locked;

        /* Look for an available channel. */
        for (i = 0; i < CMT_RX_NUM_CHANNELS; i++)
        {
    #if BSP_CFG_RTOS_USED == 0      // Non-OS
    #elif BSP_CFG_RTOS_USED == 1    // FreeRTOS
            if (i == BSP_CFG_RTOS_SYSTEM_TIMER)
            {
                /* Found CMT channel is being used for RTOS. */
                continue;
            }
    #elif BSP_CFG_RTOS_USED == 2    // SEGGER embOS
    #elif BSP_CFG_RTOS_USED == 3    // Micrium MicroC/OS
    #elif BSP_CFG_RTOS_USED == 4    // Renesas RI600V4 & RI600PX
    #endif
            //if (true == R_BSP_HardwareLock((mcu_lock_t)(BSP_LOCK_CMT0 + i)))
            switch (i)
            {
            case 0:
                cmt_locked = R_BSP_HardwareLock((mcu_lock_t)BSP_LOCK_CMT0);
                break;
            case 1:
                cmt_locked = R_BSP_HardwareLock((mcu_lock_t)BSP_LOCK_CMT1);
                break;
            case 2:
                cmt_locked = R_BSP_HardwareLock((mcu_lock_t)BSP_LOCK_CMT2);
                break;
            case 3:
                cmt_locked = R_BSP_HardwareLock((mcu_lock_t)BSP_LOCK_CMT3);
                break;
            default:
                /* never */
                cmt_locked = false;
            }
            if (true == cmt_locked)
            {
                /* Channel found. */
                *channel = i;
                channel_found = true;
                
                break;            
            }
        }        

        return channel_found;
    }
      74                                    .global _cmt_find_channel
      76                                _cmt_find_channel:
      80 0034 6E 67                         pushm   r6-r7
      82 0036 60 40                         sub #4, r0
      86 0038 66 05                         mov.L   #0, r5
      91 003a FB 72 00 00 00 00             mov.L   #_g_bsp_Locks+28, r7
      98 0040 FB F2 00 00 00 00             mov.L   #_g_bsp_Locks+32, r15
     105 0046 FB E2 00 00 00 00             mov.L   #_g_bsp_Locks+24, r14
     112 004c FB 22 00 00 00 00             mov.L   #_g_bsp_Locks+20, r2
     114                                    .balign 8,3,1
     115                                .L13:
     120 0052 61 25                         cmp #2, r5
     121 0054 20 6C                         beq .L7
     123 0056 61 35                         cmp #3, r5
     124 0058 20 51                         beq .L8
     125 005a 61 15                         cmp #1, r5
     126 005c 20 2A                         beq .L9
     131 005e F8 06 01                      mov.L   #1, [r0]
     133 0061 EC 04                         mov.L   [r0], r4
     134 0063 EC 23                         mov.L   [r2], r3
     135 0065 E3 04                         mov.L   r4, [r0]
     136 0067 FC 43 34                      xchg    r3, r4
     138 006a EC 04                         mov.L   [r0], r4
     139 006c 61 04                         cmp #0, r4
     140 006e FC DB 40                      sceq.L  r4
     142 0071 E3 23                         mov.L   r3, [r2]
     144                                    .balign 8,3,1
     145                                .L10:
     150 0073 5B 44                         movu.B  r4, r4
     151 0075 61 04                         cmp #0, r4
     152 0077 21 29                         bne .L17
     154                                    .balign 8,3,1
     155                                .L11:
     157 0079 62 15                         add #1, r5
     159 007b 61 45                         cmp #4, r5
     160 007d 21 D5                         bne .L13
     162 007f CF 41                         mov.B   r4, r1
     165 0081 5B 11                         movu.B  r1, r1
     167 0083 3F 67 03                      rtsd    #12, r6-r7
     169                                .L9:
     174 0086 E3 05                         mov.L   r5, [r0]
     176 0088 EC 04                         mov.L   [r0], r4
     177 008a EC E6                         mov.L   [r14], r6
     178 008c E3 04                         mov.L   r4, [r0]
     179 008e FC 43 64                      xchg    r6, r4
     181 0091 EC 04                         mov.L   [r0], r4
     182 0093 61 04                         cmp #0, r4
     183 0095 FC DB 40                      sceq.L  r4
     185 0098 E3 E6                         mov.L   r6, [r14]
     191 009a 5B 44                         movu.B  r4, r4
     193 009c 61 04                         cmp #0, r4
     195 009e 20 DB                         beq .L11
     197                                    .balign 8,3,1
     198                                .L17:
     200 00a0 E3 15                         mov.L   r5, [r1]
     203 00a2 66 11                         mov #1, r1
     206 00a4 5B 11                         movu.B  r1, r1
     208 00a6 3F 67 03                      rtsd    #12, r6-r7
     210                                .L8:
     215 00a9 F8 06 01                      mov.L   #1, [r0]
     217 00ac EC 03                         mov.L   [r0], r3
     218 00ae EC F6                         mov.L   [r15], r6
     219 00b0 E3 03                         mov.L   r3, [r0]
     220 00b2 E3 F6                         mov.L   r6, [r15]
     222 00b4 EC 04                         mov.L   [r0], r4
     223 00b6 61 04                         cmp #0, r4
     224 00b8 FC DB 40                      sceq.L  r4
     227 00bb FC 43 63                      xchg    r6, r3
     232 00be 2E B5                         bra .L10
     234                                .L7:
     239 00c0 F8 06 01                      mov.L   #1, [r0]
     241 00c3 EC 04                         mov.L   [r0], r4
     242 00c5 EC 76                         mov.L   [r7], r6
     243 00c7 E3 04                         mov.L   r4, [r0]
     244 00c9 FC 43 64                      xchg    r6, r4
     246 00cc EC 04                         mov.L   [r0], r4
     247 00ce 61 04                         cmp #0, r4
     248 00d0 FC DB 40                      sceq.L  r4
     250 00d3 E3 76                         mov.L   r6, [r7]
     256 00d5 2E 9E                         bra .L10

     

  • こんにちは。NoMaYです。

    どなたか、fujitaさんが気付かれた__builtin_rx_xchg(&mem, &mem);の命令列が-O2でコンパイルした時に壊れてしまう件について、GNURXの開発元のRedHat社(でしたよね) or サポートサイトのgcc-renesas.comに報告される人はいらっしゃいますか? これに気付いてしまったら放ったらかす訳にはいかない気がしますので、どなたもいらっしゃらなければ、私の方でgcc-renesas.comに報告しようかと思います。

    効率や仕様は脇へおいて、GNURXのGCCの__builtin_rx_xchg()関数のソースは間違っていなさそうなので、たぶん以下の画面コピーのフォルダのファイルのどこかに不具合があるのではないかと思います。

    rx_gcc4.8.4_2018q1\gcc\gcc\config\rx\


    ちなみに、以下はGNURXのリポジトリでは無くてGCCそのもののリポジトリですが、__builtin_rx_xchg()関数の実装は含まれていませんでした。きっと他にも色々と古いままなのだと思われます、、、

    [gcc.git] / gcc / config / rx /
    gcc.gnu.org/git/?p=gcc.git;a=tree;f=gcc/config/rx;hb=refs/heads/master

    constraints.md
    predicates.md
    rx-modes.def
    rx-opts.h
    rx-protos.h
    rx.c
    rx.h
    rx.md
    rx.opt
    t-rx

    開発費(勘で言って500万円/年ぐらいとか???)を出しているのはルネサスさん(ですよね)でしょうから、ルネサスさんから報告が行くのが一番確実に伝わるとは思われますが、、、

    [余談]

    GNURXのGCCのソースにGCCそのもののソースに無い以下のソースが含まれていることに気付いたのですが、これは何だろう、、、調べてみようかな、、、

    rx_gcc4.8.4_2018q1\gcc\gcc\config\rx\rx-pragma.c

    #include "config.h"
    #include "system.h"
    #include "coretypes.h"
    #include "tm.h"
    #include "tree.h"
    #include "c-family/c-pragma.h"
    #include "c-family/c-common.h"
    #include "diagnostic-core.h"
    #include "cpplib.h"
    #include "hard-reg-set.h"
    #include "output.h"
    #include "rx-protos.h"
    #include "function.h"
    #define MAX_RECOG_OPERANDS 10
    #include "reload.h"
    #include "target.h"

    /* Implements the "pragma ADDRESS" pragma.  This pragma takes a
     *    variable name and an address, and arranges for that variable to be
     *       "at" that address.  The variable is also made volatile.  */
    static void
    rx_pragma_address (cpp_reader * reader ATTRIBUTE_UNUSED)
    {
      /* on off */
      tree var, addr;
      enum cpp_ttype type;

      type = pragma_lex (&var);
      if (type == CPP_NAME)
        {
          type = pragma_lex (&addr);
          if (type == CPP_NUMBER)
            {
              if (var != error_mark_node)
                {
                  unsigned uaddr = tree_low_cst (addr, 1);
                  rx_note_pragma_address (IDENTIFIER_POINTER (var), uaddr);
                }

              type = pragma_lex (&var);
              if (type != CPP_EOF)
                {
                  error ("junk at end of #pragma ADDRESS");
                }
              return;
            }
        }
      error ("malformed #pragma ADDRESS variable address");
    }

    void
    rx_register_pragmas (void)
    {
      c_register_pragma (NULL, "ADDRESS", rx_pragma_address);
      c_register_pragma (NULL, "address", rx_pragma_address);
    }

     

  • In reply to NoMaY:

    NoMaYさん、fujitaさん

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

    ご協力感謝いたします。
    ご提示いただいたコードをルネサスからGCCの開発側に連絡、
    GCCの開発側から何らかのフィードバックを得たところまで確認しました。
    ご推察の通りの開発費の流れですので、NoMaYさんの手を煩わせるわけにはいかないと私は思っております。
    従いましてもう少し何らかの見解を出せるまでお時間いただければ、と思います。

    以上です

Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page