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