+ .z80 ; for M80, ignored by SLR assembler\r
+ include z180reg.inc\r
+\r
+RUN_TPA equ 0\r
+\r
+UUNKNOWN equ 0 ;Unknown CPU\r
+U8080 equ 1 ;8080\r
+U8085 equ 2 ;8085\r
+UZ80 equ 3 ;Z80\r
+UX180 equ 4 ;HD64180 or higher\r
+UHD64180 equ 5 ;HD64180\r
+UZ80180 equ 6 ;Z80180\r
+UZ8S180 equ 7 ;Z8S180, Z8L180\r
+\r
+\r
+;-------------------------------------------------------------------------------\r
+\r
+\r
+ if RUN_TPA\r
+base equ 0100h\r
+ else\r
+base equ 0\r
+ endif\r
+\r
+\r
+ aseg\r
+ org base\r
+ jp start\r
+\r
+done: db 0\r
+result: db 0\r
+\r
+;-------------------------------------------------------------------------------\r
+; Read internal register at address in L and IOBASE in H.\r
+;\r
+\r
+reg_in:\r
+ ld a,h\r
+ add a,l\r
+ ld c,a\r
+ ld b,0\r
+ in a,(c)\r
+ ret\r
+\r
+;-------------------------------------------------------------------------------\r
+; Write internal register at address in L and IOBASE in H.\r
+;\r
+\r
+reg_out:\r
+ ld b,a\r
+ ld a,h\r
+ add a,l\r
+ ld c,a\r
+ ld a,b\r
+ ld b,0\r
+ out (c),a\r
+ ret\r
+\r
+;-------------------------------------------------------------------------------\r
+; Check if register C exists. D holds mask of bit to test.\r
+; return nz, if register exists\r
+\r
+chk_reg:\r
+ call reg_in\r
+ cp 0ffh\r
+ ret nz ;\r
+\r
+ ; check, if register is changeable\r
+\r
+ xor d ; set bit(s) in register to 0\r
+ call reg_out\r
+ call reg_in ; get it back\r
+ ex af,af'\r
+ ld a,0ffh ; set to register original state\r
+ call reg_out\r
+ ex af,af'\r
+ cpl\r
+ and d\r
+ ret\r
+\r
+;-------------------------------------------------------------------------------\r
+; Check CPU\r
+;\r
+;\r
+; return:\r
+; E = 0 Unknown\r
+; E = 1 8080\r
+; E = 2 8085\r
+; E = 3 Z80\r
+; E = 4 HD64180 or higher\r
+; E = 5 HD64180\r
+; E = 6 Z80180\r
+; E = 7 Z8S180, Z8L180\r
+;\r
+;-------------------------------------------------------------------------------\r
+; Registers only in Z180+, not in HD64180\r
+; 3E OMCR\r
+;\r
+; Registers only in Z8S180/Z8L180\r
+; 12 ASEXT0\r
+; 13 ASEXT1\r
+; 1A ASTC0L\r
+; 1B ASTC0H\r
+; 1C ASTC1L\r
+; 1D ASTC1H\r
+; 1E CMR\r
+; 1F CCR\r
+; 2D IAR1B\r
+;\r
+; Reserved registers\r
+; 11\r
+; 19\r
+; 35\r
+; 37\r
+; 3B - 3D\r
+\r
+check:\r
+ ld e,U8080 ; Init return val, assume 8080\r
+ xor a\r
+ dec a ; 00 --> 0FFH 8080/8085: even parity; Z80+: No overflow\r
+ jp po,chk_z80 ; Z80+ if P/V flag reset\r
+\r
+ ; The 8085 logical AND instructions always set the auxiliary flag ON.\r
+ ; The 8080 logical AND instructions set the flag to reflect the\r
+ ; logical OR of bit 3 of the values involved in the AND operation.\r
+ ; (8080/8085 ASSEMBLY LANGUAGE PROGRAMMING MANUAL, 1977, 1978)\r
+\r
+ xor a\r
+ and a ; 8085 sets, 8080 resets half carry.\r
+ daa ; A=06 (8085) or A=00 (8080)\r
+ ret z\r
+ inc e\r
+ ret\r
+\r
+chk_z80:\r
+ ld e,UZ80 ; Assume Z80\r
+ daa ; Z80: 099H, x180+: 0F9H\r
+ cp 99h ; Result on 180 type cpus is F9 here. Thanks Hitachi\r
+ ret z\r
+ inc e ; x180\r
+\r
+ ; At least Hitachi HD64180\r
+ ; Test differences in certain internal registers\r
+ ; to determine the 180 variant.\r
+ ; First, search the internal register bank.\r
+\r
+ ld h,00H ; I/O Base\r
+find_base_loop:\r
+ ld l,icr\r
+ call reg_in\r
+ and 11011111b ; mask I/O Stop bit\r
+ xor h\r
+ cp 01FH\r
+ jr nz,nxt_base\r
+\r
+ ;TODO: additional plausibility checks\r
+\r
+ jr z,base_found\r
+nxt_base:\r
+ ld a,h\r
+ add a,040H\r
+ ld h,a\r
+ jr nc,find_base_loop\r
+ ret ;I/O registers not found\r
+\r
+ ; Register (base) found.\r
+\r
+base_found:\r
+ inc e ; HD64180\r
+ ld l,omcr ; Check, if CPU has OMCR register\r
+ ld d,M_IOC ;\r
+ call chk_reg ;\r
+ ret z ; Register does not exist. It's a HD64180\r
+\r
+ inc e ; Z80180\r
+ ld l,cmr ; Check, if CPU has CMR register\r
+ ld d,M_LNC ;\r
+ call chk_reg ;\r
+ ret z ; register does not exist. It's a Z80180\r
+\r
+ inc e ; S180/L180 (class) detected.\r
+\r
+ ret\r
+\r
+;-------------------------------------------------------------------------------\r
+\r
+start:\r
+ ld sp,stack\r
+ call check\r
+\r
+ ld hl,result\r
+ ld (hl),e\r
+ dec hl\r
+ ld (hl),0ffH\r
+ halt\r
+ jp $-1\r
+\r
+ rept 8\r
+ dw 0\r
+ endm\r
+stack:\r
+ end\r
+\r
+; vim:set ts=8 noet nowrap\r