chibicc compiler を6800向けに改造する (14) アドレッシングと最適化(2)

BASICMASTER, 昔のパソコン

chibicc compiler を6800向けに改造する (5) アドレッシングと最適化 の続き。

MC6800で良いコードを生成するには、Acc A,B と IX,SP の使い分けが必要だと書いたが、もっと場合分けが必要なことに気がついた。

1つは2バイト操作をIXで処理する場合、もう1つはlong/floatを処理する内部ルーチンへのパラメータ渡しである。

2バイト処理はIXをなるべく使いたい

グローバル変数 int x, ローカル変数 int yがあるときに、 x=y+1 のような処理はどのようにすると良いか。

2025/11/09 現在の chibicc-6800 では、このようなコードが生成される。


	ldx @bp
        ldab 1,x
        ldaa 0,x
        addb #<1
        adca #>1
        stab _x+1
        staa _x

IXを使えば簡潔で速くなる。これを処理するには右辺がIXだけで生成でき、左辺の処理にIXが不要であることを知らないといけない。


	ldx @bp
	ldx 0,x
	inx
	stx _x


if式の中もIXを使いたい

if (y!=1) や if(y-1) のような式も同様である。どちらもy!=1のときに、本体を実行する。

前者は現在の chibicc-6800 でも最適化できていて、このようなコードになる。


	ldx @bp
        ldx 0,x
        dex
        jeq L_else_1

後者はこうなってしまう。同じコードで良いのに。


        ldx @bp
        ldab 1,x
        ldaa 0,x
        subb #<1
        sbca #>1
        aba
        adca #0
        jeq L_else_1


内部ルーチンへのパラメータ渡し

longやfloatを扱う場合、特定の場所にある値をワーク領域(@long)に読み込む処理が必要である。

領域がglobalな場所であったり、IXレジスタで示される領域(オフセットが0)であれば、IXレジスタに先頭のアドレスを入れてサブルーチンコールすれば良い。

問題は、ローカル変数のときで、大抵の場合はオフセットは0ではないので、パラメータとしてIXとオフセットの両方を渡す必要がある。
しかも、サブルーチン側では両方の加算処理(6命令)を行なってから処理をする必要がある。無駄すぎる。

アドレス計算の結果はAccABに入るので、これを直接渡した方がまだマシである。AccABからIXへ転送が必要だが、3命令で済む。

もっと言えば、ローカル変数であれば単にオフセットを渡して、サブルーチン側で@bpと加算すれば、呼び出し側のサイズが小さくなる。そうすべきである。

結局のところ、単にAccAB、IXを使うかどうかだけではなく、もっと細かい場合わけが必要である。

  • 定数0
  • 2バイト定数(IXが使える)、グローバル変数のアドレスも含む
  • IXだけで直接指定できる(off=0)
  • IXだけで指定できる(off=1〜255の固定値)
  • IXと可変オフセット(必要?)
  • IXだけで計算できる(定数との同値比較、+1,-1)
  • @bpとオフセットで指定できる(オフセット固定)
  • @boとオフセットで指定できる(オフセット可変)
  • AccABだけで計算できる
  • AccABとIXの両方が必要(ローカル配列のアドレス計算など)

これ場合わけするのはさすがに難しいな……どうしたものか