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