【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

8086版V6のABI(仮)

先日、PDP-11から8086へのトランスレータを試作しました。

簡単なプログラムを変換して大まかなABIが見えてきたので、仮にまとめます。詳細についてはV6移植ハッカソンで作業しながら決めていこうと思います。

ABI

今回提示するのは標準的な8086のABIとは異なりますが、当面は変換の都合を優先します。標準的なABIへの対応は、移植が完了した後の課題とします。

以下、8086のアセンブリはIntel記法(NASM)で示します。

システムコール

PDP-11に割り込みベクタを合わせるため、int 7をシステムコールに使用します。これは実機では予約されていて勝手に使えない割り込み番号ですが、仮です。

カーネルは直接PC/ATには移植しないで、PDP-11のCPUだけを8086に置き換えたような仮想マシン(仮称キメラ)を経由する予定です。そのときまでの仮です。移植の作業フローについては次の記事を参照してください。

システムコール番号はint 7に即値を後置します。引数はUNIX V6と同様に後置します。

PDP-11 8086
mov $1, r0
sys 4
0
6
mov ax, 1
int 7
db 4
dw 0, 6

これは標準的な8086のABIとは異なりますが、前述の通り移植完了まで棚上げします。

レジスタ

基本的にPDP-11と8086のレジスタは1対1で変換します。

PDP-11 8086
R0 AX
R1 DX
R2 CX
R3 SI
R4 DI
R5 BP
R6(SP) SP
R7(PC) (IP)

8086ではPCが汎用レジスタではないため単純に変換できません。PCをレジスタとして扱っている箇所は少数ですが存在するため、個別に対応を検討します。

保存

PDP-11では関数呼び出しでR2~R6(SP)が保存されます。8086版V6でもそれに従い、対応するレジスタ(CX, SI, DI, BP, SP)を保存します。

これは標準的な8086のABIとは異なりますが、前述の通り移植完了まで棚上げします。

BX

PCを変換しないため、8086ではレジスタが1つ余ります。余ったBXレジスタは変換で一時レジスタとして使い回します。

一時レジスタにBXを選んだ理由は、アドレス指定に使えて、8bitアクセス(BH/BL)ができるからです。

mov

PDP-11は命令の直交性が高く、すべてのレジスタが同じようにアドレス指定に使用できます。

8086はアドレス指定に使用できるレジスタが限られています。

  • [BX+SI+d], [BX+DI+d], [BP+SI+d], [BP+DI+d], [SI+d], [DI+d], [BP+d], [BX+d]
    (dはディスプレースメント)

PDP-11ではアドレス指定に1つのレジスタしか使いません。今回は機械的に変換するため[BX+SI+d]のような組み合わせは使いません。

8086への変換で対応するレジスタがアドレッシングに使えない場合、一時レジスタとしたBXで対応します。

PDP-11 8086
mov (r1), r0 mov bx, dx
mov ax, [bx]

PDP-11ではソースとデスティネーションが同じ自由度で指定できるため、メモリ間の直接movも可能です。8086では不可能です。アドレス指定に使われているレジスタのうち変換が必要なものが片方だけなら一時レジスタBXで、両方ならスタックを使って対応します。

PDP-11 8086
mov (r1), 4(r5) mov bx, dx
mov bx, [bx]
mov [bp+4], bx
mov (r1), (r0) mov bx, dx
push [bx]
mov bx, ax
pop [bx]

V6のコンパイラは関数呼び出しでの引数用のスタックとしてあらかじめ2バイトを確保しているため、デスティネーションに(SP)が多用されます。当面は効率に目をつむり、SPを巻き戻してのpushで対応します。

PDP-11 8086
mov (r1), (sp) add sp, 2
mov bx, dx
mov bx, [bx]
push bx

PDP-11はmov命令でスタックの操作が行えるためpush/pop命令がありません。スタック操作を認識してpush/pop命令に変換します。

PDP-11 8086
mov r0, -(sp) push ax
mov (sp)+, r0 pop ax
mov (r0), -(sp) mov bx, ax
push [bx]

感想

CISC間での変換のはずなのに、まるでRISCに変換するかのような分解っぷりです。8086はレジスタが少なくアドレス指定にも制限があるため、ある意味RISCよりも回りくどくなっている面があります。

トランスレータはつなぎだと割り切っています。最終的にはコンパイラに手を入れる計画なので、その時に出力するアセンブリを調整しようと思います。