2020-01-07 22:45 — asano
6502系のプロセッサは何度にもわたって命令の追加が行われています。ほぼピン互換のものだけでも次のような種類のものが存在します。
- NMOS 6502
オリジナルです。 - CMOS 65C02
上をCMOS化したもので無条件ブランチ(BRA
)・インデックスレジスタの保存・復帰などの命令が追加されました。既存の命令でもアドレッシングモードが追加されたものがあります。 - CMOS 65C02(Rockwell, Ricohなど)
さらにビット操作(SMB
,RMB
)・ビット判定分岐(BBR
,BBS
)の命令が追加されました。 - CMOS 65C02(WDC)
さらに停止(STP
)・割込待ち(WAI
)の命令が追加されました。
ピン互換の無いものも含めるとさらに以下のようなものもあります。
- RP2A03
ファミリーコンピュータに使用されたものでBCD演算機能が省かれています。他にサウンド機能やDMA機能などが追加されています。 - 65C816
メモリ空間が16MBに拡張され、アキュムレータ・インデックスレジスタも16ビットに拡張されました。他にも多くの変更点があります。 - HuC6280
PCエンジンに使われたものです。 - MELPS740
三菱電機が組み込み用に拡張したものです。
これ以外にも6502を祖先に持つものは存在します。
ここでは比較的入手しやすい1~4を判別することにします。いつものようにUniversal Monitorの該当部分です。
56/ F836 : =>TRUE IF USE_IDENT
57/ F836 : 80 0D FCB $80,ID65C-*-2 ; BRA ID65C on 65C02, NOP #xx on 6502
58/ F838 : ;; 6502
59/ F838 : A9 1E LDA #low(IM65)
60/ F83A : 85 27 STA PT0
61/ F83C : A9 FD LDA #high(IM65)
62/ F83E : 85 28 STA PT0+1
63/ F840 : A9 00 LDA #$00
64/ F842 : 4C 62 F8 JMP IDE
65/ F845 : ;; 65C02
66/ F845 : ID65C:
67/ F845 : 0F A9 10 FCB $0F,$A9,IDR65C-*-3 ; BBR0 $A9,IDR65C on R65C02, NOP / LDA,#xx on 65C02
68/ F848 : 8F A9 0D FCB $8F,$A9,IDR65C-*-3 ; BBS0 $A9,IDR65C on R65C02, NOP / LDA,#xx on 65C02
69/ F84B :
70/ F84B : A9 25 LDA #low(IM65C)
71/ F84D : 85 27 STA PT0
72/ F84F : A9 FD LDA #high(IM65C)
73/ F851 : 85 28 STA PT0+1
74/ F853 : A9 01 LDA #$01
75/ F855 : 4C 62 F8 JMP IDE
76/ F858 : ;; R65C02
77/ F858 : IDR65C:
78/ F858 : A9 2D LDA #low(IMR65C)
79/ F85A : 85 27 STA PT0
80/ F85C : A9 FD LDA #high(IMR65C)
81/ F85E : 85 28 STA PT0+1
82/ F860 : A9 03 LDA #$03
83/ F862 : IDE:
84/ F862 : 85 1B STA PSPEC
85/ F864 : 20 B9 FB JSR STROUT
86/ F867 : [56] ENDIF
まず57行目、80
,xx
はCMOSの65C02(2, 3, 4)ではBRA
(無条件ブランチ)命令です。それではNMOSの6502ではどう解釈されるのでしょう?
6502.org Tutorials: 65C02 Opcodes(下のリンク参照)によると2バイトのNOP
とのことです。試しにメモリに80
,00
,00
,00
と書き込んで実行してみます。00
はBRK
命令なのでブレーク時のPC
の値からどの00
でブレークがかかったかを見れば80
が何バイト命令であったかがわかります。
やってみると2つ目の00
でブレークがかかったので2バイト命令です。
これだけではNOP
なのかディスプレースメントが0のブランチなのか不明なので80
,01
,00
,00
を試してみます。
さらに条件分岐命令ではないのかなど疑うこともできますが、キリが無いのでこれ以上は上述の資料を信じることにします。
つづいてCMOS 65C02のうち2と3,4を識別します。67行目の時点で2,3,4のいずれかであることはわかっていますので、3で追加された命令を利用します。
NOP
とされ、命令長もデータシートに記載されていますので安心して利用できます。
これは大きく分けて2通りの方法が考えられます。
SMB
,RMB
命令でビットが変化することをチェックするBBR
,BBS
命令で分岐するかチェックする
いずれの場合もビット変更・判定の対象となるのはゼロページです。
a.の命令は2バイト長で2バイト目はアドレスなのですが、非対応の2では1バイト長のNOP
なので、2バイト目(ゼロページのアドレス)の値は1バイト長で害の無い命令のオペコードである必要があります。
b.の命令は3バイト長で2バイト目はアドレス・3バイト目は分岐のディスプレースメントになりますが、2ではやはり1バイト長のNOP
なので、ゼロページのアドレスの値は2バイト長で害の無い命令(あるいはアドレスとディスプレースメントともに1バイト長で害の無い命令)のオペコードである必要があります。
ゼロページの特定のアドレスを変更する必要があるというのはちょっと使いにくいですね。
NOP
を置けば命令長の条件は緩和できますが、任意のアドレスが使えるわけではありません。
それで思いついたのがこの67,68行目です。BBR
, BBS
命令が有効であればアドレスA9
に何が書かれていてもどちらかの条件は満たすのでIDR65C
に分岐します。無効であればA9
,xx
はLDA #xx
と解釈され、そのまま下へ流れ落ちます。
Universal Monitorでは割込みを使っていませんが、割り込みルーチンでアドレスA9
の内容を書き換えると判別に失敗する可能性があります。ビット0が"1"だと67行目で分岐せず、その直後の割込みでビット0が"0"に書き換えられると次の68行目でも分岐しません。
次は3と4の判別なのですが、実はまだうまい(汎用な)方法を見つけられていません。4で追加された命令はどちらもプロセッサが止まってしまう命令なので使えないのです。まぁ逆に言うと区別する必要もあまり無いのですが....
最後に確認状況について、1はSY6502A, UM6502, UM6502Aで、3はRP65C02Gで行ないました。2はNCR65C02を手配中でまだ確認できていません。4も入手していたW65C02S8P-10が偽者だったようで動作せず、やはり手配中です。
コメント
6502/65816系の判別ルーチン発見
6502/65816 CPU variant detection code
http://forum.6502.org/viewtopic.php?f=2&t=2263
というページを見つけましたが、ここでも Rockwell R65C02 と WDC W65C02 の判別はしていない(できてない)様です。
ただ、他のバリアントとの判別は細かくできる様ですので、御参考になるかと思います。
Re: 6502/65816系の判別ルーチン発見
情報ありがとうございます。
やはりRockwellとWDCは識別不能なんですね。
コメントを追加