Z80 or 8080?

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