現在地

ASのIM6100対応(その4)


カテゴリー:

前回の最後に複合命令の処理がイマイチと書いたのは次のようなことです。

     	SNL MQA

SNLはグループ2ですから次のMQAは共通命令テーブルとグループ2の命令テーブルを探すことになります。ところがこれはグループ3なので当然見つかりません。

結果として"unknown instruction"エラーになるわけですが、MQAは存在する命令でただSNLとグループが違っているだけです。"invalid instruction combination"エラーの方がより親切というものでしょう。

そこですべてを1つの命令テーブルに入れることにしました。各命令ごとに複合命令にできるか、できるならどのグループかの情報を付加して組み合わせられるか判定します。

ここで1つ問題があります。これまでデコードルーチンに渡される符号なし16ビットのパラメータの、上4ビットにパネルモードや6120のメモリ拡張に関するフラグを入れ、下12ビットにオペコードを入れていたのですが追加情報を入れる空きがもうありません。

仕方ないので次のような配列を作りました。

typedef struct {
	char *NName;
	InstProc Proc;
	Word NCode[3];
	Word Flags;
} tInstInfo;

static tInstInfo InstInfo[] = {
	/* Memory Reference Instruction */
	{"AND", DecodeMR, {00000,     0,     0}, 0},
	{"TAD", DecodeMR, {01000,     0,     0}, 0},
	{"ISZ", DecodeMR, {02000,     0,     0}, 0},
	{"DCA", DecodeMR, {03000,     0,     0}, 0},
	{"JMS", DecodeMR, {04000,     0,     0}, 0},
	{"JMP", DecodeMR, {05000,     0,     0}, 0},

	/* Operate Instruction (Group 1) */
	{"NOP", DecodeOP, {07000, 07400, 07401}, F_Combi | F_GP1 | F_GP2 | F_GP3},
	{"IAC", DecodeOP, {07001,     0,     0}, F_Combi | F_GP1},
	{"RAL", DecodeOP, {07004,     0,     0}, F_Combi | F_GP1},
	{"RTL", DecodeOP, {07006,     0,     0}, F_Combi | F_GP1},
	{"R3L", DecodeOP, {07014,     0,     0}, F_6120 | F_Combi | F_GP1},
	{"RAR", DecodeOP, {07010,     0,     0}, F_Combi | F_GP1},
	{"RTR", DecodeOP, {07012,     0,     0}, F_Combi | F_GP1},
.....

InstTableにはフラグ+オペコードの代わりにこの配列のインデックスを登録します。各デコードルーチンでは渡されたインデックスでこの配列からオペコードや必要な情報を取り出します。

例えばNOP HLT MQLという複合命令があったとしましょう。

まず1つ目のNOPを見るとグループ1,2,3すべてに属しそれぞれの場合のオペコードは7000(8), 7400(8), 7401(8)であることがわかります。この時点ではグループは1, 2, 3のいずれであるかは確定しません。

次のHLTのデータを見てみましょう。

.....
	/* Operate Instruction (Group 2) */
	{"HLT", DecodeOP, {    0, 07402,     0}, F_Combi | F_GP2},
.....

これはグループ2のみなので、グループ2が確定します。オペコードは7400(8)NOPのグループ2の場合のコード)と7402(8)のORです。

続いて最後のMQLのデータを見てみましょう。

.....
	/* Operate Instruction (Group 3) */
	{"MQL", DecodeOP, {    0,     0, 07421}, F_Combi | F_GP3},
.....

おっと、これはグループ3ですので組み合わせられないことが判明しました。"invalid instruction combination"エラーです。

もし途中で配列にないものが現れたら"unknown instruction"エラーです。

これで必要な機能は揃ったとHD1-6120ボード用にUniversal Monitorの移植を始めたのですが...

このアーキテクチャ、イミディエイト命令が存在しないので定数の扱いが非常に厄介です。

ACを0にクリアするならCLAです。

1にするならCLA IAC、クリアしてからインクリメント、命令長もクロックもクリアだけと一緒です。

-1ならCLA CMA、クリアしてからビット反転します。

2, 4はCLA CLL IAC RALとかCLA CLL IAC RTLでできるのかな。データシートによるとこの順序で実行されるらしいからクリアしてインクリメントして左シフトでできると思うのだけど...

実行順序は決まっていて、アセンブリソースにどの順序で書いても一緒です。

BSWも使えば64も作れるかな。でもこういう特殊な値以外はメモリに置いておいて参照します。

	.....
	CLA
	TAD	label1
	.....
label1:	DC	constant
	.....

定数を使うたびにDC疑似命令を書くのはよいとして、毎回ラベルを付けなくてはいけないのは面倒です。同一ページ内にないといけませんし、同じ値なら使いまわしたいところです。

Temporary Symbols も使えないか試したのですが使い勝手が悪く... などと考えていたところSHのLTORG機能を思い出しました。SHは8ビットまでならイミディエイトが使えますが、それを超えたらメモリに定数を置いて参照するしかありません。あまりに面倒なのでメモリに定数を置いて参照するコードを自動的に生成できるのです。IM6100にも同じ機能を搭載することにしました。

そもそもイミディエイトという概念がないので文法を拡張する必要があります。

	TAD	L const

のように書くとconstがどこかのメモリに置かれ、それを参照するコードが生成されます。どこに置くかはLTORG疑似命令で指定します。同一ページ内でないといけないので通常はページ末尾に置くことになるでしょう。同一値はまとめられるので書き換えるISZ, DCAではエラーにしています。

	JMS	IL const

のような組み合わせも可能でページ外のサブルーチン呼び出しに使えます。Indirectと組み合わせる場合はISZ命令などもOKです。

これでモニタの移植も捗って基本機能が動くようになり、その過程でASのバグも修正し一区切りついたかなということで先ほどパッチを AS-users ML の方に送りました。

次回はモニタ移植の話を予定しています。

2022-08-07 追記:
AS 1.42bld228 に無事入りました。

公式ソースでは上記命令テーブルの部分は配列の初期化ではなくヒープに確保したメモリを埋めていく方式に変更されています。
私はすっかり忘れていたのですがASはDOSの16ビット環境用にもビルドできるので。

参考文献・関連図書: 
”Intersil IM6100 CMOS 12 bit Microprocessor”, Intersil.
”PDP-8 PAL III Symbolic Assembler Programming Manual", DEC.

コメントを追加

Plain text

  • HTMLタグは利用できません。
  • ウェブページアドレスとメールアドレスは、自動的にハイパーリンクに変換されます。
  • 行と段落は自動的に折り返されます。
※ コメントは原則公開です。個別のご相談などは「ご意見・ご要望」からお願いします。