2019年7月31日水曜日

CP/M-8000は移植できるのか リンカ 1

CP/M-8000のリンカ ld8kのソースコードがP-CP/M-Z8k SOURCESの中に見つかったので、Programmer's Guideと共に読み進めています。

最初、ソースコードを修正してLinuxで動くようにしようとしたのですが、文法が古典過ぎて最近のコンパイラは通りません。また、バイトオーダの違いもあって、素直には動かせそうにないので、ソースコードを参考に書き直すことにしました。

ソースコードだけからでは意味がわからなかった部分も、Programmer's Guideにコマンドファイルフォーマットとリンカの使用方法の説明があったおかげで、再配置データやシンボルテーブルが読み出せるようになりました。

下はcpmsys.relのシンボルテーブルを読み出した例。


このファイル中のシンボルは、225個あることがわかります。どうやら、セグメント番号0xffでタイプ2のシンボルが外部定義シンボルのようです。

リンクの仕方は、ソースコード読み進めてこれから理解していきます。

2019年7月28日日曜日

CP/M-8000は移植できるのか CPMLDRを探る 1

The Unofficial CP/M Web site にある CP/M-8000 1.1 で確認を始めています。
CPMLDRのソースコードは、disk4 に収まっています。

BIOSは、Olibetti M20 というマシン用に書かれています。幸いなことに、ネット上にはマシンのハードウェア情報があるので参考になりそうです。

bios.sub がBIOSをビルドするためのサブミットファイルです。そこから読み進めると、コンパイルとアセンブルが必要なファイルは、
  • bios.c
  • biosasm.8kn
  • biosdefs.8kn
  • biosboot.8kn
  • biosif.8kn
  • biosio.8kn
  • biosmem.8kn
  • biostrap.8kn
  • syscall.8kn
  • fpedep.8kn
  • fpe.8kn
  • libcpm.a
biosboot.8knの中に、メモリ配置に関する情報がありました。
  • ブート時のシステムの配置アドレスは、<<10>>0000
  • ブート時のシステムのPSAは、<<4>>0100
  • システムの配置アドレスは、<<11>>0000
  • システムのPSAは、<<2>>0100

BIOSはアセンブリ言語だけで記述されていると思っていたら、C言語も使われています。結構面倒なことになってきました。gccが使えるのか、もしくはアセンブリ言語で書き直しかな。

fpedep とfpe はソースが無く、アセンブルされたオブジェクトのみがあります。これらは、浮動小数点演算用のようで、ローダに必要なのかわかりません。

CP/M-8000は移植できるのか

正直、かなり手強そうです。

現在、The Unofficial CP/M Web Site にある、下の2つのドキュメントを読んでいるところです。

・ Programmer's Guide
・ System Guide

ドキュメントが英語で書かれているのは仕方ないとして、私がCP/Mの知識をほとんど持っていないことが、理解が進まない原因です。さらに、セグメントやシステム/ユーザーモードの存在とかが話をややこしくしていて、頭がだいぶ混乱しています。しかし所詮は趣味なので、最高の人生の暇つぶしとして移植を楽しんでいくつもりです。

これからは、情報をまとめるためのメモ代わりとして、ここを使っていきます。

とりあえずわかったこと、
  • cpm.sysがOS本体で、bios.rel, cpmsys.rel,  libcpm.a をld8kでリンクして作る 。
  • cpmsys.rel は、ccp.rel, bdos.rel, libcpm.a をリンクしたもの。
  • 簡略版のBDOS と BIOSをリンクしたcpmldrが、cpm.sysをメモリーにロードする。
  • CP/Mはシステムメモリ空間、トランジェントコマンドはノーマルメモリ空間を使う(ハードウェアが対応していれば)
  • ノンセグメントのコマンドでは、インストラクションとデータのメモリ空間をわけることもできる。(ハードウェアが対応していれば)
