究極の8bit CPUを考える
モトローラのMC6809のことを「究極の8bit」と最初に呼んだのは月刊ASCII誌1980年10月号の特集「究極の8bitマイクロプロセッサ MC6809」だと思う。特集では、1980年5月に発表されたベーシックマスターレベル3(6809搭載の8bit機)、ハード・ソフトウェアアーキテクチャー、自作コンピュータ記事が掲載された。翌1981年5月に6809を2つ搭載した富士通FM-8が発表され、1984年には書籍も出版された。
当時高校生だった私はすっかり感化されてしまって大学に入学してすぐにFM-8を買ったものだ(そしたら直後にFM-7が出て大ショックであったが、それはさておき)。
6809はアセンブラでプログラミングするには便利なCPUで、6800にあった欠点(IXレジスタが1本しかない、16bit演算ができない)が解消された良いCPUだと思ったし、今もそう思っている。
ただ、現代の目からすると「なんとかならなかったか」と思う面はあって、本当に究極だったのか?と思ったりもする。
MC6809
- 6809.net - 6809命令表 - 6809 命令表
- Analysis of the M6809 instruction set | Proceedings of the May 16-19, 1983, national computer conference(1983年の論文)
MC6309
1982年に日立から出た6809互換CPU。6809に比べて様々な強化が行われている。
-
アキュムレーターの追加 (E,Fの2本。連結して16bitレジスタWとしても使える)
-
D,Wを連結して32bitレジスタQとして使える
-
ゼロレジスタ、-1レジスタの追加
-
E,F,Wをインデックスアクセスのオフセットとして利用できる
-
Wをベースレジスタとして使える
-
符号付き乗除算、16bit演算の強化、ブロック転送命令の強化
-
bit演算命令の追加
-
https://colorcomputerarchive.com/repo/Documents/Microprocessors/HD6309/Oh!FM,%20April%201988%20(Japanese).pdf
それは8bit CPUなのだろうか
6809も複雑な命令では命令長が長くなる。インデックスレジスタとしてY/U/Sを使うとプリバイトが付くし、複雑なアドレッシングではポストバイトが付く。(5バイトが最長だっけ?覚えてない)。 6309の新設命令ではさらにプリバイトが1バイト付く。x86の進化を見ているようだ。
8bit CPUなので命令長はなるべく1バイトにして欲しいし、2バイトのアドレス付けて3バイトが上限だと思う。
Analysis of the M6809 instruction set | Proceedings of the May 16-19, 1983, national computer conferenceによると、平均命令長は以下の通り。意外に短い?
|Class Average|Size |Numeric|2.16 bytes |Monitor|2.27 bytes |Compiler|2.30 bytes |Application|2.40 bytes |Compiled|2.43 bytes |All|2.35 bytes
命令bit数が足りない
命令長が8bitしかないのが厄介。レジスタ数は4個では足りないので仮に8個にすると、レジスタ指定に3bitを消費する。レジスタレジスタ転送を1命令に納めると、これだけで6bit使ってしまい、命令に残す余地が2bitしかない。6809ではレジスタ転送命令は2バイト(TFR+ポストバイト)になっているし、6309のTFRはポストバイトを使い切ってしまっている。
8080は8bitレジスタ8個(Mもレジスタと見なす)で、レジスタ間転送のMOV命令で命令セットの1/4(64個分)を消費している。2レジスタ命令は転送命令だけであり、他の命令は暗黙のうちにレジスタ指定が行われている。
いまどきのCPUっぽくレジスタレジスタ演算をメインにしようとすると、とにかく命令ビット数が足りない。それなら16bit CPUにした方が素直で良さそうである(H8みたいに)。
RISC-Vのように、16bit命令を標準にして、使用頻度の高い命令/レジスタは短縮命令を用意するのが良いのか?(それ、ポストバイトの逆だな)。
レジスタ数は何個が良いのか
汎用レジスタ8個は厳しいので4個+SP+PCで考える。演算は全て16bitとし、load/storeだけバイト単位も許すことにしよう。
演算はレジスタ間だけだとすると(いいのか?)、1XXX レジスタ指定2x2bit でも8命令しか使えない。さすがにこれはダメだ。
アドレス修飾と演算のレジスタを分けると1bit浮くんだけど、それでは6800である。
こんなのを考えてみた
-
基本はMC6800
-
16bit演算は必要
-
インデックスレジスタは2本(以上)必要
-
MC6800のAレジスタ命令を16bit Dレジスタ命令にする。Bはそのまま。
-
DとBを分けるかどうか。
- 分けなくても良いような気がする(Dの下位8bitがB)
- 分けない場合、ADDBでキャリーが出たらどうするのか?
- Dに1バイト足したい時はどうするのか
- (ADDDbyte のような命令が欲しくなる。ADD/SUB/ADC/SBCの4つ。合計16命令?)
- 分けた方が便利な用途はある
- 10進ASCII->2進変換のときは、Bで処理しながらDに値を作りたい
- この場合、ADDD B のような命令が必要になる。これもADD/SUB/ADC/SBCの4つだが、4つで済むはず
- 済まないな。論理演算を考えると転送命令が欲しくなる。Dの上位下位と転送方向で4命令
-
ゼロページアドレッシングを潰して、その部分のコードをYレジスタ修飾にする。
-
なのでアドレッシングモードは、イミディーエイト・X修飾・Y修飾・エクステンデッドの4つ
-
LDY,STY,CPYを空き部分に追加
- $83-8B,$C3-$F3,$CC-$FC,$CD-$FD が空いている
-
NEG/COM/LSR/ROR/ASR/ASL/ROL/DEC/INC/TST/CLR のY修飾ができない
- 元々MC6800でもゼロページが使えず、エクステンデッドになっていた
- なくても困らない(かもしれない)。この時だけはXのみにする?(命令の対称性が崩れるのでよろしくない)
- あるいは、エクステンデッドを潰してYにする。こちらが筋が良いと思う
- あるいは、シフト・ローテートだけ空きに入れる?
- この手の命令が欲しくなるのは16bit/32bitの乗除算や論理演算である
- インデックスアドレッシングができれば問題ないはず
-
32bitレジスタが欲しいときがある
- 32bit longや32bit float
- 6809などのコンパイラでは Y:D を32bit レジスタとして使っている
- Dの裏レジスタがあれば良いような気がする (Z80みたいだ)
- LDD high16bit, XGDD, LDD low16bit で良い
- どうせならX/Yにも裏レジスタが欲しい
-
PSHX/PULX/PSHY/PULY, TSY/TYSを空きに追加 (PSHD/PULDはPSHA/PULAの位置を使う)
-
ADX(ABX), ADY(ABY), ADS(ABS)などのアドレスレジスタ操作命令を追加
- メモリとの加算をしたい場合の命令の空きがないぞw
- 実用上はDと足せれば十分なはず
- キャリーは立たせるべきか?
-
XGDX,XGDY,XGXYも欲しい
- スタックとの交換命令(8080のXTHL)も欲しい?
-
ABA/SBA/CBAは削除。あると便利ではあるが
-
命令の空き位置は、下記サイトの一覧が便利
別の案
- 基本はMC6800
- AccA,Bを16bit化する
- Load/Store byteを追加して、下位8bitを読み書きできるようにする
- バイト読み込みのときに符号拡張するかしないか。00拡張にしてSign Extendがある方が良さそう
- ダイレクトページは無くして、IY修飾にする
- メモリを直接触れる命令は、MC6800ではNEG/COM/LSR/ROR/ASR/ASL/ROL/DEC/INC/TST/CLRがある
- NEGは不要だと思うので削って他の命令を入れる
- 両方16bitだと、ABA/SBA/CBAの他にAND/OR/XORも欲しくなる
オペコード空間
RISC/CISC
同様のことを考えている人
- mc6809/super6809.md at master · cavnex/mc6809
- 6502.org • View topic - How would YOU extend the 6502?