MCS6502の特徴としては次のようなものがあります。8 bitプロセッサにしては珍しかった各種間接アドレッシングを使えたこと。CPU内のレジスタはほとんど8 bit化して、スタックポインタまで8 bitにしてしまい、$0100から$01FFのアドレス範囲にしかスタックを配置できないというような思い切ったハードウェアの簡略化(ここでは16進数表記に$の記号を前置する)。相対分岐命令で飛び先を下位8 bitから順番に計算する際、上位8 bitに桁上がりの影響がないと判定した時点で先に進める(後で詳細を書きます)といった高速化の工夫が行われていること。ADD命令がなく、ADC命令で代用するなど、命令の思い切った簡略化。
上はMOS Technology社のMPS6502、下はSynertek社のSY6502。SY6502はこのほかに林義信様よりいただいたものがあります。MOS Technology社はパッケージ種別をプリフィックスの第2文字で表示していて、セラミックパッケージがMCS、プラスチックパッケージはMPSとなります。
CMOS化された65C02にはビット操作命令など、追加された命令がいくつも存在します。そのため、MCS6502の未定義命令を使用していたプログラムは動作しません。
MC6800と異なり、アキュムレータが1本になっている代わりにインデックスレジスタが2本になっています。このXとYのインデックスレジスタはアドレッシングにおいて異なる機能を持ちますから、注意してください。詳細はアドレッシングモードの解説で。プログラムカウンタPCが16 bit幅なのはよいとして、インデックスレジスタもスタックポインタも8 bit幅です。インデックスレジスタはポインタとして使用することはできません。16 bitのアドレス定数を修飾するレジスタくらいの役割になります。問題はスタックポインタで、8 bit幅しかないので、16 bitアドレスの全メモリ空間の任意の場所を指すわけにはいきません。スタックは1ページ内に限定されています。つまり、スタック領域の上位8 bitは$01に限定されています。16進数で$0100から$01FFまでの間の空間だけがスタックとして使用できるのです。
フラグ類を集めたレジスタをMC6800ではコンデションコードレジスタ(CCR)と呼びましたが、MCS6502ではプロセッサステータスレジスタ(PSR)と呼びます。このレジスタのフラグのようすもMC6800とは異なります。ただ、NはネガティブでVがオーバーフロー、Iが割り込みマスクでZがゼロフラグというあたりは、ビット位置が異なっても意味はMC6800と同じです。Cはキャリーフラグで、一見MC6800と同じですが、減算のときには桁借りがあったときに0で桁借りがなかったときに1になります。これはMC6800と逆になっていますから、注意しなくてはなりません。比較命令も減算の一種ですから、条件分岐命令の使い方がMC6800と異なります。減算のときにキャリーフラグの意味が逆になるCPUには、他にもMicrochip社のPICシリーズなんかがあります。ややこしそうですが、まぁ慣れですね。BはBRKフラグで、割り込み原因がソフトウェア割り込みのBRK命令であったかIRQ割り込み信号によるものかの識別に使います。この2種類の割り込みは、割り込みベクタが異なれば問題なかったのですが、なぜか同じ割り込みベクタを共用しているので、識別用のフラグが新設されたというわけです。最後に残ったDフラグは10進数演算モードを表すデシマルフラグです。MC6800にあったハーフキャリーフラグがないことに気付いているかもしれませんが、さらにMCS6502にはDAA命令もありません。それではBCD演算ができないみたいですが、あっと驚く方法でBCD演算を可能にしています。それが、このDフラグです。Dフラグが0のときには、加減算を行うADC命令やSBC命令で2進数演算が普通に行われます。ところがDフラグを1にセットしてあると、自動的にADC命令やSBC命令でBCD演算が行われるようになっているのです。減算でBCD演算が可能というだけでMC6800より強力ですが、たとえば複数バイトの加算サブルーチンがあったとして、そのサブルーチンをDフラグを1にセットしてから呼び出すだけで、複数桁のBCD加算サブルーチンとして利用可能になってしまうということになります。なかなか強力そうな機能です。しかし、リセット時の状態は不定ですし、割り込みサービスルーチンの中の演算も注意しないとメインルーチンで設定されているDフラグの状態によって影響を受けますから、充分に注意が必要な機能です。
アドレッシングモードは相当に増えています。イミディエートアドレッシング、ゼロページアドレッシング(MC6800のダイレクトアドレッシング)、アブソリュートアドレッシング(MC6800のエクステンドアドレッシング)、インプライドアドレッシングとアキュムレータアドレッシング(どちらもMC6800ではインプライドアドレッシングに分類)はMC6800と名称は異なっていても同一です。ただし、アブソリュートアドレッシングの16 bitアドレス指定はMC6800がオペコードの後にアドレス上位、アドレス下位と並んで配置されていたのに対し、MCS6502ではオペコードの後にアドレス下位、アドレス上位の順になっていて、8080Aなどと同一の並びになっています。
インデックスアドレッシングはMC6800では16 bitのインデックスレジスタを8 bitオフセットで修飾するモードしかありませんでしたが、MCS6502ではずっと複雑になっています。まずアブソリュートXとアブソリュートYは16 bitのオペランドアドレスを8 bitのインデックスレジスタで修飾するモードです。3 Byte命令になるし、インデックスレジスタは255までのオフセット分しか修飾できません。次はゼロページXとゼロページYアドレッシングモード。これはオペランドの内容とインデックスレジスタの内容を加えたゼロページ内のメモリにアクセスするモードです。かりに9 bit目にキャリーが発生しても、$100以上のアドレスにアクセスするわけではなく、アドレス上位1 Byteは0に固定されたままです。一般にゼロページXしか使えませんが、LDXとSTX命令に限っては、Xの内容を操作するのにゼロページXでは不便ですから、ゼロページXの代わりにゼロページYアドレッシングが使えるようになっています。この後の二つの間接アドレッシングは複雑になっています。ひとつはインデックス修飾の間接アドレッシングで、ゼロページXアドレッシングをまず行い、そのアドレスから始まるメモリ2 Byteの内容の値を操作対象アドレスと解釈します。ゼロページX間接とも表現します。ゼロページに複数のポインタを用意しておき、それをXレジスタで切り替えることができるモードです。もうひとつが間接アドレッシングのインデックス修飾です。まずゼロページアドレッシングを行い、そのゼロページメモリから2 Byteの値を取得します。それをYレジスタでインデックス修飾します。こちらは簡単にはゼロページ間接Yと表現します。ゼロページ領域内に複数のインデックスレジスタを用意しておきたい場合に使えます。ただし、特定の命令で使用するインデックスレジスタはゼロページアドレッシングで固定される点がXレジスタを使用するゼロページX間接と異なります。
条件分岐系の命令ではMC6800と同じように相対アドレッシングを使用します。JMP命令とJSR命令はアブソリュートアドレッシングが基本ですが、JMP命令にだけは間接アドレッシングが使えて、オペランドとして16 bitアドレスを使用し、そのアドレスから始まる2 Byteのデータが示すアドレスにジャンプします。
概して、チップ上からは16 bitポインタが消えてしまいましたが、その分の16 bitポインタをゼロページ上に多数用意できるアドレッシングモードが用意されているのが特徴です。MC6800では16 bitポインタ(インデックスレジスタ)が1本しかなく、その退避や復旧回数がやたら多くなってしまってプログラム速度が低下してしまったのと比べると、チップ面積を小さくできる上に高速化できます。もう少し具体的に考えてみましょうか。2ヶ所以上のメモリロケーションに取られた連続データへの操作(たとえばメモリコピーや文字列比較など)の場合、同じインデックスレジスタを続けて2回使用するなんてことはあまりありません。1ヶ所のデータにアクセスしたら、すぐに別のメモリロケーションのデータを参照して何かの作業を行うというほうが普通です。すると、MC6800ではインデックスアドレッシングを使用するたびに、どこかにインデックスレジスタを保存して、別のポインタをインデックスレジスタにロードしなくてはなりません。そんなことなら、MCS6502でゼロページ間接Yアドレッシングを使用した方が、インデックスレジスタのストアやロード命令が不要になる分、コードが短く高速になってしまうというわけです。
命令の名称や雰囲気は、比較的MC6800に似ています。
以下にアキュムレータを中心とした演算命令を並べます。
表のMNE.はニーモニック、IMMはイミディエートアドレッシングモード、ABSはアブソリュートアドレッシング、ZEROはゼロページ、ACCはアキュムレータ、I.XはゼロページX間接、I.Yはゼロページ間接Y、Z.XはゼロページX、A.XはアブソリュートX、A.YはアブソリュートYの各アドレッシングモードを意味します。NZCVはそれぞれフラグ変化を示すもので、命令実行によって変化するものには*を、変化しないものには空白を書き込んであります。命令の各カラムの16進数2桁と数字1桁は、16進数2桁が機械命令のバイナリコードを、数字1桁が実行に要するクロック数を表します。ただし、インデックス修飾によってアドレス下位8 bitから上位に桁上がりがある場合は、さらにもう1クロックが必要とされます。これは、桁上がりの有無に関らず下位8 bit分のアドレス計算を行った時点で、そのアドレスから内容を読み出しておき、桁上がりがなければそのデータを使用して演算を続け、桁上がりがあった場合には先に読み取ったデータを破棄して次のクロックで正しいアドレスからデータを読み込むという、一種の投機的先読みを行っているためです。
MNE. IMM ABS ZERO ACC I.X I.Y Z.X A.X A.Y NZCV 動作 ADC 69 2 6D 4 65 3 61 6 71 5 75 4 7D 4 79 4 **** A + M + C -> A AND 29 2 2D 4 25 3 21 6 31 5 35 4 3D 4 39 4 ** A & M -> A BIT 2C 4 24 3 ** * A & M CMP C9 2 CD 4 C5 3 C1 6 D1 5 D5 4 DD 4 D9 4 *** A - M EOR 49 2 4D 4 45 3 41 6 51 5 55 4 5D 4 59 4 ** A eor M -> A LDA A9 2 AD 4 A5 3 A1 6 B1 5 B5 4 BD 4 B9 4 ** M -> A ORA 09 2 0D 4 05 3 01 6 11 5 15 4 1D 4 19 4 ** A | M -> A SBC E9 2 ED 4 E5 3 E1 6 F1 5 F5 4 FD 4 F9 4 **** A - M - not C -> A STA 8D 4 85 3 81 6 91 6 95 4 9D 5 99 5 A -> M ROR 6E 6 66 5 6A 2 76 6 7E 7 *** ASL 0E 6 06 5 0A 2 16 6 1E 7 *** LSR 4E 6 46 5 4A 2 56 6 5E 7 *** ROL 2E 6 26 5 2A 2 36 6 3E 7 *** INC EE 6 E6 5 F6 6 FE 7 ** M + 1 -> M DEC CE 6 C6 5 D6 6 DE 7 ** M - 1 -> MMC6800だと、このグループに属する命令は27種類ありますが、MCS6502では15種類と、ほぼ半分になっています。アキュムレータのインクリメントやデクリメントもできず、キャリーを無視した加減算もありません。クリアやビット反転、符号反転などの命令も省略されています。BCD補正命令もありませんが、これはもちろん先に説明したようにDフラグによってADC命令とSBC命令の動作モードが変化するためです。
MNE. IMM ABS ZERO Z.X A.X A.Y Z.Y NZCV 動作 LDX A2 2 AE 4 A6 3 BE 4 B6 4 ** M -> X LDY A0 2 AC 4 A4 3 B4 4 BC 4 ** M -> Y CPX E0 2 EC 4 E4 3 *** X - M CPY C0 2 CC 4 C4 3 *** Y - M STX 8E 4 86 3 96 4 X -> M STY 8C 4 84 3 94 4 Y -> M間接系のアドレッシングモードがありません。Z.YはゼロページYアドレッシングモードを意味します。XのロードやストアにはXを使ったアドレッシングモードではなく、Yを使ったアドレッシングモードになるというのは、合理的でしょう。比較系の命令では、インデックスレジスタでアドレス修飾を行うモードが使えません。
MNE. IMP NZCV 動作 INX E8 2 ** X + 1 -> X INY C8 2 ** Y + 1 -> Y DEX CA 2 ** X - 1 -> X DEY 88 2 ** Y - 1 -> Y TAX AA 2 ** A -> X TAY A8 2 ** A -> Y TSX BA 2 ** S -> X TXA 8A 2 ** X -> A TXS 9A 2 X -> S TYA 98 2 ** Y -> AINX, INY, DEX, DEYはインデックスレジスタのインクリメントとデクリメント。きちんとZフラグも変化しますから、ループの終了条件にも使えます。
MNE. IMP 動作 CLC 18 2 0 -> C CLD D8 2 0 -> D CLI 58 2 0 -> I CLV B8 2 0 -> V SEC 38 2 1 -> C SED F8 2 1 -> D SEI 78 2 1 -> I PHA 48 3 A -> M(S--) PHP 08 3 P -> M(S--) PLA 68 4 M(++S) -> A PLP 28 4 M(++S) -> PCL*という命令はフラグのクリアで、SE*命令がフラグのセットです。キャリーのセットやリセットはMCS6502では加減算の際に必要となりますし、DレジスタもBCD演算と2進数演算を切り替えるためにセットやリセットが必要です。割り込みマスクのIレジスタも命令によって値を変更する必要がありますね。ところが、Vフラグに関してはクリアするCLV命令があるのにセットするSEV命令というのがありません。これは、ハードウェアで説明するSO端子を使用するために必要な命令で、クリアは必要だけれどもセットする必要が無いからです。SO端子のネガティブエッジでオーバーフローフラグが強制的にセットされます。これを検出して条件分岐できますが、次のエッジを検出するためには前もってリセットしておかなくてはなりません。そのための命令です。
MNE. REL 条件 BCC 90 2 C = 0 BCS B0 2 C = 1 BEQ F0 2 Z = 1 BMI 30 2 N = 1 BNE D0 2 Z = 0 BPL 10 2 N = 0 BVC 50 2 V = 0 BVS 70 2 V = 1条件判定用のフラグがPSRに4種類ありましたから、それぞれが0か1かという条件で、計8種類の条件分岐命令があります。MCS6502では相対アドレッシング(表ではRELと表記)を使用する命令が、この条件分岐命令しかありません。無条件分岐とか、サブルーチン呼び出しに相対アドレッシングを使うことはできないのです。
MNE. IMP ABS IND 動作 NOP EA 2 PC++ JMP 4C 3 6C 5 Addr -> PC JSR 20 6 PC -> (SP--), Addr -> PC RTI 40 6 (++SP) -> PSR, (++SP) -> PC RTS 60 6 (++SP) -> PC BRK 00 7 1 -> B, PSR -> (SP--), PC -> (SP++), (VEC) -> PCNOP命令には説明が不要でしょう。ただし、半端なコードが割り当てられています。JMP命令は16 bitアドレス空間の任意の位置にジャンプできますし、16 bitアドレスで示されたメモリから2 Byteを読み込んで、そのアドレスにジャンプする間接アドレッシングモード(IND)も使用できます。MCS6502では無条件のジャンプはJMP命令しか存在しません。相対アドレッシングの無条件分岐はありません。そこは少々不便かもしれませんが、ADD命令すら省略する設計ですから、しょうがないでしょうね。JSR命令もおきまりのサブルーチンジャンプで、リターンアドレスをスタック上にプッシュしてからジャンプするものです。アブソリュートアドレッシングしか使えません。JSR命令と対になって使用されるリターン命令がRTS (Return from Subroutine)命令です。
ソフトウェアの観点からの類似性ばかりでなく、ハードウェア自身もMC6800の類似が指摘されています。というより、ハードウェアの方の類似性の方が高いといえるでしょう。ほぼ同じタイミングの同期バスを採用していて、メモリや入出力デバイスの設計を簡単に流用できたりしますが、その上にピン配置までMC6800と似ています。
具体的にはピン配置はこうなっています。MC6800と比べてみてください。
GND 1 40 RES* RDY 2 39 CK2 CK1 3 38 SO IRQ* 4 37 CK0 NC 5 36 NC NMI* 6 35 NC SYNC 7 34 R/W* VCC 8 33 DB0 AB0 9 32 DB1 AB1 10 31 DB2 AB2 11 30 DB3 AB3 12 29 DB4 AB4 13 28 DB5 AB5 14 27 DB6 AB6 15 26 DB7 AB7 16 25 AB15 AB8 17 24 AB14 AB9 18 23 AB13 AB10 19 22 AB12 AB11 20 21 GND
Motorola社との表記の違いでVSSがGNDになっていたり、アドレスやデータのA0やD7がAB0やDB7なんてふうになっていますが、アドレスバスとデータバス、電源、割り込み信号や制御信号のかなりの部分が同一であることがわかります。違いがあるのは、クロック信号の発振回路が内蔵になっているためクロック関係の信号と、DMAの仕組みがなくなっている(RDY信号で外部回路付加によって実現可能)部分、SO入力の部分だけです。SO入力信号はSet Overflow Flagという意味で、立ち下がりでオーバーフローフラグがセットされます。1 bitの入力ポートとして使えますが、まぁ良い子は使わずにプルアップしておくでしょうねぇ。SYNCは8080やZ80 CPUのM1と同じ意味の信号で、命令のオペコードをフェッチしていることを表します。
VMA信号が存在しないのもMC6800と比べると変わっているところでしょうか。他のプロセッサに慣れ親しんだ方からすると相当に気持ち悪いでしょうが、MCS6502ではクロックに同期して、必ずメモリアクセスを行います。仮に命令を内部で解釈実行している時間ですら、メモリ側から見ればクロックに同期してまったく同じ読み書きの信号が出力され続けています。無効なメモリアクセスサイクルであることを示す信号が存在しないのですから、区別が付きません。無効な書き込みが行われるのは、INCやROR命令などのリードモデファイ形式、つまりあるメモリアドレスからデータを読み込んで加工を行い、同一アドレスに書き戻すような命令で、正しく加工されたデータを書き込む直前に、同じアドレスにでたらめなデータを書き込む場合にしか、行われません。対象がメモリなら最終的に書き込まれた値しか残りませんから影響はないというわけです。他の不要なメモリアクセスは読み込みばかりで、命令実行中にプログラムカウンタやインデックスレジスタ操作が不完全なままのアドレスから読み出すものです。命令の解説に少々注意した通りです。
相手がメモリならどこを何回読み込もうと問題はありませんが、I/Oポートでアクセスに応じてフラグが変化するようなものに不要なアクセスが行われると、困ってしまいます。対策としては、I/Oポートを特定のページに集めて、I/Oと同じページにメモリを配置しないようにハードウェア設計しておき、I/Oポートへのアクセスにはアブソリュートアドレッシングを必ず用いることとリードモデファイ形式の命令を用いてI/O操作を行わないというソフトウェア面での注意を徹底することが必要です。
割り込み関係の信号はMC6800と同じようにRES*, NMI*, IRQ*の3本があり、ソフトウェア割り込みを起こすMC6800のSWI命令に相当するBRK命令も備えています。
これらの要因で割り込みが発生すると、割り込みベクタを参照します。ベクタは要因ごとに次のようなアドレスに格納されることになっています。
割り込み要因 | ベクタアドレス |
IRQ, BRK | FFFE, FFFF |
RES | FFFC, FFFD |
NMI | FFFA, FFFB |
ベクタはMCS6502のアドレスの最上位に位置しますが、細かい位置や順序はMCS6502とMC6800とで異なります。また、16 bitデータの格納順序の規則も異なっていますから、注意してください。MCS6502では下位バイトが常に小さなアドレスに配置されます。
RES*信号が有効にされてから規定の時間が経過後にHに戻されると、$FFFCから2 Byteのデータを読み込んでPCにロードします。そして、そのPCを用いて命令をフェッチしてプログラムの実行を始めます。IフラグはセットされてIRQ入力が禁止されますが、他のレジスタ類の初期化は行われません。値が不定の中にはDフラグもあって、リセット後に命令で初期設定しない限りADC命令やSBC命令を正しく実行できませんから、注意してください。
NMI*はエッジトリガの割り込み信号で、HからLへの遷移によって割り込みが発生します。Lレベルが長時間続いても、CPUの実行状態になんの影響も与えません。NMIが発生すると、Bフラグを0にしてPCとPSRをスタックにつみ、Iフラグを1にセットしてIRQを禁止して$FFFAから2 Byteのデータを取り出してPCに格納し、割り込みサービスルーチンの実行を開始します。アキュムレータやインデックスレジスタの退避は行われず、プログラマが保存や復帰の管理を行う必要があります。
IRQ*はレベルトリガの割り込み入力信号で、Iフラグが0のときにIRQ*がLレベルになっていれば割り込みが発生します。Bフラグを0にしてPCとPSRをスタックにつみ、Iフラグを1にセットしてそれ以上のIRQ割り込みの発生を禁止してから$FFFEからのデータをPCに格納して割り込みサービスルーチンに分岐します。
BRK命令はソフトウェア割り込みですが、Iフラグの状態に影響されないことと、PSRをスタックにつむ前にBフラグを1にセットすることだけがIRQと異なります。それ以外はまったくIRQと同じシーケンスで実行されます。割り込みベクタまで共通なので、IRQとBRK命令による割り込みは同一の割り込みサービスルーチンが呼び出されることになります。IRQとBRK命令の、どちらが原因で割り込みサービスルーチンが呼ばれたか、PSRのBフラグを調べて判定しなくてはなりません。直接PSRのBフラグによって条件分岐を行ったり、PSRのビットの状態を調べたりする命令は存在せず、アキュムレータにPSRの内容を転送してから判断しなければなりませんが、その転送命令もないので、PHP命令とPLA命令を続けて実行したりしてからAND命令でBフラグだけ残すようにして、やっと条件分岐することができるわけで、ちょっと面倒ですけどね。BRK命令については、さらに注意する点があります。BRK命令発生時にスタックにプッシュされるPCの値は、BRK命令の次のアドレスではなくて、さらにもうひとつ次のアドレスです。BRK命令実行後に割り込みサービスルーチンがRTI命令を実行して元の命令シーケンスを実行しはじめる際、BRK命令の次の1 Byteは無視されてしまいますから、気をつけてください。BRK命令の直後にはNOP命令でも挿入しておかないと、思わぬトラブルのもとになります。
RTI命令はスタックからPSRとPCを取り出して割り込み発生前の命令シーケンスの実行を継続する命令です。PLP命令とRTS命令でも同じようなことができそうですが、MCS6502ではJSR命令とRTS命令に変なクセというか、ある種の実装上の都合というか、ちょっと事情があって、PLP命令とRTS命令でRTI命令を置き換えることができないようになっています。3 ByteのJSR命令でスタックにプッシュされるアドレスは、JSR命令のアドレスに3を加えたものではなく、2を加えたアドレスになっています。RTS命令では、PCにスタックから取り出した値をロードしてから、余分に1回だけインクリメントして、正しいアドレスから命令が読み込めるようにしています。RTI命令ではその余分な1回のインクリメントが行われません。変な仕様ですが、JSR命令とRTS命令、割り込み類とRTI命令を、必ず対にして使用すれば不整合が起こり得ませんから問題ないといえば問題ないのですけどね。
MCS6502はRockwellによってCMOS化されましたが、同時に命令を追加し、ハードウェア的な問題点にも修正が入っています。
RockwellのR65C02の高速版。
まずは追加された命令です。既存の命令にアドレッシングモードが追加されているものと、新設された命令があります。アキュムレータ演算には、ゼロページ間接アドレッシングが使えるようになっています。また、BIT命令には待望のイミディエートアドレッシングが追加されています。INCとDECにはアキュムレータを対象とすることができるようになりました。以下では、追加した命令のオペコードとサイクル数の間にアスタリスク*を入れてあります。
MNE. IMM ABS ZERO ACC I.X I.Y Z.X A.X A.Y ZIND NZCV 動作 ADC 69 2 6D 4 65 3 61 6 71 5 75 4 7D 4 79 4 72*5 **** A + M + C -> A AND 29 2 2D 4 25 3 21 6 31 5 35 4 3D 4 39 4 32*5 ** A & M -> A BIT 89*2 2C 4 24 3 34*4 3C*4 ** * A & M CMP C9 2 CD 4 C5 3 C1 6 D1 5 D5 4 DD 4 D9 4 D2*5 *** A - M EOR 49 2 4D 4 45 3 41 6 51 5 55 4 5D 4 59 4 52*5 ** A eor M -> A LDA A9 2 AD 4 A5 3 A1 6 B1 5 B5 4 BD 4 B9 4 B2*5 ** M -> A ORA 09 2 0D 4 05 3 01 6 11 5 15 4 1D 4 19 4 12*5 ** A | M -> A SBC E9 2 ED 4 E5 3 E1 6 F1 5 F5 4 FD 4 F9 4 F2*5 **** A - M - not C -> A STA 8D 4 85 3 81 6 91 6 95 4 9D 5 99 5 92*5 A -> M INC EE 6 E6 5 1A*2 F6 6 FE 7 ** M + 1 -> M DEC CE 6 C6 5 3A*2 D6 6 DE 7 ** M - 1 -> MZINDと表記したゼロページ間接アドレッシングモードでは2 Byte命令となり、2 Byte目の8 bit値で指示されたゼロページ内のメモリから16 bitデータを取り出して、その値を実際のオペランドアドレスとして解釈します。
MNE. REL ABS IND IA.X 動作 BRA 80*3 Addr -> PC JMP 4C 3 6C 5 7C*6 Addr -> PC無条件相対分岐命令であるBRA命令が新設されています。以前になかったのが不思議なくらいでした。この命令は、必ず分岐しますから、最短の命令実行クロック数が3となっています。実際にはアドレスの桁上がりに応じて3ないし4クロック必要となります。また、JMP命令には特別なアドレッシングモードが追加されています。表ではIA.Xと表記していますが、アブソリュートX間接とでも表現すべきモードで、まずはアブソリュートXアドレッシングと同じようにアドレス計算を行い、そこから16 bitのデータを読み出して、その値をPCへとロードします。ジャンプテーブルを実装するのに便利なモードです。
MNE. IMP 動作 PHX DA 3 X -> M(S--) PHY 5A 3 Y -> M(S--) PLX FA 4 M(++S) -> X PLY 7A 4 M(++S) -> Yインデックスレジスタ類のプッシュプルでした。これでサブルーチン内とか割り込みサービスルーチン内でのインデックスレジスタ退避が楽になります。
MNE. ABS ZERO Z.X A.X NZCV 動作 STZ 9C 4 64 3 74 4 9E 5 0 -> M TRB 1C 6 14 5 * not A & M -> M TSB 0C 6 04 5 * A | M -> MSTZ命令はSTore Zeroの略ですね。TRB命令はTest and Reset Bits、TSB命令はTest and Set Bitsの略になっていて、アキュムレータで1が入っているビットに対応するメモリの複数のビットを操作します。
MNEMONIC ZERO 動作 BBR[0-7] [0-7]F 4 if M<b> = 0, branch BBS[0-7] [8-F]F 4 if M<b> = 1, branch RMB[0-7] [0-7]7 5 0 -> M<b> SMB[0-7] [8-F]7 5 1 -> M<b>
これらの命令はフラグに影響を与えません。BBRとBBS命令はBranch if Bit ResetとBranch if Bit Setという意味で、オペランドにゼロページと分岐先のラベルを取り、条件が満たされたときに相対アドレッシングで分岐します。RMB命令とSMB命令はReset Memory BitとSet Memory Bitの略で、特定のビットを1にしたり0にしたりするものです。
以上で65C02で追加された命令は終わりです。他に、問題点の修正が以下のように行われているようです。
ところで6502アーキテクチャは今でも受け継がれている流れがあります。たとえば、これ。
三菱のM37450の開発用窓付き8 KByte UVEPROM内蔵版のM37450E4SSと、少量生産用の窓なし8 KByte PROM版のM37450E4SP。
組み込み制御用の1チップマイクロコンピュータですが、6502にビット操作命令と乗算命令などを加えて強化したCPUアーキテクチャです。こちらの方が65C02より強化された命令セットになっています。アドレッシングモードも細かく分ければ17種類と増加しています。残念ながら、追加された命令パターンは65C02とは互換性がありません。同じようなビットのセット・リセット命令のコードも違えば、INC A, DEC Aのコードもしっかり異なっています。ちなみに、ほかに256 ByteのRWMにシリアルやパラレルポート、A/DやD/A、タイマに他のマイクロプロセッサがアクセスできるスレーブポートなど、至れり尽せりの入出力機能がセットになって、(少し古めのこの石でも)2.5 MHzクロックで動作し、わずかな消費電力と、なかなか使い出のあるチップでした。なお、これはすでに製造中止。ROMがぐんと増えて高速になったものなら手に入るかもしれません。でも、最初に紫外線消去可能なパッケージのを見たときには、ダイの大きさに驚いたなぁ。これで採算あってるのかな。
Return to IC Collection