前回のADD編の続き。
μPD8080Aは減算後の十進補正も正しく動作する、ということなので確認。
chkbcdsub.awk
$1 ~ /[0-9][0-9][0-9][0-9]/ {a=substr($1,1,2)b=substr($1,3,2)if (b>a) a=a+100c=a-bif (c!=($4-0)) print $0}
入力データの1カラム目は4桁の16進数で、前2桁から後ろ2桁で減算を行う。その結果を十進補正したものが4カラム目。このスクリプトはこの減算を行い、十進補正値と比較して異なれば出力する。
Intelの8080だと00〜99 - 00〜99の全組み合わせ10000通りですべてエラー。例えば:
0000 00 *Z*H*P** 06 *****P**
0001 FF S****P*C 65 ***H*P*C
...
とこのような感じで1行目は減算時のハーフフラグの立ち方がおかしく、よけいな補正をしている。2行目は"F"から補正値6を引かないといけないところを加算している。ということで減算時の補正についてはまったく考慮していない。
NECのμPD8080AではSUB命令の後の補正後の値はすべて正しかった。ところで十進補正の補正値である"6"をDAA命令で足すのか引くのかはどうやっているのだろうか。おそらくDAA命令の直前に実行した演算命令がADDなら加算、SUBなら減算にしているはずで、もしかしたら未定義のフラグを使っているのか。ここは気になる点。
※8086だとDAA命令とDAS命令でそれぞれ加算後十進補正、減算後十進補正と命令が別れている。
さてここまでやって1加算するINR命令と1減算するDCR命令ではどうだろうか。これも確認してみた。
ADD 1とINR、SUB 1とDCRの比較結果はこちら:
Intel 8080の結果は以下の部分が異なる。2〜5カラム目がADD 1の結果、6〜9カラム目がINRの結果。
INR:
FF01 00 *Z*H*P*C 66 *****P*C 00 *Z*H*P** 06 *****P**
これは値が範囲外、かつキャリーフラグがINRでは立たないので補正されていない。問題なし。
DCR:
0001 FF S****P*C 65 ***H*P*C FF S****P** 65 ***H*P*C
そもそもSUB後のDAAは保証外、値が範囲外、INRでキャリーが立たない。問題なし。
NEC μPD8080Aの結果。
INR:
0F01 10 ***H**** 16 ***H**** 10 ******** 10 ********1F01 20 ***H**** 26 ***H**** 20 ******** 20 ********
2F01 30 ***H*P** 36 ***H*P** 30 *****P** 30 *****P**
3F01 40 ***H**** 46 ***H**** 40 ******** 40 ********
4F01 50 ***H*P** 56 ***H*P** 50 *****P** 50 *****P**
5F01 60 ***H*P** 66 ***H*P** 60 *****P** 60 *****P**
6F01 70 ***H**** 76 ***H**** 70 ******** 70 ********
7F01 80 S**H**** 86 S**H**** 80 S******* 80 S*******
8F01 90 S**H*P** 96 S**H*P** 90 S****P** 90 S****P**
9F01 A0 S**H*P** 06 ***H*P*C A0 S****P** 00 *Z***P*C
AF01 B0 S**H**** 16 ***H***C B0 S******* 10 *******C
BF01 C0 S**H*P** 26 ***H***C C0 S****P** 20 *******C
CF01 D0 S**H**** 36 ***H*P*C D0 S******* 30 *****P*C
DF01 E0 S**H**** 46 ***H***C E0 S******* 40 *******C
EF01 F0 S**H*P** 56 ***H*P*C F0 S****P** 50 *****P*C
0F01 10 ***H**** 16 ***H**** 10 ******** 10 ********
値が範囲外なので問題なし。
DCR:
0001 FF S**H*P*C 99 S**H*P*C FF S****P** FF S****P**
1001 0F ***H*P** 09 ***H*P** 0F *****P** 0F *****P**
2001 1F ***H**** 19 ***H**** 1F ******** 1F ********
3001 2F ***H**** 29 ***H**** 2F ******** 2F ********
4001 3F ***H*P** 39 ***H*P** 3F *****P** 3F *****P**
5001 4F ***H**** 49 ***H**** 4F ******** 4F ********
6001 5F ***H*P** 59 ***H*P** 5F *****P** 5F *****P**
7001 6F ***H*P** 69 ***H*P** 6F *****P** 6F *****P**
8001 7F ***H**** 79 ***H**** 7F ******** 7F ********
9001 8F S**H**** 89 S**H**** 8F S******* 8F S*******
A001 9F S**H*P** 99 S**H*P** 9F S****P** 9F S****P**
B001 AF S**H*P** A9 S**H*P** AF S****P** AF S****P**
C001 BF S**H**** B9 S**H**** BF S******* BF S*******
D001 CF S**H*P** C9 S**H*P** CF S****P** CF S****P**
E001 DF S**H**** D9 S**H**** DF S******* DF S*******
F001 EF S**H**** E9 S**H**** EF S******* EF S*******
00-01から90-01はBCD演算の対象。DCRでハーフキャリーが立っていないのでDAA補正が正しくない。ということはBCDの範囲内ならINR後DAAはIntel、NECとも正常動作する。DCR後DAAはIntelは保証外、NECは被減数が00,10,20,30,40,50,60,70,80,90でDCR後DAAで誤動作する。
惜しい。NEC μPD8080Aの減算後DAAではINRで正常動作するつもりでDCRを使うとハマるんじゃなかろうか。
INR/DCRではキャリーフラグは立たない。フラグのうちS/Z/Pは結果だけから求められるが、CY/ACは演算の種類と値によって決まる。INR/DCRはALUの加減算器のパスを通ってない感じがする。
残りは8085やZ80との比較かな。
おまけ:チェコスロバキアから届いたTESLA MHB8080A動きました。
MHB8080ACデータシート

インテル8080伝説
