GNURL78やLLVM-RL78でのover 64KB ROMのchecksumを計算するcodeを考えてみるスレッド

こんにちは。NoMaYです。

最近、以下のスレッドに関わったのですが、暫く時間が経った後で思い返してみると、farキーワードの起源の8086のマイクロソフトコンパイラでの仕様とか、CC-RL及びそれに準ずるLLVM-RL78での仕様とか、それらを鑑みると、投稿した以下のコードでの64KB境界を跨いだfarポインタのインクリメントやポインタ比較は素朴に期待したようには動かないのが本来の仕様である可能性が高い筈、と思い直しました。そこで、コードを考え直してみることにしました。

続く。

C言語からのアセンブラ関数呼び出しについて
community-ja.renesas.com/cafe_rene/forums-groups/beginners/f/002-2095199602/9532/c

上のスレッドに投稿した、素朴に期待したようには動かないのが本来の仕様である可能性が高い、そんなコード(現状はGNURL78でOKだが):

#include <stdint.h>
const uint16_t __far psum_rom = 0x1234; /* This variable is placed at the end of the ROM by linker script. */
uint16_t _RomSum(void);
uint16_t __attribute__((noinline, optimize("no-isolate-erroneous-paths-dereference"))) _RomSum(void)
{
    // FIXME: In case of using the immediate value in stead of `&psum_rom`, if other than -O0 is used,
    // the generated code has no ES register handling. It seems to be a bug of GNURL78 (ex. 4.9.2.202201).

    const uint16_t __far *prom, *sum_s, *sum_e;
    uint16_t sum = 0;

    sum_s = 0;
    sum_e = &psum_rom; // (const uint16_t __far *)0x017DFEUL; --> No ES register handling.
    for( prom = sum_s; prom < sum_e; prom++ )
    {
        sum += *prom;
    }
    return sum;
}

 

Parents
  • こんにちは。NoMaYです。

    今になって思い至ったのですが、2つ前に書いた以下のことを鑑みると、GNURL78の__farが、桁上がりや桁借りをやらないことによる効率向上よりも、もともとGCCに無かった__farを追加するにあたり開発期間/開発費用を節約する為にいっそのことポインタ演算に関してuint32_tと同じ扱いにしたことによる結果として桁上がりや桁借りもやるようになっていた、という気もしてきました。

    > 他方、その頃、私はGCCを使っていなかったので、GCCではどういう仕様になっていたのか、というか8086向けGCCはもともと存在しなかったような(曖昧な記憶では80386向けDOSエクステンダ上で動作するDJGPP(DJ Delorie氏が開発)というGCC以前にはx86向けのものは存在しなかったような)気もしますが、私はそのあたりのことが分かりません。

    > そして、GCCのドキュメントには、現在のx86向けのGCCに関してはnear/far/hugeというキーワードは存在しないようでした。

    そこで、以下のソースをコンパイルしてリストファイルを眺めてみたところ、これは確かにそういうことだよなぁ、という結論に至りました。

    ということで、このスレッドは私の勘違いでした、ということで終わりにします。すみません。



    ソース:

    uint16_t __far *ptr;
    void test(void)
    {
        ptr++;
    }

     
    -O0でのリストファイル:

     0000 AF 00 00                      movw ax, !_ptr
     0003 BD F0                         movw r8, ax
     0005 AF 00 00                      movw ax, !_ptr+2
     0008 BD F2                         movw r10, ax
     000a AD F0                         movw ax, r8
     000c 04 02 00                      addw ax, #2
     000f BD F0                         movw r8, ax
     0011 AD F2                         movw ax, r10
     0013 61 D8                         sknc
     0015 A1                            incw ax
     0016 BD F2                         movw r10,ax
     0018 AD F0                         movw ax, r8
     001a BF 00 00                      movw !_ptr, ax
     001d AD F2                         movw ax, r10
     001f BF 00 00                      movw !_ptr+2, ax
     0022 D7                            ret

     
    -O1,-O2,-O3,-Os,-Ogでのリストファイル:

     0000 AF 00 00                      movw ax, !_ptr
     0003 04 02 00                      addw ax, #2
     0006 BF 00 00                      movw !_ptr, ax
     0009 AF 00 00                      movw ax, !_ptr+2
     000c 61 D8                         sknc
     000e A1                            incw ax
     000f BF 00 00                      movw !_ptr+2,ax
     0012 D7                            ret

     

Reply
  • こんにちは。NoMaYです。

    今になって思い至ったのですが、2つ前に書いた以下のことを鑑みると、GNURL78の__farが、桁上がりや桁借りをやらないことによる効率向上よりも、もともとGCCに無かった__farを追加するにあたり開発期間/開発費用を節約する為にいっそのことポインタ演算に関してuint32_tと同じ扱いにしたことによる結果として桁上がりや桁借りもやるようになっていた、という気もしてきました。

    > 他方、その頃、私はGCCを使っていなかったので、GCCではどういう仕様になっていたのか、というか8086向けGCCはもともと存在しなかったような(曖昧な記憶では80386向けDOSエクステンダ上で動作するDJGPP(DJ Delorie氏が開発)というGCC以前にはx86向けのものは存在しなかったような)気もしますが、私はそのあたりのことが分かりません。

    > そして、GCCのドキュメントには、現在のx86向けのGCCに関してはnear/far/hugeというキーワードは存在しないようでした。

    そこで、以下のソースをコンパイルしてリストファイルを眺めてみたところ、これは確かにそういうことだよなぁ、という結論に至りました。

    ということで、このスレッドは私の勘違いでした、ということで終わりにします。すみません。



    ソース:

    uint16_t __far *ptr;
    void test(void)
    {
        ptr++;
    }

     
    -O0でのリストファイル:

     0000 AF 00 00                      movw ax, !_ptr
     0003 BD F0                         movw r8, ax
     0005 AF 00 00                      movw ax, !_ptr+2
     0008 BD F2                         movw r10, ax
     000a AD F0                         movw ax, r8
     000c 04 02 00                      addw ax, #2
     000f BD F0                         movw r8, ax
     0011 AD F2                         movw ax, r10
     0013 61 D8                         sknc
     0015 A1                            incw ax
     0016 BD F2                         movw r10,ax
     0018 AD F0                         movw ax, r8
     001a BF 00 00                      movw !_ptr, ax
     001d AD F2                         movw ax, r10
     001f BF 00 00                      movw !_ptr+2, ax
     0022 D7                            ret

     
    -O1,-O2,-O3,-Os,-Ogでのリストファイル:

     0000 AF 00 00                      movw ax, !_ptr
     0003 04 02 00                      addw ax, #2
     0006 BF 00 00                      movw !_ptr, ax
     0009 AF 00 00                      movw ax, !_ptr+2
     000c 61 D8                         sknc
     000e A1                            incw ax
     000f BF 00 00                      movw !_ptr+2,ax
     0012 D7                            ret

     

Children
No Data