未だ不明なこと
  • cpm.sysが読み込まれるメモリアドレスがどう決まるのか?
  • TPAのアドレスがどうやって決まるのか?
  • トランジェントコマンドは、何かリロケータブルなフォーマットなのか?
  • ccp.rel と bdos.rel は提供されていない?

CP/M-8000の実行環境が無いとld8kが使えないので、cpm.sysを作るには、クロスでリンクできる環境が必要そうです。

とりあえず、CP/M本体をメモリーにロードするcpmldrを動かすことを当面の目標にします。

2019年7月26日金曜日

z8kmon公開

Z8001用の機械語モニターをGitHubにさらしました。
なんの使いみちの無いようなものでも、誰かの役に立てるかもしれず。

https://github.com/4sun5bu/z8kmon


気が向いたらアップデートしていきます。
使い方はREADMEを読めば、大方わかるはずです。
<<0>>0000からRAMが配置されている不自然なメモリー配置が前提になっているので、ROMを先頭に配置する方は、適当にリンカスクリプトを書き換えてください。

これからは、作ったZ8001ボードでCP/M-8000が動かせるのか検討する、セカンドフェーズに入っていきます。

2019年7月14日日曜日

Z8001クロス開発環境 binutilsをビルドしてみる

以前、導入したクロス開発環境だと、binutilsのバージョンが2.19と古いので、新しいバージョンをビルドします。最新は2.32で、Z8000も未だにサポートされています。

ビルドに使った環境は、Ubuntu 18.04.2 LTS (Bionic Beaver) 64bit です。

 https://ftp.gnu.org/gnu/binutils/binutils-2.32.tar.gz

ダウンロードしたら、展開します。

    tar xvzf binutils-2.32.tar.gz

ビルド用のディレクトリを作ります。

    mkdir cross-dev

ビルド用のディレクトリに入り、configureを実行します。targetには、z8k-elfは指定できないようなので、z8k-coffにします。prefixには、インストールするディレクトリを指定します。

    cd cross-dev
    ../binutils-2.32/configure --target=z8k-coff --prefix=$HOME/opt

そして、

    make
    make install

私の環境では、エラーもなく結構かんたんにビルドできました。
prefixで指定したディレクトリのbinの下に、実行ファイルが入っていますので、PATHを通しておきます。

残念ですが、GCCは公式にはZ8000をサポートしていないようなので、古いバージョンを使うしかないですね。



2019年7月4日木曜日

Z8001のアセンブリ言語 その2

また誰の役にも立たないと思いますが、Z8001のアセンブリ言語でコードを書いているときに気づいたことを書き留めておきます。

レジスタの値がゼロか正負かを調べるには TEST より OR 

レジスタの値がゼロかどうか調べたり、正か負を調べる場合に、TESTを使うと7クロックですが、同じレジスタ同士でORを使うと4クロックですみます。TESTは、レジスタではなくメモリの値を調べる場合に使ったほうが、メモリから一度レジスタに読み出す必要がないのと、レジスタを破壊しなくてすむので有利になります。またTESTは32bit値が使えますが、ORでは使えません。

レジスタのゼロクリアには CLR より XOR

レジスタの値をゼロにしたい場合、CLRを使うと7クロックですが、同じレジスタ同士でXORを使うと4クロックですみます。ただし、CLRではフラグは変化しませんが、XORではZフラグが変化してしまいます。これもメモリの値をゼロにしたい場合には、CLRをつかった方が有利になります。

OR Rx, Rx でキャリーフラグはリセットされない

Z80では、Cフラグをリセットするために、ORANDが使われていましたが、Z8000では、フラグがリセットされません。リセットには、RESFLG C を使います。


INC, DEC はキャリーフラグが変化しない

Z80もそうだったような気がしますが、実行結果によってZフラグやSフラグは変化するのに、Cフラグには影響しません。INCDECは、1から16まで増減量を指定できるので便利なのですが、Z80には無かったので、コードを書くときに指定を忘れがちです。

また、何か気づいたら書いていきます。