標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第263回]
●RLC、RRC、RAL、RARのテストプログラムです
8本目のテストプログラムです。
今回はローテイト命令のテストプログラムです。
ローテイト命令というのはなかなかに面倒な命令です。
ADDとかSUBでしたら、Windows付属の電卓を16進数表示にして使えば簡単に計算結果を求めることができます。
しかしローテイトとなると、そうはいきません。
右回転と左回転の別に加えて、キャリーを含めて9ビットのローテイトまであるのですから、比較データを手計算で求めるのは容易ではありません。
これこそ、Z80で先に計算させるメリットが極めて大です。
幸いINR命令などと違い、ローテイト命令はC(キャリー)フラグ以外のフラグは変化しません。
[出典]Intel社8080User’s Manual
もちろんZ80でも同じです。
計算結果の値はちょっと手計算で求めるのは面倒ですからZ80にやってもらいますが、フラグはC(キャリー)フラグが変化するだけですから、フラグについては簡単です。
さっそくZBKボードでテストプログラムを実行し、その結果をもとにして比較データを作成しました。
先にZ80で実行した結果をもとにして作ったTEST8のプログラムリストです(こういう持って回ったような表現をするときは、大抵何か問題があるときなのです)。
2009/6/13 17:55 TEST8.TXT END=408C ;;; MYCPU80 TEST8 ;;; RLC RRC RAL RAR ;;; 09/6/13 ; ORG $4000 ; STCK=$5000 MWK=$5001 ERBF=$6000 ; 4000 310050 LXI SP,STCK 4003 0E00 MVI C,00 4005 C5 PUSH B 4006 F1 POP PSW;CLEAR FLAG REGISTER ; ; RLC 4007 0608 MVI B,08 4009 3E57 MVI A,57 400B 07 RLC1:RLC 400C F5 PUSH PSW 400D 05 DCR B 400E C20B40 JNZ RLC1 ; RRC 4011 0608 MVI B,08 4013 3E57 MVI A,57 4015 0F RRC1:RRC 4016 F5 PUSH PSW 4017 05 DCR B 4018 C21540 JNZ RRC1 ; RAL 401B 0608 MVI B,08 401D 3E57 MVI A,57 401F 17 RAL1:RAL 4020 F5 PUSH PSW 4021 05 DCR B 4022 C21F40 JNZ RAL1 ; RAR 4025 0608 MVI B,08 4027 3E57 MVI A,57 4029 1F RAR1:RAR 402A F5 PUSH PSW 402B 05 DCR B 402C C22940 JNZ RAR1 ;;; ; CHECK 402F 310060 LXI SP,ERBF 4032 210050 LXI H,STCK 4035 2B DCX H 4036 118C40 LXI D,TBL1END 4039 0640 MVI B,40 403B 1A LOOP0:LDAX D 403C BE CMP M 403D CA4140 JZ LOOP0_2 4040 E5 PUSH H;ERR 4041 2B LOOP0_2:DCX H 4042 1B DCX D 4043 05 DCR B 4044 C23B40 JNZ LOOP0 4047 E5 PUSH H 4048 210000 LXI H,$0000 404B E5 PUSH H 404C 76 HLT ; ;COMPARE DATA TABLE ;RAR 404D 00 DB 00 404E AF DB AF 404F 01 DB 01 4050 5E DB 5E 4051 00 DB 00 4052 BD DB BD 4053 01 DB 01 4054 7A DB 7A 4055 00 DB 00 4056 F5 DB F5 4057 01 DB 01 4058 EA DB EA 4059 01 DB 01 405A D5 DB D5 405B 41 DB 41 405C AB DB AB ;RAL 405D 01 DB 01 405E 2B DB 2B 405F 01 DB 01 4060 95 DB 95 4061 01 DB 01 4062 CA DB CA 4063 00 DB 00 4064 E5 DB E5 4065 01 DB 01 4066 72 DB 72 4067 00 DB 00 4068 B9 DB B9 4069 01 DB 01 406A 5C DB 5C 406B 40 DB 40 406C AE DB AE ;;RRC 406D 00 DB 00 406E 57 DB 57 406F 01 DB 01 4070 AE DB AE 4071 00 DB 00 4072 5D DB 5D 4073 01 DB 01 4074 BA DB BA 4075 00 DB 00 4076 75 DB 75 4077 01 DB 01 4078 EA DB EA 4079 01 DB 01 407A D5 DB D5 407B 41 DB 41 407C AB DB AB ;RLC 407D 01 DB 01 407E 57 DB 57 407F 01 DB 01 4080 AB DB AB 4081 01 DB 01 4082 D5 DB D5 4083 00 DB 00 4084 EA DB EA 4085 01 DB 01 4086 75 DB 75 4087 00 DB 00 4088 BA DB BA 4089 01 DB 01 408A 5D DB 5D 408B 00 DB 00 408C AE TBL1END:DB AE ; ERBF =6000 LOOP0 =403B LOOP0_2 =4041 MWK =5001 RAL1 =401F RAR1 =4029 RLC1 =400B RRC1 =4015 STCK =5000 TBL1END =408C
●あれぇ?エラーが出てる?
今回は、8080でもZ80でも結果はフラグを含めて全く同じはずですから、安心して実行したのですが、なんとまあ、どうしたことかポロポロといっぱい比較エラーが出ているではありませんか。
比較データと比較した結果、不一致が見つかると、そのデータのあるスタックアドレスが、5FFFからの「エラースタック」に記録されます。
スタックですから後ろから前に、発生した順に記録されます。
結構たくさん不一致データが出ています。
発生順に、4FFA、4FF8、4FF4、4FEE、4FEA…。
いったいどうしたことでしょう。
4FFFからの結果のスタックの中身を確認してみました。
この画面は、実は後からあらためて記録したものですから、TEST8DT1.HTXの内容の表示がちょっとおかしいのですけれど(まあそのように書きましてもほとんどの方はどこがおかしいのかお気づきにはならないと思います)、大したことではありませんから、気になさらないでください。
わかりやすいように、また2バイトずつ区切って、最後の16バイトを抜書きしてみましょう。
0157 01AB 05D5 00EA 0575 04BA 015D 00AE
エラーが発生したトップは4FFAでした。その次が4FF8、さらに4FF4です。
データの一番最後のスタックアドレスが4FFFでそこから前に順番に4FFE、4FFDと若くなっていきます。
エラーの発生したデータを着色してみました。
なんと!ビット2がONになっています。
ビット2は…、P(パリティ)フラグです。
どうして、ローテイト命令で、パリティフラグがONになってしまうのだぁ…?
回路図をよーく見ても、そんなばかなことにはなっていません…。
さては、誤動作か…。
しかし、さらに結果をよくよく見てみますと、もっとおかしいことに気がつきました。
これ、パリティが違ってるじゃないの!
たとえば、最初のエラーの04BAは、フラグが04で(つまりパリティフラグだけがON)、そのときの結果の値がBAです。
BA? 10111010でしょう?
1のビットが奇数個だから、パリティフラグが立つわけないでしょうよ。二重におかしいよ、これ。
さらにさらに混乱した頭で、プログラムやら比較データやらを見ていくうちに、もっとおかしなところに気がつきました。
最初に説明しましたように、このプログラムの最後についている比較データは、もともとZ80に実行させて得られた結果をそのまま利用したものです。
ところが、この比較データをよく見てみると、Z80もエラーをしているらしいところがみつかりました。
上のプログラムリストの407Bのデータです。
41になっています。
ローテイト命令はC(キャリー)フラグしか変化しないはずですから、ビット0しかON/OFFしないはずです。
それなのに、他のビットが、Z80でもONになってしまっている…?
ONになっているのはビット6、Z(ゼロ)フラグです。
●そうか、わかったぞ!
407BはRLCのテストの次に実行するRRCの最初の結果のフラグです。
さらによく見ると、その次の406Bも40ですから、Z(ゼロ)フラグが立っています。
ここはRRCのテストの次に実行するRALの最初の結果のフラグです。
おおなんとさらに、405Bも41ですから、Z(ゼロ)フラグが立っています。
ここはRALのテストの次に実行するRARの最初の結果のフラグです。
プログラムリストをあらためて確認してみて、やっとそのわけがわかりました。
今回のテストプログラムはローテイト命令の動作をテストするために、Bレジスタに08を入れて、それをカウンタにして、ローテイト命令を8回繰り返し実行させるようにしてあります。
そこの部分のプログラムです。
; RLC
4007 0608 MVI B,08
4009 3E57 MVI A,57
400B 07 RLC1:RLC
400C F5 PUSH PSW
400D 05 DCR B
400E C20B40 JNZ RLC1
; RRC
4011 0608 MVI B,08
4013 3E57 MVI A,57
4015 0F RRC1:RRC
4016 F5 PUSH PSW
400DのDCR Bで、結果がB=0になったら、次のRRCのテストに移ります。
このときZ(ゼロ)フラグが立つのです。
そして次のRRCのテストでは、4015のRRCの実行の結果が、4016のPUSH PSWによってフラグとともにスタックに保存されます。
RRC命令は、C(キャリー)フラグ以外のフラグは変化させませんから、その直前に行われた、DCR B命令でセットされたZ(ゼロ)フラグがそのまま残ったままスタックに保存されたのです。
すると、おお!
世にも不思議なパリティフラグの謎も、突然に解けてしまいました。
こいつも、犯人は、DCR Bだったのです。
Z80は、INR、DCRやADD、SUBなどではパリティフラグは変化させません。
厳密に言うと、Z80では上記の命令にはパリティフラグはなくて、オーバーフローフラグになります。
しかし、8080は、INR、DCR命令でもその結果によって、パリティフラグがセット、リセットされます。
そんなものは、意味がない、と考えて、当初はINR、DCR命令では、パリティフラグを無視していたのですが…。
つい、魔が差してしまって、つい先日、INR、DCRやADD、SUBにもパリティフラグを追加してしまいました。
そうしたら、この始末です。
だから、パリティフラグなんて、余計だと言っていたんですよぉ。
エラーだと思ったのは、実はエラーではなくて、Z80と8080の違いが原因だったのでした。
これにて、一件落着。
やれやれ。ほんと、疲れること。
2009.6.29upload
前へ
次へ
ホームページトップへ戻る