home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 2
/
FFMCD02.bin
/
new
/
misc
/
emu
/
z80
/
generic_macs.i
< prev
next >
Wrap
Text File
|
1993-12-21
|
7KB
|
311 lines
** The generic versions of the macros for the implementation-dependent
** Z80 instructions.
** The file Z80_coding.i contains the definitions of the macros and
** register aliases used in the instruction emulation routines.
** If your assembler does not handle register aliasing, you will have to
** translate the aliases used below to the corresponding register names,
** as defined in the include file. Take great care when doing this.
** ======================================================================
** Notes on the refresh register
**
** The real behaviour of the R register seems impossible to emulate at a
** reasonable speed, since it increments at certain intervals providing
** certain parts of the CPU are free. Usually once per instruction, but
** sometimes twice. (If anybody finds a complete description of this,
** please send me a copy).
**
** The R register is not incremented after each instruction; instead when
** Ld A,R is executed the bits 0-6 have to be made up from some counter
** like the Pseudo-PC or the system clock. Bit 7 is taken from the last
** stored R.
**
** When Ld R,A is executed, only bit 7 must be safely stored in the
** Z80_R field of the control structure. Bits 0-6 may be treated in any
** way by the implementer.
**
** The file generic_macs.i provides a version of Ld A,R which uses the
** Pseudo-PC to 'approximate R' as a non-machine specific way to do it.
** ---------------------------------------------------------------------
IFD VERBOSE
LIST
** Using the generic macros for the implementation-dependent routines.
NOLIST
ENDC
** The In instructions "read" a fixed value:
DEFAULT_IN = 00
/* Macros can't be nested, so we do it like this: */
In_r_1C1_subm MACRO ;Parameter: register
move.b #DEFAULT_IN,\1 ;this is where you "read" the value
tst.b \1 ;V is cleared, N and Z tested
putsr d7
eor.b d7,d6
and.w #1,d6
eor.b d7,d6 ;keep old carry
parity \1
skip 1
next
ENDM
In_A_1C1_mac MACRO
In_r_1C1_subm A
ENDM
In_B_1C1_mac MACRO
In_r_1C1_subm B
ENDM
In_C_1C1_mac MACRO
In_r_1C1_subm C
ENDM
In_D_1C1_mac MACRO
In_r_1C1_subm D
ENDM
In_E_1C1_mac MACRO
In_r_1C1_subm E
ENDM
In_L_1C1_mac MACRO
In_r_1C1_subm L
ENDM
In_H_1C1_mac MACRO
swap d6 ;save flags
move.b #DEFAULT_IN,d6 ;"read" the value
move.w HL,(Work)
move.b d6,(Work) ;V is cleared, N & Z tested
putsr d7
or.b Z80_Parity(TableB,d6.w),d7 ;set parity in d7
move.w (Work),HL
swap d6 ;old flags back
eor.b d7,d6
and.w #1,d6
eor.b d7,d6 ;keep old carry
skip 1
next
ENDM
;"Undocumented" instruction. Reads from the port but does not
;store the value. Flags are affected by the read value as usual,
;and this instruction is sometimes named "In F,(C)". The name
;"In (HL),(C)" would be symmetric, but is not correct.
In_xx_1C1_mac MACRO
swap d6 ;save flags
move.b #DEFAULT_IN,d6 ;"read" the value
tst.b d6 ;V is cleared, N & Z tested
putsr d7
or.b Z80_Parity(TableB,d6.w),d7 ;set parity in d7
swap d6 ;forget the value, old flags back
eor.b d7,d6
and.w #1,d6
eor.b d7,d6 ;keep old carry
skip 1
next
ENDM
** ----
In_A_1n1_mac MACRO
getRPC ;d7="Real PC" is addressing the immediate data
getz d7,d7 ;transfer the byte to d7
;Now, the port address is formed from A (bits 15-8)
;and d7 (bits 7-0).
move.b #DEFAULT_IN,A ;"read" the value.
skip 1
next
ENDM
** ----
Ind_mac MACRO
move.b #DEFAULT_IN,d7
putz d7,HL
decw HL
and.w #%1011,d6
decb B
bne.s 01$ ;jump if not zero
or.w #%0100,d6
01$ skip 1
next
ENDM
** ----
Indr_mac MACRO
move.b #DEFAULT_IN,d7
01$ putz d7,HL
decw HL
decb B
bne.s 01$ ;loop
or.w #%0100,d6
skip 1
next
ENDM
** ----
Ini_mac MACRO
move.b #DEFAULT_IN,d7
putz d7,HL
incw HL
and.w #%1011,d6
decb B
bne.s 01$ ;jump if not zero
or.w #%0100,d6
01$ skip 1
next
ENDM
** ----
Inir_mac MACRO
move.b #DEFAULT_IN,d7
01$ putz d7,HL
incw HL
decb B
bne.s 01$ ;loop
or.w #%0100,d6
skip 1
next
ENDM
** ----
Ld_A_R_mac MACRO
getRPC ;take bits from RPC (since PPC is always even)
move.b Z80_R(TableB),A
eor.w d7,d6
and.w #80,d6 ;keep bit 7 of stored R
eor.w d7,d6 ;V is cleared, Z and N tested.
putsr d7
eor.w d7,d6
and.w #1,d6 ;keep old carry
eor.w d7,d6
tst.b Z80_IFF(TableB) ;test IFF2
beq.s 01$ ;jump if IFF2 clear
or.w #%0010,d6 ;set V if IFF2 set
01$ skip 1
next
ENDM
** ----
Ld_R_A_mac MACRO
move.b A,Z80_R(TableB) ;(the bits 6-0 are never reused)
skip 1
next
ENDM
** ----
** The Out instructions don't "output" anything, but merely change
** registers and flags as needed.
** It is OK for Otir and Otdr to be a bit inefficient. The real Z80
** instruction does a complete re-execution each time it loops.
** If that is done here as well, the block output timing will be nicer.
Otdr_mac MACRO
01$ getz HL,d7
;d7 holds the byte to be output,
;BC the port address.
;place "output" here
decw HL
decb B
bne.s 01$ ;loop
or.w #%0100,d6 ;Set Z
skip 1
next
ENDM
** ----
Otir_mac MACRO
01$ getz HL,d7
;d7 holds the byte to be output,
;BC the port address.
;place "output" here
incw HL
decb B
bne.s 01$ ;loop
or.w #%0100,d6 ;Set Z
skip 1
next
ENDM
** ----
Out_1C1_r_mac MACRO ;Parameter: register
;"output" to BC
skip 1
next
ENDM
Out_1C1_H_mac MACRO
;"output" to BC
skip 1
next
ENDM
** ----
;"Undocumented" instruction. Seems to output a zero value
;to the port. The name "Out (C),(HL)" would be symmetric,
;but is not correct.
Out_1C1_xx_mac MACRO
;"output" a zero to port BC
skip 1
next
ENDM
** ----
Out_1n1_A_mac MACRO
getRPC
getz d7,d7 ;get immediate data to d7
;"output" A to address given by d7 (bits 7-0)
;(bits 15-8 seem tobe undefined)
skip 1
next
ENDM
** ----
Outd_mac MACRO
getz HL,d7
;"output" value in d7 to BC
decw HL
and.w #%1011,d6 ;Clear Z
decb B
bne.s 01$ ;jump if not zero
or.w #%0100,d6 ;Set Z
$01 skip 1
next
ENDM
** ----
Outi_mac MACRO
getz HL,d7
;"output" value in d7 to BC
incw HL
and.w #%1011,d6 ;Clear Z
decb B
bne.s 01$ ;jump if not zero
or.w #%0100,d6 ;Set Z
01$ skip 1
next
ENDM
** ----
** The Reti and Retn instructions do not themselves cause any signalling,
** but interrupt-controlling hardware could be watching the bus to see
** when an interrupt finishes.
Reti_mac MACRO
;Do any "hardware" emulation first.
getz ZSP,1(Work)
incw ZSP
getz ZSP,(Work)
incw ZSP
move.w (Work),d7
makePPC
testreq
ENDM
** ----
Retn_mac MACRO
;Do any "hardware" emulation first.
getz ZSP,1(Work)
incw ZSP
getz ZSP,(Work)
incw ZSP
move.w (Work),d7
makePPC
move.b Z80_IFF(TableB),d7
asr.b #1,d7 ;IFF2 -> IFF1 -> bit 5
and.b #$C0,d7 ;reset bits 5-0
move.b d7,Z80_IFF(TableB)
testreq
ENDM
** ======================================================================