標準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

前へ
次へ
ホームページトップへ戻る