M6800ファミリを発表してからしばらく、Motorola社は新しいアーキテクチャのプロセッサを発表しませんでした。しかし1979年になると、次々と新しいアーキテクチャのプロセッサを発表します。その中のひとつに、マイクロプロセッサの機能をぎりぎりまで削って小規模組み込み用に特化させたM6805ファミリがあります。
レジスタもできるだけ削り、アキュムレータは1本のみ、インデックスレジスタも1本でしかも8 bit幅に減らし、PCも内蔵しているROMサイズ分のビット数しか使えないし、スタックポインタも5 bit幅しかありません。プログラムメモリを外部に増設することもできません。命令もそれなりに整理されています。そうして節約したトランジスタを内蔵メモリとI/Oポートに回すという方針ですね。
ただ、削り取って小規模にしただけがM6805の特徴というわけではありません。シリーズ展開こそがM6805ファミリの特徴といえるでしょう。内蔵I/Oのバリエーションも多く、I/O本数を減らした小型パッケージのものもいくつも用意されていて、ROMもPROM版が用意されていて少量生産品への応用にも配慮されていました。またCMOS版も早い時期に提供されていて、電池動作機器にも利用可能でした。
同時期に開発されたM6801ファミリと比べると、処理能力は劣っていますが、簡単な応用にはコストも低く押さえられ、適しています。
これは日立製のHD6805U1です。プロセッサ部はMC6805互換でしょうが付属回路については資料なし。
では特徴的なレジスタ構成を図で説明します。一応、以下の説明ではM6805シリーズの最初の実装であるMC6805P2をもとにしています。
MC6809やMC6801はもちろんMC6800よりも小さく削り取られたレジスタセットになっています。MCS6502とも違いますね。
アキュムレータAとインデックスレジスタXはひとつずつで、それぞれ8 bit幅しかありません。もともと内蔵RWMは少ないですから、100 Byte以上のバッファにデータを格納して処理することなどできませんし。256 Byteより大きな定数表を用いて数値を変換するようなことも困難ですが、普通は8 bitデータ処理ばかりだと思えば、そんなに問題にはならないのでしょうね。
スタックポインタSPは実質的に5 bitだけです。MC6805ではアキュムレータをスタックにプッシュしたりすることはできず、サブルーチン呼び出し時のPC退避と割り込み時の内部レジスタ退避しかスタックを利用しません。どうせROM容量も限られているわけですから、16レベルものサブルーチンネストが制限になることもないでしょうし、多重割り込みが複雑に絡み合うような応用に利用されることもないという判断の結果でしょう。
プログラムカウンタPCは11 bit幅と図にはありますが、ROM容量などが増強されたモデルでは、メモリアクセスに必要なだけのビットが付け加えられています。
コンデションコードレジスタCCRからはMC6800と比べてオーバーフローフラグが省略されています。下からキャリーC、ゼロZ、ネガティブN、割り込みマスクI、ハーフキャリーHとなっています。
レジスタメモリ操作の命令はこのくらいあります。
意味 ニーモニック IMMED DIRECT EXTEND INDEX0 INDEX8 INDEX16 動作 Load A from Memory LDA A6 2 2 B6 4 2 C6 5 3 F6 4 1 E6 5 2 D6 6 3 M -> A Load X from Memory LDX AE 2 2 BE 4 2 CE 5 3 FE 4 1 EE 5 2 DE 6 3 M -> X Store A in Memory STA B7 5 2 C7 6 3 F7 5 1 E7 6 2 D7 7 3 A -> M Store X in Memory STX BF 5 2 CF 6 3 FF 5 1 EF 6 2 DF 7 3 X -> M Add Memory to A ADD AB 2 2 BB 4 2 CB 5 3 FB 4 1 EB 5 2 DB 6 3 A + M -> A Add Memory and C to A ADC A9 2 2 B9 4 2 C9 5 3 F9 4 1 E9 5 2 D9 6 3 A + M + C -> A Subtract Memory from A SUB A0 2 2 B0 4 2 C0 5 3 F0 4 1 E0 5 2 D0 6 3 A - M -> A Sub. M from A with B. SBC A2 2 2 B2 4 2 C2 5 3 F2 4 1 E2 5 2 D2 6 3 A - M - C -> A AND Memory to A AND A4 2 2 B4 4 2 C4 5 3 F4 4 1 E4 5 2 D4 6 3 A & M -> A OR Memory with A ORA AA 2 2 BA 4 2 CA 5 3 FA 4 1 EA 5 2 DA 6 3 A | M -> A EOR Memory with A EOR A8 2 2 B8 4 2 C8 5 3 F8 4 1 E8 5 2 D8 6 3 A ^ M -> A Compare A with Memory CMP A1 2 2 B1 4 2 C1 5 3 F1 4 1 E1 5 2 D1 6 3 A - M Compare X with Memory CPX A3 2 2 B3 4 2 C3 5 3 F3 4 1 E3 5 2 D3 6 3 X - M Bit Test Memory with A BIT A5 2 2 B5 4 2 C5 5 3 F5 4 1 E5 5 2 D5 6 3 A & M Jump unconditional JMP BC 3 2 CC 4 3 FC 3 1 EC 4 2 DC 5 3 Addr -> PC Jump to Subroutine JSR BD 7 2 CD 8 3 FD 7 1 ED 8 2 DD 9 3 PC -> (SP--), Addr -> PC
アドレッシングモードがM6800と少々異なっています。イミディエート、ダイレクト、エクステンドは共通ですが、インデックスアドレッシングにオフセットなし(INDEX0)、8 bitオフセット(INDEX8)、16 bitオフセット(INDEX16)の3種類のモードが存在します。
各アドレッシングモードごとに3組の数字が記入されていますが、最初のものが命令のバイナリコードで、中央が実行クロック数、最後がその命令のバイナリコードのバイト数ということになります。
バイナリコードを観察すると、各アドレッシングモードごとに上位4 bitが決まっていて、$A0 - $FFの範囲のコードが使われていることがわかります。バイナリコードの下位4 bitは命令の種類を表していて、上記の表に含まれる命令が16種類あることからも、16種類のすべての4 bitの組み合わせが利用されていることがわかります。
次はリードモディファイライト命令について。
意味 ニーモニック INH(A) INH(X) DIRECT INDEX0 INDEX8 動作 Increment INC 4C 4 1 5C 4 1 3C 6 2 7C 6 1 6C 7 2 Opr + 1 -> Opr Decrement DEC 4A 4 1 5A 4 1 3A 6 2 7A 6 1 6A 7 2 Opr - 1 -> Opr Clear CLR 4F 4 1 5F 4 1 3F 6 2 7F 6 1 6F 7 2 0 -> Opr Complement COM 43 4 1 53 4 1 33 6 2 73 6 1 63 7 2 !Opr -> Opr Nagate NEG 40 4 1 50 4 1 30 6 2 70 6 1 60 7 2 - Opr -> Opr Rotate Left Thru Carry ROL 49 4 1 59 4 1 39 6 2 79 6 1 69 7 2 ROL(Opr) Rotate Right Thru C ROR 46 4 1 56 4 1 36 6 2 76 6 1 66 7 2 ROR(Opr) Logical Shift Left LSL 48 4 1 58 4 1 38 6 2 78 6 1 68 7 2 LSL(Opr) Logical Shift Right LSR 44 4 1 54 4 1 34 6 2 74 6 1 64 7 2 LSR(Opr) Arithmetic Shift Right ASR 47 4 1 57 4 1 37 6 2 77 6 1 67 7 2 ASR(Opr) Test for Negate/Zero TST 4D 4 1 5D 4 1 3D 6 2 7D 6 1 6D 7 2 Opr - 0
このグループの命令はバイナリコードの上位4 bitが3から7の間にすべて含まれています。
INH(A)はアキュムレータへの操作を意味し、INH(X)はインデックスレジスタへの操作を意味します。また16 bitオフセットのインデックスアドレッシングは利用できません。0ページの256 Byteの範囲にしか書き込み可能なRWMとかI/Oポート用レジスタが配置されていませんから、当然といえば当然ですけれど。ROMの固定データに対してこれらの命令を実行しようとしても、書き込みができないので使えません。そのため、0ページ範囲をアクセスするのに必要なだけのアドレッシングモードしか用意されていません。
次はブランチ命令です。すべてプログラムカウンタ相対アドレッシング専用命令です。
意味 ニーモニック REL 条件 Branch Always BRA 20 4 2 常に分岐 Branch Never BRN 21 4 2 常に分岐せず(2 Byte NOP命令) Branch If Higher BHI 22 4 2 C + Z = 0 Branch If Lower or Same BLS 23 4 2 C + Z = 1 Branch If Carry Clear BCC 24 4 2 C = 0 (BHS: Higher or Same) Branch If Carry Set BCS 25 4 2 C = 1 (BLO: Lower) Branch If Not Equal Zero BNE 26 4 2 Z = 0 Branch If = Zero BEQ 27 4 2 Z = 1 Branch If HC Clear BHCC 28 4 2 H = 0 Branch If Half Carry Set BHCS 29 4 2 H = 1 Branch If Plus BPL 2A 4 2 N = 0 Branch If Minus BMI 2B 4 2 N = 1 Branch If IM Clear BMC 2C 4 2 I = 0 Branch If IM Set BMS 2D 4 2 I = 1 Branch If Int. Line Low BIL 2E 4 2 INT* = L Branch If Int. Line High BIH 2F 4 2 INT* = H Branch to Subroutine BSR AD 8 2 動作: PC -> (SP--), PC += offset
最後のだけがサブルーチン呼び出しで特別な動作をしますが、他は条件分岐命令です。バイナリも条件分岐命令は$2xの形式になっていますが、BSR命令だけJSR命令のイミディエートアドレッシング相当の$ADというコードが割り当てられています。
原則的にM6801と同一の命令ですが、オーバーフローフラグVが削除されているので符号付き比較などオーバーフローフラグが判定条件に含まれる命令が削除され、代わりに別の条件分岐命令が加えられています。
まず、ハーフキャリーの状態を判定するBHCC/BHCS命令があります。M6805では、BCD演算を行うためのDAA命令がありません。そのため、どうしてもBCD演算を行う場合、これらの命令を用いてDAA命令と同じことを数命令のコードで実現しなくてはなりません。
次に割り込みマスクの状態を判定する命令が追加されています。M6805ではCCRの内容をアキュムレータに転送するような命令はなく、条件分岐命令以外でCCRの各ビットの状態を調べることは事実上できません。それで追加されたのでしょう。
最後に割り込み要求入力INT*端子の状態を判定する命令が追加されています。割り込み禁止状態にしておいて、この命令でINT*端子の状態を調べることによって、INT*端子も1 bitの入力ポートとして利用できます。
M6805で新設されたビット操作命令は、次の4種類です。
意味 ニーモニック SPECIAL 動作 Branch if Bit n is set BRSET 0000nnn0 10 3 指定ビットが1なら分岐 Branch if Bit n is clear BRCLR 0000nnn1 10 3 指定ビットが0なら分岐 Set Bit n BSET 0001nnn0 7 2 指定ビットを1にする Clear Bit n BCLR 0001nnn1 7 2 指定ビットを0にする
今までの表と異なり、オペコード欄は2進数で表現されています。
これらの命令では、メモリ空間のゼロページ内に含まれる特定のビットを操作します。ビット番号はオペコード内のビット1からビット3、表のオペコードでnnnとなっている場所に埋めこまれます。ゼロページアドレッシングに使われる8 bitのオペランドが第2 Byteに配置されます。BRSET, BRCLRは条件分岐命令の一種で、飛び先を指定する符号付き8 bitオペランドは命令コードの最後の第3 Byteに配置されるようになっています。
BSET, BCLR命令はフラグにまったく影響を与えませんが、BRSET, BRCLR命令は命令実行の副作用として、判定対象のビットをCフラグに格納します。そのため、飛び先をBRSET, BRCLR命令の次の命令に指定しておいて、単なるビットロード命令としても利用できます。うまく使えばソフトウェアでシリアル通信の受信を行うような場合に利用できます。
このグループの命令の上位4 bitは0か1に決まっています。
最後に制御命令を列挙します。すべてインヘレントアドレッシングの1 Byte命令です。
意味 ニーモニック INHER 動作 Transfer A to X TAX 97 2 1 A -> X Transfer X to A TXA 9F 2 1 X -> A Set Carry Bit SEC 99 2 1 1 -> C Clear Carry Bit CLC 98 2 1 0 -> C Set Interrupt Mask SEI 9B 2 1 1 -> I Software Interrupt SWI 83 11 1 Push all registers, (SWI vector) -> PC Return from Subroutine RTS 81 6 1 (++SP) -> PC Return from Interrupt RTI 80 9 1 Pull all registers Reset Stack Pointer RSP 9C 2 1 $1F -> SP NO-Operation NOP 9D 2 1 Do nothing
あまり珍しい命令はありませんが、RSP命令だけは少し注釈が必要でしょうか。
M6805ではスタック領域を任意のメモリアドレスに配置することはできません。スタックアクセス時の下位5 bitだけがスタックポインタから供給され、それ以外の上位ビットは固定されています。おまけにスタックに退避されるのはサブルーチン呼び出し時の戻りアドレスか割り込み時の内部レジスタ情報に限定されて、プログラマが任意の一時データやレジスタを格納することはできません。そのため、スタックポインタをインデックスレジスタに転送して何かの処理を行うような場面が生じることもなく、スタックポインタ操作命令はほとんどありません。普通はリセット時に自動的に行われるスタックポインタ初期化で$1Fがスタックポインタにロードされるのを利用して、あとはスタックポインタの値をプログラマが操作することはありません。どうしてもスタックポインタを初期化したい場合に限り、RSP命令で初期化しなおすことができます。
このグループの命令の上位4 bitは8か9に限定されています。
以上で全命令を紹介しおえたことになります。
概して、オペコードの上位4 bitを調べるだけで命令種別とアドレッシングモードが確定するようになっている、シンプルな命令体系です。
なお、CMOS版チップでは、スリープモード制御のために制御命令に2命令が追加されていたりします。レジスタメモリ操作命令、ブランチ命令、ビット操作命令のオペコード領域はすべてのコードに命令が割り当てられていますが、リードモディファイライト命令と制御命令には、まだ命令未割り当てのコードがたくさん残っています。スリープモード制御命令は、もちろん制御命令の一種としてコードが割り当てられています。