Intel社が8080Aの改良版として発表したのが8085です。Intel社によれば、3 umプロセスにより約6500個のトランジスタを集積したチップで、1976年3月に発表だそうです。通常のバージョンで3 MHzクロックで動作し、高速版では5 MHzで動作するものも供給されました。命令の処理に必要なクロック数は8080とほぼ同一なので、(メモリなど外部のスピードが間に合うなら)2 MHzクロックの8080Aよりはクロック周波数に比例した分だけ高速になっています。8085と同時期に発表されたZ80 CPUが2.5 MHzクロックで、その高速版が4 MHzクロックということを考えると、8080の命令だけを使う限りは2割くらい8085が高速ということになるんでしょうかね。1命令あたりのクロック数もそれほど変化ありませんし。
上が8085で1977年製のプラスチックパッケージのものです。下は8085の改良品の8085Aでセラミックパッケージ。
8085のマイナーバージョンアップが8085Aです。DMAモードのときにALEがスリーステートになっていたのが8085AではLレベルに固定されているとか、TRAP割り込みの際に割り込みイネーブル状態を保存するなど、わずかな不具合の修正だけです。1978年に8085Aに切り替わりました。ただ、最近ジャンクで出てくるのは8085A(のセカンドソース品)だけになっていますね。
8080Aと比べてどのような改善が行われたかというと、
5 V単一電源化
クロックジェネレータとシステムコントローラ内蔵
簡単な割り込みコントローラ内蔵
高速化
1 bit I/Oポート追加
割り込みマスク制御用のRIMとSIMの2命令の追加
くらいですかね。ROMとI/Oポートを集積化した8355/8755、RWMとタイマやI/Oポートを集積化した8155/8156と組み合わせれば、3チップ構成で完全なコンピュータを実現できました。同等の回路を8080AとそのファミリLSIで構成すれば10個以上のICが必要となりますし、5 Vの電源の他に12 Vと-5 Vも用意しなくてはなりません。8085Aもそれほど低消費電力ではありませんが、部品数が少ないこともあり8080Aで組んだときの1/4程度になるでしょう。ちょうどMotorolaの製品系列のMC6802に相当します。
水晶発振子を接続するだけでクロック信号を生成し、メモリやI/Oの読み書きパルス信号を直接出力できますから、8080A + 8224 + 8228がひとつになっていることになります。しかも5 V単一電源で動作し、4本の割り込み端子が追加されています。後述しますが、小規模な組み込み用には便利です。
広く使われたCPUファミリの中では、トランジスタ数が手頃であったためもあるのか、CMOS版が早い時期に開発されて使われるようになったのも特徴的でしょうか。沖電気の場合には1981年からCMOS版を供給していました。Z80もCMOS化されていくのですが、時期的に8085系よりは後になります。
当時はZ80という競合相手があり、パーソナルコンピュータで8085が採用された例はほとんどありません。しかし、小規模の組込み用途にはZ80より小型化できる傾向があり、自動販売機の制御とか工場のオートメーションコントロールのシーケンサと呼ばれる小型制御モジュールなどによく使われていました。
パーソナルコンピュータ的な使い方だと大容量のRWMが必要となりますからダイナミックメモリを使いたくなります。8085とZ80を比べれば、Z80の方がダイナミックメモリを使いやすいですから、パーソナルコンピュータに使うならZ80となるのでしょう。しかし制御用なら話は別です。RWMは128 Byteからせいぜい2 KByteで済むような用途が多くS-RWMですみます。命令が8085の方が少ないとはいえ、Z80の拡張した命令を使わなくても、それほど不便ではありません。Z80は強力なベクタ割り込みが使えて、割り込みを多用する組み込み用途には有利そうにみえますが、Z80専用の周辺LSIを使わなければいけないという制約がつきます。8085なら8080Aの割り込み信号に加えて4本の割り込み信号が拡張されていますから、割り込み要因が5種類以下なら外付け部品なしで割り込みサービスルーチンを起動できます(要データバスプルアップ)。周辺LSIを組み合わせて8085-8755-8155の3チップ構成のコンピュータならZ80より単純で小型ですし、8085-74LS373-74LS139-ROM-RWM-8255A-8255Aといった形でLSIが5個にLS TTLが2個という構成でもZ80システムと比べてコストが安くあがるかもしれません。Z80で複数の外部割り込みに高速に対処しようとするなら、アドレスデコーダ用のゲートを数えないことにしてもZ80 CPU - ROM - RWM - Z80 PIO - Z80 PIOといった組み合わせになってしまいます。Z80 CPUは安くなってもZ80専用の周辺LSIは高かったですから、割り込みが数種類なら8085よりコスト面で不利になります。外部割り込み要因が1本だけならZ80 PIOの代わりに8255Aが使えて、8085システムと似たり寄ったりのコストになるのですが。そんなわけで、組み込み用途には8085という判断もあったのです。
RIMとSIMの2命令が追加されただけで他は8080と同一の命令ですから、8080の項を参考にしてもらえばよさそうですが、命令実行に必要なクロック数が多少変更されていますので、そのあたりだけ比較してみます。次の表の8080の項が8080のクロック数、8085の項が8085のクロック数を意味します。命令のビットパターンや意味の方は8080の項目を参照してください。
アセンブラ表記 8080 8085 MOVE, LOAD, and STORE MOV rm, r 5/7 4/7 *** MOV r, M 7 7 MVI rm, imm 7/10 7/10 LXI rp, imm16 10 10 STAX rx 7 7 LDAX rx 7 7 STA addr 13 13 LDA addr 13 13 SHLD addr 16 16 LHLD addr 16 16 XCHG 4 4 STACK operations PUSH rr 11 12 *** POP rr 10 10 XTHL 18 16 *** SPHL 5 6 *** JUMP JMP addr 10 10 JC addr 10 7/10*** JNC addr 10 7/10*** JZ addr 10 7/10*** JNZ addr 10 7/10*** JP addr 10 7/10*** JM addr 10 7/10*** JPE addr 10 7/10*** JPO addr 10 7/10*** PCHL 5 6 *** CALL CALL addr 17 18 *** CC addr 11/17 9/18*** CNC addr 11/17 9/18*** CZ addr 11/17 9/18*** CNZ addr 11/17 9/18*** CP addr 11/17 9/18*** CM addr 11/17 9/18*** CPE addr 11/17 9/18*** CPO addr 11/17 9/18*** RETURN RET 10 10 RC 5/11 6/12*** RNC 5/11 6/12*** RZ 5/11 6/12*** RNZ 5/11 6/12*** RP 5/11 6/12*** RM 5/11 6/12*** RPE 5/11 6/12*** RPO 5/11 6/12*** RESTART RST vec 11 12 *** INCREMENT and DECREMENT INR rm 5/10 4/10*** DCR rm 5/10 4/10*** INX rp 5 6 *** DCX rp 5 6 *** ADD ADD rm 4/7 4/7 ADC rm 4/7 4/7 ADI imm 7 7 ACI imm 7 7 DAD rp 10 10 SUBTRACT SUB rm 4/7 4/7 SBB rm 4/7 4/7 SUI imm 7 7 SBI imm 7 7 LOGICAL ANA rm 4/7 4/7 XRA rm 4/7 4/7 ORA rm 4/7 4/7 CMP rm 4/7 4/7 ANI imm 7 7 XRI imm 7 7 ORI imm 7 7 CPI imm 7 7 ROTATE RLC 4 4 RRC 4 4 RAL 4 4 RAR 4 4 SPECIALS CMA 4 4 STC 4 4 CMC 4 4 DAA 4 4 INPUT/OUTPUT IN port 10 10 OUT port 10 10 CONTROL EI 4 4 DI 4 4 NOP 4 4 HLT 7 5 *** NEW 8085 INSTRUCTIONS RIM - 4 0010 0000 Read Interrupt Mask SIM - 4 0011 0000 Set Interrupt Mask
RIMとSIM命令の後には命令のビットパターンと意味を付け足しておきました。行の末尾に***という印が付いているものが8080と8085で異なる実行クロック数を持つ命令です。
総じて、スタック関係、プログラムカウンタ関係、インクリメンタやデクリメンタに関係する命令に変更がなされています。条件ジャンプと条件リターンに関しては相当に変わり、以前はサブルーチンの脱出を工夫して条件リターンで終えるようにすると、条件不成立時に条件ジャンプを使うより4クロックも高速化されるというテクニックがありましたが、8085になってからは1クロックの差しかなくなってしまいました。条件ジャンプの条件不成立時のクロック数が減少したのが特に効いているといえるでしょう。もっとも従来のテクニックも、短いバイト数の分岐命令がないため、プログラムサイズを減らすには依然として有効です。HLT命令のクロック数が短くなったのは、一見あまり意味が無さそうですが、MC6800のWAI命令と同じように割り込み待ちのために使用されるという用途面を考えると、より高速のデータ転送に利用できるようになったという点で結構な改善と言えるでしょう。
なお、上の命令表ではaddrは16 bitアドレス定数、immは8 bit定数、imm16は16 bit定数を意味します。
さらにrとrmについては以下のレジスタ名の*印の付いているものに置き換えることになっています。
レジスタ名 r rm A * * B * * C * * D * * E * * H * * L * * M *
rp, rr, rxについては次のレジスタペア表記の*印の付いているものと置き換えられます。
表記 rp rr rx B * * * D * * * H * * SP * PSW *
新命令のRIM命令とSIM命令の詳細を説明します。
RIM命令は割り込みマスクなどをAレジスタに読み込む命令です。そのAレジスタの各ビットの意味を表にしてみました。
ビット | 名称 | 意味 |
7 | SID | SID端子の状態 |
6 | I7 | RST7.5の実行待ちの割り込み要求 |
5 | I6 | RST6.5の実行待ちの割り込み要求 |
4 | I5 | RST5.5の実行待ちの割り込み要求 |
3 | IE | 割り込みイネーブル |
2 | M7 | RST7.5の割り込みマスク状態 (0: enable, 1: disable) |
1 | M6 | RST6.5の割り込みマスク状態 (0: enable, 1: disable) |
0 | M5 | RST5.5の割り込みマスク状態 (0: enable, 1: disable) |
この命令はSID入力のためにも必要な命令です。さらにMCS-85で追加されたRST7.5, RST6.5, RST5.5という3本のマスク可能割り込み入力のマスク状態と、割り込み待ち状態を得られます。DI命令とEI命令で設定される割り込みイネーブル状態も取得できます。
SIM命令はAレジスタのデータを使って割り込みマスクなどを操作する命令です。やはり表でその意味を説明します。
ビット | 名称 | 意味 |
7 | SOD | SOD端子への出力データ |
6 | SSI | 1ならSODへデータ転送 |
5 | X | 未使用 |
4 | R7 | 1ならRST7.5要求のリセット |
3 | MSE | 1なら割り込みマスクの設定を行う |
2 | M7 | RST7.5の割り込みマスク |
1 | M6 | RST6.5の割り込みマスク |
0 | M5 | RST5.5の割り込みマスク |
ビット6とビット3のおかげで、SOD出力と割り込みマスク設定を別々に行うことができるようになっています。
別のことを調べているついでに「トランジスタ技術1983年4月号」の記事の一部に柳寿男氏による「8085Aの隠し命令」というコラムを見つけました。といっても元ネタはElectronics誌の1979年1月18日号だそうです。元来私はこの手の命令を使用するのは嫌いなのですが、今さらこの知識を得ても利用する人など皆無だろうし、そんなことで悪習を広める行為になるとも考えられないので、話の種として残しておきます。
命令の前に、実はフラグを納めたFレジスタの未使用ビット3 bitの内の2 bitに新たなフラグが付け加えられています。ついでですから、8080/8085の規定上のFレジスタとZ80 CPUのFレジスタとも比較してみましょう。
ビット | 8080/8085 | undocumented 8085 | Z80 CPU | 備考 |
7 (MSB) | S | S | S | 符号フラグ |
6 | Z | Z | Z | ゼロフラグ |
5 | 0/# | X5 | # | 本来は未使用、X5については後述 |
4 | AC | AC | H | 補助キャリないしハーフキャリ、BCD演算補正用 |
3 | 0/# | 0 | # | 未使用 |
2 | P | P | P/V | パリティフラグ、Z80 CPUだけはオーバーフローフラグ兼用 |
1 | 1/# | V | N | オーバーフローフラグか減算フラグ |
0 (LSB) | C | C | C | キャリ |
未定義のビットには#記号を使用しています。8080Aの資料によっては未定義ビットが0か1に固定であることを明記したものがあったので、そこには#と併記しています。ビット4のACとHフラグは呼び名が異なるだけで、意味や動作は同じものです。
8080/8085にはオーバーフローフラグがなくて、Z80 CPUには追加されたことになっているのが、現実の8085ではこっそりとビット1に組み込まれています。もちろんZ80 CPUとの互換性はありません。Z80 CPUではNフラグといって減算命令実行時にのみセットされるフラグが入っていて、BCDデータの減算時の補正に利用されています。
さらに現実の8085のビット5にはX5と名づけられたフラグが入っています。この意味の定義は面倒ですが、通常の8 bit加減算の場合には第1オペランドの符号をS1、第2オペランドの符号をS2、演算結果の符号をRとするとき、X5 = S1 & S2 | S1 & R | S2 & Rという式でX5の変化を記述できるようです。ただし減算時にはS2を反転したものに置き換えなくてはなりません。ただ、別の意味になるときもあって、16 bit演算の場合にはキャリの役割を果たすようです。しかも特筆すべきはX5はINX命令やDCX命令で変化します。つまりINX命令実行時に0FFFFHから0000Hへとレジスタペアの内容が変化したり、DCX命令実行時にレジスタペアの内容が0000Hから0FFFFHに変化したときにX5がセットされ、INXやDCX命令でそれ以外の値の変化が起きたときにはリセットされるのです。これとX5に関する条件ジャンプ命令の存在だけでも明文化されて公開されていたら便利だったかもとか、ちょっと考えてしまいます。
さて、それでは本題の未定義命令を紹介しましょう。8080のオペコードは244種類存在します。8085では2命令追加されて246種類。どちらも複数バイトにわたるオペコードは存在せず、1 Byteだけのオペコードしかありませんから、8085で残されている未定義命令のコードは256 - 246で10種類です。この10種類のオペコードを8085に実行させると、意外なことにどれも有意義そうな動作をします。おっと、ちょっと面白そうだから、8080の未定義オペコード12種類について8085で明文化されている追加命令と未定義命令、Z80 CPUの命令解釈と並べて表にしてみましょう。なお未定義命令のニーモニックについては文献で定義しているものを使用しています。
オペコード | 8085 | undocumented 8085 | Z80 CPU |
08 | -- | DSUB | EX AF, AF' |
10 | -- | ARHL | DJNZ rel |
18 | -- | RDEL | JR rel |
20 | RIM | RIM | JR NZ, rel |
28 | -- | LDHI imm | JR Z, rel |
30 | SIM | SIM | JR NC, rel |
38 | -- | LDSI imm | JR C, rel |
CB | -- | RSTV | ビット操作命令の導入コード |
D9 | -- | SHLX | EXX |
DD | -- | JNX5 addr | IXレジスタ関係命令の導入コード |
ED | -- | LHLX | 各種拡張命令の導入コード |
FD | -- | JX5 addr | IYレジスタ関係命令の導入コード |
では、未定義命令10種類について、まずは簡潔に表形式で示してから、多少の補足を行います。
命令 コード clock 動作 DSUB 08 10 HL <- HL - BC ARHL 10 7 HL <- HL/2, CY <- L0 RDEL 18 10 DE <- DE*2, E0 <- CY, CY <- D7 LDHI imm 28 dd 10 DE <- HL + imm LDSI imm 38 dd 10 DE <- SP + imm RSTV CB 6/12 if(V) push PC, PC <- 40H SHLX D9 10 (DE) <- HL JNX5 addr DD al ah 7/10 if(!X5) PC <- addr LHLX ED 10 HL <- (DE) JX5 addr FD al ah 7/10 if(X5) PC <- addr
DSUB命令はHLレジスタからBCレジスタを減算するものです。16 bit加算はDAD命令で実行できましたが、Z80 CPUには拡張されている16 bit減算が、8085にはこんなところに未定義命令として追加されていたようです。Z, S, P, CY, AC, X5, Vの全フラグが影響を受けます。
ARHL命令はHLレジスタペアの算術右シフトです。符号を意味するHレジスタのMSBは変化しません。Lレジスタの最下位ビットがCYフラグに入ります。CYフラグだけが変化します。RDEL命令はDEレジスタペアのCYフラグも含めた左ローテート命令です。CYとVフラグが変化します。
なお、未定義命令でフラグに影響を与えるのは、ここまでの3命令だけで、残りの7命令はフラグを変化させることはありません。
LDHI命令とLDSI命令は、それぞれHLレジスタペアかSPに8 bit定数を加えたものをDEレジスタペアに格納します。HLレジスタペアやSPは変化しません。テーブル操作やスタックフレーム操作に利用できそうです。
RSTVはオーバーフローフラグであるVフラグが立っていたときRST 8命令相当の動作を行う、オーバーフロー割り込み命令です。0040Hから始まるアドレスにオーバーフロー対策ルーチンを記述しておき、適切な処理を行うことができます。直接Vフラグを判定できる命令はこれだけです。Vフラグがリセットされているときには6クロック、セットされているときには12クロックを消費します。
SHLX命令とLHLX命令はDEレジスタペアで保持しているアドレスにHLレジスタペアの内容を書き込んだり、逆に読み出したりする命令です。DEレジスタペアの内容はインクリメントされるようなことはなく、特に変化しません。通常の2 Byteデータの格納法と同じく、(DE)で指されているアドレスにLレジスタが、(DE + 1)で指されているアドレスにHレジスタが対応します。
JNX5命令とJX5命令はX5フラグに対する条件ジャンプ命令です。X5フラグを直接判定できる命令はこの2種類だけです。条件が一致して分岐する場合には10クロック、分岐しない場合には7クロックを消費します。
このように、命令解釈実行回路の作成時に未定義命令の検出と対策をきちんと考えていなかったら偶然へんな動作をする命令コードが出来上がってしまったというようなものではなく、何か作為的に実装されているような気がしますね。SHLX命令とLHLX命令など、動作はちょうど対応関係にあるのに、オペコードは0D9Hと0EDHのように直接の対応関係はありませんし。一時は真面目に考えて命令を追加したけれど、互換性の確保とか何かしらの判断があって公開されなかった機能のようです。
以上のフラグや命令については、表題は8085AとなっていますがIntel社の8085についても利用可能なことを確かめました。ただし、すべてのオペランドや条件について調べたわけではなくて簡単にたとえばある値についてHLとBCの差が得られたとか、その程度しか調べていませんが。他にも三菱のM5L8085APや東芝のTMP8085APについても簡単な確認を行って、以上のように動作するらしいことを確かめました。もちろん、これらの命令の利用を勧める気などありませんが、たいていの8085はこんなこともできたんだという事実を記録しておきたかったので。おひまな方は他社の8085Aでも動作確認をして報告してくれると、載せてしまうかも。
採用したコンピュータ製品
NEC TK-85
Intel SDK-85
精工舎 SEIKO 8500