5月5日の「GAME09」で一部紹介した、
ttps://www.zukeran.org/shin/d/2024/06/04/bm-development-environment-8/
「ず」さんのブログを見ていたら、6800用のGAME68関連のアーカイブにGAME言語のソースをアセンブラのソースの形で出すコンパイラが紹介されていたので、ダウンロードして6809用に書換えてみた。
ここに、一応 使い物になる程度の形になったので公開しょうと思う。
GAME-CC0_0531.zip 4shared.comのリンクなので気になる方はご遠慮ください。
先に、着手していたGAME09の方は、インテルHEX形式でのシリアル転送のルーチン部分が目処がたったので、GAME09インタプリタ内に内包させるすり合わせ作業中。
GAME-CC0は、それ以外にasm6809を使っていますのでa09などの他のアセンブラを使用の場合は、適宜makefileの修正を行ってください。
以下はGAME-CCオリジナルからの改変作業過程の作業メモです。何をどうイジったかの参考にでも どうぞ。
makefile
11から17行、gameオブジェクト生成ルール コメントアウト
common.hの構造体宣言をmain.cに移動
print_string_t STRING_FCC[10000];
opt_do_loop_t odl[1000];
opt_for_loop_t ofl[1000];
Node *code[10000];
Token *token;
シリアル端末専用のSBC6809用のため 不要なBM-L2専用の音楽、タイマー、カーソル制御関係の機能をコメントアウト
ここまでやると、linuxのgccでコンパイルが通る。
この時点で判るバグは、'=nn のRNDシード設定が何もコードを吐き出さない。
論理否定notが使えない。
文字列と改行のみのプリント文の行でエラーになる。
手持ちのアセンブラが「.」(ピリオド)「_」(アンダーバー)で始まるラベルをエラーとするので、「.」「_」で始まるラベルを生成する部分を修正。
parse.c内のToken *tokenize()関数の中にある、変数名判別部がアルファベットの大文字しか受け付けてないので
ソース上で小文字のアルファベットであっても内部処理で大文字に置き換えるように修正
}else if ((('A'<=*p) && (*p<='Z')) || (('a'<=*p) && (*p<='z'))){
// printf(";tokenize TK_LVAR '%c',p='%s'\n",*p,get_least_line(p));
p[0]=*p & 0xdf;
grep -nHIF -- .L (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:574: sprintf(label,".LN%d",(v>=0)?v:65536);
codegen.c:584: sprintf(label,".LL%d",labelnum++);
codegen.c:593: sprintf(label,".LD%d",v);
codegen.c:601: sprintf(label,".LF%d",v);
「.L」を「L_L」に変更
grep -nHIF -- RMB (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:2032:void RMB_comment(char *label,int size,char *comment)
codegen.c:2036:void RMB(char *label,int size)
codegen.c:4409: RMB("_RETSP",2);
codegen.c:4411: RMB("_A",2);
codegen.c:4412: RMB("_B",2);
codegen.c:4413: RMB("_C",2);
codegen.c:4414: RMB("_D",2);
codegen.c:4415: RMB("_E",2);
codegen.c:4416: RMB("_F",2);
codegen.c:4417: RMB("_G",2);
codegen.c:4418: RMB("_H",2);
codegen.c:4419: RMB("_I",2);
codegen.c:4420: RMB("_J",2);
codegen.c:4421: RMB("_K",2);
codegen.c:4422: RMB("_L",2);
codegen.c:4423: RMB("_M",2);
codegen.c:4424: RMB("_N",2);
codegen.c:4425: RMB("_O",2);
codegen.c:4426: RMB("_P",2);
codegen.c:4427: RMB("_Q",2);
codegen.c:4428: RMB("_R",2);
codegen.c:4429: RMB("_S",2);
codegen.c:4430: RMB("_T",2);
codegen.c:4431: RMB("_U",2);
codegen.c:4432: RMB("_V",2);
codegen.c:4433: RMB("_W",2);
codegen.c:4434: RMB("_X",2);
codegen.c:4435: RMB("_Y",2);
codegen.c:4436: RMB("_Z",2);
codegen.c:4437: RMB("_CALLRET",2);
codegen.c:4449: RMB_comment(label,2,comment);
「_」「V_」に変更
grep -nHIF -- \t_ (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:755: printf("\tINC\t_%s\n",v);
codegen.c:760: printf("\tDEC\t_%s\n",v);
codegen.c:765: printf("\tINC\t_%s+1\n",v);
codegen.c:770: printf("\tDEC\t_%s+1\n",v);
codegen.c:775: printf("\tTST\t_%s+1\n",str);
codegen.c:779: printf("\tTST\t_%s\n",str);
codegen.c:1036: printf("\tNEG\t_%s+1\n",v);
codegen.c:1038: printf("\tDEC\t_%s\n",v);
codegen.c:1039: printf("%s\tCOM\t_%s\n",label,v);
codegen.c:1158: printf("\tLDA%s\t_%s\n",r,str);
codegen.c:1172: printf("\tLDA%s\t_%s+1\n",r,str);
codegen.c:1324: printf("\tSTAB\t_%s+1\n", str);
codegen.c:1325: printf("\tSTAA\t_%s\n", str);
codegen.c:1361: printf("\tSTAA\t_%s\n",str);
codegen.c:1366: printf("\tSTAA\t_%s+1\n",str);
codegen.c:1376: printf("\tSTAB\t_%s\n",str);
codegen.c:1381: printf("\tSTAB\t_%s+1\n",str);
codegen.c:1415: printf("\tADDB\t_%s+1\n", v);
codegen.c:1459: printf("\tADDB\t_%s+1\n", v);
codegen.c:1460: printf("\tADCA\t_%s\n", v);
codegen.c:1495: printf("\tSUBB\t_%s+1\n", v);
codegen.c:1496: printf("\tSBCA\t_%s\n", v);
codegen.c:1569: printf("\tANDB\t_%s+1\n", v);
codegen.c:1575: printf("\tANDB\t_%s+1\n", v);
codegen.c:1576: printf("\tANDA\t_%s\n", v);
codegen.c:1606: printf("\tORAB\t_%s+1\n", v);
codegen.c:1607: printf("\tORAA\t_%s\n", v);
codegen.c:1631: printf("\tEORB\t_%s+1\n", v);
codegen.c:1632: printf("\tEORA\t_%s\n", v);
codegen.c:1671: printf("\tCLR\t_%s+1\n", v);
codegen.c:1682: printf("\tCLR\t_%s\n", v);
codegen.c:1788: printf("\tCMPA\t_%s\n",str);
codegen.c:1792: printf("\tCMPA\t_%s+1\n",str);
codegen.c:1800: printf("\tCMPB\t_%s\n",str);
codegen.c:1804: printf("\tCMPB\t_%s+1\n",str);
codegen.c:1866: printf("\tLDX\t_%s\n",str);
codegen.c:1895: printf("\tSTX\t_%s\n", v);
codegen.c:1909: printf("\tCPX\t_%s\n",str);
codegen.c:1936: printf("\tLDX\t_%s\n",str);
codegen.c:4398: printf("\tSTS\t_RETSP\n");
「_」「V_」に変更
grep -nHIF -- \tRMB\t2 (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:4457: printf("_%s\tRMB\t2\t; for loop pseudo array\n",ofl[i].label[j]);
codegen.c:4465: printf("_%s\tRMB\t2\t; do loop pseudo array\n",odl[i].label[j]);
「_%s」を「V_%s」に変更
asm6809では「FCC 'ABC'」などと記述すると 'ABC'の最初のAしかオブジェクトに反映されないバグ? 仕様?
なので、「FCC 'ABC'」は「FCC /ABC/」などと記述を変更する。
DO-untilループの出現数カウンタのodlの扱いが、for-nextループの出現カウンタのoflと
混同されているところを2箇所発見修正
エミュレータ6809内蔵のアセンブラのバグで #-1を8ビットの#$ffと変換する。8ビットのA,Bに対してなら問題ないがD,X,Yなど16ビット計算では意味が変わってくる。
追記:#-$01とすると $00ffを#-$0001とすると$ffffを出してくれる。
GAMECC側に16ビット数値を扱うときに変更するように工夫が必要。
ADDD,LDX命令のイミディエイト コードを出す所に負号拡張処理を追加
FCCコードの部分で文字列中に「/」スラッシュを使うと、
デリミターとしての/と混同されて文字列の一部が消滅するのでデリミターとして「”」ダブルクォートを使うことにする。
この時点で引っかかっているのは、RNDのシード値が設定できない。
do-untilの「@=1」をコンパイルするとコンパイラが警告文を出すが動作するコードを吐く
othello.gで使われているのだが、所謂 do-untilループ内からのbrakeらしいのだが
do-untilの一対しか許されてないっぽいので、警告のエラーを出してるっぽい?
BM-L2用の特殊文字の変換ルーチンを無くす。SBC6809などのACIAのシリアル接続だけの環境用に作っているので
所謂7ビット文字だけの扱いに収めるのが目標
プログラムの終端をどうしようか思案中、インタプリタでは
「#=-1」でプログラム終了してインタプリタに戻ってきたが、
今のところ何も入れてないのでメモリ空間一周してバッファフローしてエミュレータがフォールトする。
そろそろ、SBC6809実機に入れる算段も考えたい。EEPROMを外して焼いて戻してだと非効率だから、
HEX形式でシリアル転送して、メモリに転送するルーチンをROMに組むこむか?
6800−6809のニーモニックコンバータが無いのかと探している。
6809が出た当初に、6800から移行した先達が作っていそうだと思ったんだが見つけられていない。
rev 0520
BM-L2の固有文字を変換する部分を無効化、
LDXに対して 変数領域 オリジナルだと「_」で始まる変数のラベルをこちらでは「V_」で始まるようにしてるので
LDXに付ける変数ラベルが変えられてないのを修正。
オリジナルだと
LDX #_TMP
なのを
LDX #V_TMP
と出すようにしてるつもりで、オリジナルのままだったのを修正
インタプリタのGAME9EXのセットのGAME9CCを試しにgameccでコンパイルさせてみた際にこのバグを発見。
GAME9CCにもいくつかバグを発見
行番号3610と3700の間に、3520があってエラーになる。
あとGAME言語的には仕様であってバグではないのだが、存在しない行番号に向けてジャンプする命令が何箇所か
gameccではエラー扱いなので、コメント文のダミー行を入れて対処。
intelHEX形式の端末画面経由のアップロード、ダウンロードツールを作る。
要はHEX形式のテキスト文をコピーして6809上でペーストするとメモリ上に落とされる。ダウンローダと
6809のメモリ上のバイナリデータをHEX形式に整えて、画面に表示させ
それを端末上からコピーしてPCでテキスト文として保存する。セーバー。
ダウンローダーはZ80のアセンブラで組まれたものが参考に出来たので、
6809でもアセンブラで組んでみた。
セーバーは、GAME言語で組んでGAMECCでアセンブラのソースにした。
その際に、「TSX」のコードのミスを発見。
単に「TFR S,X」で良いのを「LD X,S」としていた。
レジスタ同士のデータのやり取りをLD命令でやる80系の癖でヤラカシていた。
あと、6800ではSを1加算すると説明されていたが、
6809でSに1加算するとスタック絡みでフォールトするので不要だと判断した。
入力動作の際に、16進のA-Fの小文字での入力を受け付けないのを
小文字のA-Fを内部で大文字に変換するようにした。
RNDシード値の設定をできるように修正
オミットしたTIMER設定部を参考にRNDに置き換えてみた。
あと、#-1を#-$0001に修正する部分で#0も#-$0000になっていたのを修正
オプティマイズルーチンが過剰反応して、無駄な省略をするせいで
却って変数の無駄な差し渡しが発生しているところを直したいが最適化処理の流れを追うのが面倒で放置中
現状、なんとか動いているので一旦はコレで良しとする。ソース上でもインタプリタでも問題なく動作するが
GAMECCでコンパイルすると動作がおかしい場合は、出てきたアセンブラのソースを眺めて
該当部分のデータの流れを適宜見てもらうしかない。
例を示すと
maze.gの
102 D(0)=1 D(1)=S D(2)=-1 D(3)=-S U=S*T-1
がオリジナルだが
GAMECCでコンパイルして動作させるために
102 D(0)=1 U=S D(1)=S D(2)=-1 D(3)=-U U=S*T-1
オプティマイザの処理で、変数Sとそれを負数にした-Sが同一の値だと認識されてD(3)に代入されるので
一旦変数Uという別の器を用意している。
変数領域として$800、プログラム本体は$2000に生成するように.asm内のORG文を設定して
GAMECCの中でコンパイル時に変更できるようなコマンドラインオプションなどは用意していない。
コメント
コメントを投稿