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



Parents
  • こんにちは。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;
    }

     

Reply
  • こんにちは。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;
    }

     

Children
No Data