How do you detect which CPU your program is running on? Maybe you want to optimize for Z80, but also want your program to run in an Intel 8080. There are subtle differences which you can take advantage of to detect the type of CPU.
One such difference is in the flags used by the ALU. The Z80 has an N flag (subtract flag) which the 8080 does not. Obviously, it’s not possible to test a flag which isn’t there, but you can do so indirectly. When the flags are pushed to the stack, the 8080 will “set” the N flag to be always 1, to fill in the unused flag position (bit 1 in the byte representing the flags). The OR instruction in the Z80 clears the N flag. The following short instruction sequence will detect this difference.
mvi a,2
ora a ; Clear the N flag
push psw
pop d
ana e ; If a=0, this is a Z80, else a=2
The PUSH/POP sequence moves the flags to the E register. Then it is simple to test if bit 1 is set (8080) or clear (Z80). The code uses Intel 8080 mnemonics, because the code of course must run on an 8080, and not use any Z80 specific instructions.
A full example for CP/M is:
TPA equ 0100h
BDOS equ 0005h
PRINT equ 09h
NFLAG equ 02h
org TPA
main:
mvi a,NFLAG
ora a
push psw
pop d
ana e
jz isZ80
lxi d,t8080
jmp done
isZ80:
lxi d,tz80
done:
mvi c,PRINT
call BDOS
ret
tz80: db 'Z80$'
t8080: db '8080$'
end main
Edit a file CPUTEST.ASM with the above text, Run ASM CPUTEST, followed by LOAD CPUTEST, and you end up with an executable CPUTEST.COM.
The above code was tested good on a real Z80 and on a NEC V20 in 8080 emulation mode.
For reference, a version using Zilog instruction mnemonics is listed below (assembles to the same binary as the 8080 version above):
.z80
TPA equ 0100h
BDOS equ 0005h
PRINT equ 09h
NFLAG equ 02h
org TPA
main:
ld a,NFLAG
or a
push af
pop de
and e
jp z,isZ80
ld de,t8080
jp done
isZ80:
ld de,tz80
done:
ld c,PRINT
call BDOS
ret
tz80: db 'Z80$'
t8080: db '8080$'
end main