2021年5月19日水曜日

6800用のGAMEインタプリタとコンパイラを6809に移植

 6800用のGAMEインタプリタだけでなく、コンパイラも移植してみました


動機

発注してあるプリント基板が未だに届かないので最近はソフトばかりいじっていますが、前回は6800用のTL1コンパイラを6809に移植することができましたので、その勢いで、今度はGAMEインタプリタとコンパイラの移植に挑戦してみました。

GAMEインタプリタの6809への移植は、既に1981年に藤原誠さんによる「GAME09インタプリタ」や、1984年の萩平哲さんによる「GAME-FMインタプリタ・コンパイラ」があり、いずれも実行速度や機能面で非常に優れたもので、私もインストールして使わせてもらっていました。しかし、いずれもソースは公開されておらずバイナリコードだけです。

移植するコンパイラは

今回移植しようと考えたものは、2019年5月8日のブログ「6802基板でGAME68コンパイラを走らせる」で紹介した「GAME68コンパイラ」で、松島義明さんがGAME自身で記述されたものです。

GAME自身で記述されているということは、コンパイラとしての論理構造は6800でも6809でも変わらず、コード生成の部分だけが異なっているということになります。

そして、生成されるコードは6800のバイナリであるわけですが、前回のTL1でも述べましたように、6809と6800のバイナリにはそれほど大きな違いはないので、異なっているものだけを書き換えるだけで済むのではないかと考えました。(安直ですね。)


コンパイラのランタイムルーチンを見ると


まず最初にランタイムルーチンを調べてみました。

GAMEインタプリタ内のルーチンを利用していることもあって、わずか300バイト足らずの小さなものですが、逆アセンブルしてみたところ、6809と異なっている命令はNOPとLDXのみでしたので、簡単に書き換えることができました。

しかし、インタプリタ内のルーチンを使用しているということは、実行時には6809版のインタプリタが必要ということになりますので、コンパイラより先にインタプリタの移植が必要だということになります...


インタプリタの移植が必要だった

ということで、まずインタプリタの移植に取り組むことになりました。

6800用インタプリタもTL1と同様にアセンブラソースが公開されていますので、TL1の時と同じようにスタック命令に注意しながら書き換えることで、それ程苦労せずに動作させることができました。(私の場合はハードもソフトも速さにはそれ程こだわらず、正常に動作すれば良しというスタンスですので、最適化などはほとんど行っていません。)


インタプリタの移植が済んだので

インタプリタの移植が済んで、コンパイラのランタイムルーチンが呼んでいるルーチンのアドレスが確定しましたので、GAME68自身で記述されているコンパイラの関係するアドレスを書き換えたものを作り、簡単なプログラムで生成されたコードを調べてみました。

すると、Xレジスタ関連の命令とPSH,PUL命令を書き換えただけで動くプログラムもあるではありませんか。

この結果に気を良くして、コンパイラのソースを読んでみた限りでは、コンパイラで生成される命令の中で、6800と6809とでコードが異なるものとしてはLDX, STX, INX, TAB, TBA, PSHA, PSHB, PULA, PULBの9種がありましたが、これらはバイト数が異なるものの、置き換えにはそれ程困難はなさそうです。しかし、それらに加えて一部にLDS, STSというスタック関係の命令も使われているようですので、これらについては注意が必要です。

[5月23日追記]訂正:LDS, STS命令は使われていませんでした。


GAME09コンパイラ(らしきもの)を作ってみた

とりあえず、スタック関係の命令はそのままにしておいて(GAMEのどの命令で使われるのかまだ分からないので...)その他の命令だけを置き換えたものを作成してみました。


動作環境の詳細

使用した6809ボードは前回と同じ6809/6802DualCPUボードです。


6809/6802 Dual CPUボード

メモリマップです。


メモリマップ

ソースプログラムの格納領域は、TL1コンパイラの場合と合わせて $3000 からにしています。

オリジナルのランタイムルーチンは $2100~$22BA ですが、その先頭に生成オブジェクトへのジャンプ命令(3バイト)を追加し、JMP $2100で実行できるようにしています。

それぞれのプログラムの読み込みですが、あらかじめMOT形式に変換しておいて、自作モニタの LコマンドやASSIST09の LOADコマンドでロードしています。

そのMOT形式への変換プログラムですが、前回のTL1コンパイラのソースの場合はエディタで行番号を付けずに作成したものを変換しましたが、GAMEのソースの場合は行番号が付いていますので、それをバイナリに変換して新たに格納アドレスを付加するように機能拡張しました。また、付加する行番号や格納するアドレスを指定できるようにもしました。


CvtTxtTl1Src.exe


コンパイルの実行手順

次のような手順でコンパイルを実行します。

1.モニタでGAME9インタプリタをロードする

       L GAME9EX

        拡張機能付きのGAME9が$0100からにロードされる

2.インタプリタを起動する(コールドスタートで)

        G 100

3.モニタに移動する

        >=$F800

4.ソースプログラムをロードする

        L (source file)

        ソースプログラムが $3000 からにロードされる

5.GAME9コンパイラとランタイムルーチンをロードする

        L GAME9CS

        ランタイムルーチンが$2100からに、コンパイラが $4000 からにロードされる

6.GAME9インタプリタに戻る(ホットスタートで)

        G 103

7.コンパイラをアクティブにする

        =$4000 (先頭アドレスのセット)

        ==          (末尾アドレスをサーチ)

8.コンパイルを実行する

        #=1


実行例

実行した例を示します。オリジナルではワークエリアなどいくつかの問い合わせに答えてからコンパイルが始まりますが、ソースプログラムの格納エリアなどを決め打ちしましたので、#=1ですぐにコンパイルが始まります。

実行例

コンパイルの終了後、GAME上で >=$2100 とすると生成されたオブジェクトが実行されます。


終わりに

まだ全ての6800命令を6809命令に書き換えてはいないのですが、いくつかのプログラムをコンパイルして正常に動作することを確認しました。

以前「GAME68コンパイラ」のブログを書いた際に、コンパイラの作者の松島義明さんから掲載の許可をいただいていますので、今回の6809へ書き換えたものも公開しても良いと思います。

今の時代にGAMEやTL1を使おうという奇特な方がおられるとは思えませんが、もしご希望があるようでしたら、書き換えられずにそのままになっているスタック関係の命令の書き換えが終了しましたら公開する予定です。変換プログラム CvtTxtTl1Src.exe についても同様です。

以上、私の単なる思い付きでやってみたことで、実用性はほとんどありませんが、巷間、6800と6809とはバイナリレベルの互換性が無いので云々という評価がありますが、全く異なっているわけではないので、違っている部分にだけ注意を払えばこんなこともできるというサンプルになれば幸いです。(と言っても、今どき、6800はおろか6809のプログラムですら化石時代の遺物みたいなものでしょうが...)


0 件のコメント:

コメントを投稿