Z80 DAA 内部キャリーフラグは実在するのか?
Z80 DAA 内部キャリーフラグは実在するのか?
「別冊トランジスタ技術 SPECIAL No.7 特集 HD64180徹底活用マニュアル」の第1章12「HD64180とZ80のDAA命令の違い」という記事に、
Z80ではDEC
命令はキャリーフラグが変化しないにもかかわらず、その演算結果のボローを内部に保持して、直後のDAA
命令の動作に影響を与えるという記述があります。
ザイログの一次情報Z180 Family QUESTIONS AND ANSWERSにもZ80との動作の差異としてこの内部キャリーフラグについての記載があります。
一方、多くのZ80エミュレーターではこの内部キャリーフラグは実装せずDAA
命令実行開始時のAレジスタの値が099h
より大きい場合はキャリーフラグがセットされているものとみなす事で同様の結果を実現しています。
公式情報の方が信頼性が高そうにも思えますが、実際にはエミュレーターの動作の方が正しそうです。 というのも、前述のトラ技SPECIALの記事ではSBUGでステップ実行して動作検証していますが、SBUGによるステップ実行で内部キャリーフラグが保持できるとは考え難いためです。
内部キャリーフラグが実在する場合は 次のふたつのコードの結果が異なるはずです。
DEC A
直後にDAA
xor a
dec a
daa
ボローしないDEC A
で内部キャリーを一応クリアしPOP AF
で内部キャリーフラグ以外の状態を再現後にDAA
xor a
ld hl,0ffbah
push hl
inc a
dec a
pop af
daa
動作検証用のCP/Mプログラムを作成しみました。
HB-11実機とFS-A1ST実機Z80モード(T9769C)での実行結果
[normal]
xor a A:00 F:-Z---P--
dec a A:FF F:S-5H3-N-
daa A:99 F:S---3PNC
[set AF value]
xor a A:00 F:-Z---P--
ld hl,0ffbah A:00 F:-Z---P--
push hl A:00 F:-Z---P--
inc a A:01 F:--------
dec a A:00 F:-Z----N-
pop af A:FF F:S-5H3-N-
daa A:99 F:S---3PNC
エミュレーターと同じ動作であり、やはり内部キャリーフラグは存在しないようです。
FS-A1ST実機R800モードでの実行結果
[normal]
xor a A:00 F:-Z---P--
dec a A:FF F:S--H--N-
daa A:99 F:S----PNC
[set AF value]
xor a A:00 F:-Z---P--
ld hl,0ffbah A:00 F:-Z---P--
push hl A:00 F:-Z---P--
inc a A:01 F:--------
dec a A:00 F:-Z----N-
pop af A:FF F:S-5H3-N-
daa A:99 F:S-5-3PNC
こちらも未定義フラグ以外は同じ結果です。
CP/Mプログラムソース(sjasm)
(1stepずつ命令を増やして最初から実行し直すという力技ステップ実行)
org 100h
ld de,op1
call puts
ld de,op10
call puts
xor a
call putreg
ld de,op11
call puts
xor a
dec a
call putreg
ld de,op12
call puts
xor a
dec a
daa
call putreg
ld de,op2
call puts
ld de,op20
call puts
xor a
call putreg
ld de,op21
call puts
xor a
ld hl,0ffbah
call putreg
ld de,op22
call puts
xor a
ld hl,0ffbah
push hl
call putreg
pop af
ld de,op23
call puts
xor a
ld hl,0ffbah
push hl
inc a
call putreg
pop af
ld de,op24
call puts
xor a
ld hl,0ffbah
push hl
inc a
dec a
call putreg
pop af
ld de,op25
call puts
xor a
ld hl,0ffbah
push hl
inc a
dec a
pop af
call putreg
ld de,op26
call puts
xor a
ld hl,0ffbah
push hl
inc a
dec a
pop af
daa
call putreg
ret
op1:
db "[normal]",0dh,0ah,"$"
op10:
db "xor a $"
op11:
db "dec a $"
op12:
db "daa $"
op2:
db "[set AF value]",0dh,0ah,"$"
op20:
db "xor a $"
op21:
db "ld hl,0ffbah $"
op22:
db "push hl $"
op23:
db "inc a $"
op24:
db "dec a $"
op25:
db "pop af $"
op26:
db "daa $"
hex:
db "0123456789ABCDEF"
putreg:
push af
ld e,'A'
call putc
ld e,':'
call putc
pop af
push af
call puthex2
ld e,' '
call putc
ld e,'F'
call putc
ld e,':'
call putc
pop af
push af
push af
pop hl
push hl
ld e,'S'
bit 7,l
jr nz,fS
ld e,'-'
fS:
call putc
pop hl
push hl
ld e,'Z'
bit 6,l
jr nz,fZ
ld e,'-'
fZ:
call putc
pop hl
push hl
ld e,'5'
bit 5,l
jr nz,f5
ld e,'-'
f5:
call putc
pop hl
push hl
ld e,'H'
bit 4,l
jr nz,fH
ld e,'-'
fH:
call putc
pop hl
push hl
ld e,'3'
bit 3,l
jr nz,f3
ld e,'-'
f3:
call putc
pop hl
push hl
ld e,'P'
bit 2,l
jr nz,fP
ld e,'-'
fP:
call putc
pop hl
push hl
ld e,'N'
bit 1,l
jr nz,fN
ld e,'-'
fN:
call putc
pop hl
push hl
ld e,'C'
bit 0,l
jr nz,fC
ld e,'-'
fC:
call putc
pop hl
ld e,0dh
call putc
ld e,0ah
call putc
xor a
inc a
dec a
pop af
ret
puthex2:
push af
rra
rra
rra
rra
call puthex
pop af
puthex:
and 0fh
ld e,a
ld d,0
ld hl,hex
add hl,de
ld e,(hl)
putc:
ld c,2
jp 5
puts:
ld c,9
call 5
di
ret