MC6800のプログラミングテクニック(30) xorshift32の実装

BASICMASTER

下記のサイトに、同一プログラムを各種CPUで書いた比較記事が掲載されている。MC6800だとどうなるか、PRNG(擬似乱数)プログラムを書いてみた。


お題:擬似乱数プログラム

周期が 2^32-1 である擬似乱数を作成するコードである。Cで書くと下記の通り。0は生成されないので要注意。


uint16_t rnd_xorshift_32() {
    static uint16_t x=1,y=1;
    uint16_t t=(x^(x<<5)); 
    x=y; 
    return y=(y^(y>>1))^(t^(t>>3));
}


素直にMC6800で書いてみる

chibiccから関数として呼べる形で書いてみた。変数がxx,yy,ttなのは、x がレジスタ名と衝突して使えなかったから(as6800の制限)。

メモリを節約するために x/y/zにはインデックスレジスタ経由でアクセスしているが、ダイレクトページが使えるなら その方が早い。

40命令、62バイトである。データ部分が別に6バイト。


        .data
xyt:    .word   1
        .word   1
        .word   0
xx      .equ    0
yy      .equ    2
tt      .equ    4
        .code
        .export _asm_xorshift_32
_asm_xorshift_32:
        ldx     #xyt
;       t = x^(x<<5);
        ldab    xx+1,x
        ldaa    xx,x
        aslb
        rola
        aslb
        rola
        aslb
        rola
        aslb
        rola
        aslb
        rola
        eorb    xx+1,x
        eora    xx,x
;       t = t^(t>>3);
        stab    tt+1,x
        staa    tt,x
        lsra
        rorb
        lsra
        rorb
        lsra
        rorb
        eorb    tt+1,x
        eora    tt,x
        stab    tt+1,x
        staa    tt,x
;       x = y
        ldab    yy+1,x
        ldaa    yy,x
        stab    xx+1,x
        staa    xx,x
;       tmp = y^(y>>1);
        lsra
        rorb
        eorb    yy+1,x
        eora    yy,x
;       y = tmp ^ t;
        eorb    tt+1,x
        eora    tt,x
        stab    yy+1,x
        staa    yy,x
        rts


6502版と比べてみる

6502版では、x<<5 と t>>3 はループで書かれている。6502でアキュムレータは1つしかなく、残り8bitはメモリシフトを使っている。

メモリシフトに絶対アドレッシングを使うので、1bitシフトするのに4バイト使う(lsr / ror _x)。

ループのために(ldx #$03 … dex / bne _lp2)の5バイトを使っても元が取れる。

MC6800では16bit数値のシフトは lsra / rorb の2バイトで足りるし、ループに6バイト使う。元が取れないので、素直にシフト命令を並べている。


もうちょっとだけ短くする

x<<5 の部分は ほんの少しだけ短くできる。左に5bitシフトする代わりに、右に3bitシフトすれば良い。

一見すると最後に入れ替えが必要に思えるが、最初にAccABに読み込むときに逆に読んでおけば良い。

右からキャリーに溢れた1bitを回収するのと 下位ビットを0クリアする処理が必要。2命令・1バイトだけ小さくなる(38命令、61バイト)。


        ldab    xx,x
        ldaa    xx+1,x
        lsrb
        rora
        rorb
        rora
        rorb
        rora
        rorb
        andb    #$e0



もっと小さくできるだろうか?

コメント

タイトルとURLをコピーしました