** Definitions for coding of Z80 instruction routines.
** (Macros and register aliases.)

** =====================================================================

** Registers:

**  D0	 00   A'   00   A       A0      TableBase/Work
**  D1	 00   B'   00   B       A1      Pseudo-PC
**  D2	 00   C'   00   C       A2      Z80 SP (high word is garbage)
**  D3	 00   D'   00   D       A3      Z80 address zero
**  D4	 00   E'   00   E       A4      CacheBase
**  D5	 scratch    H	L	A5	FlagsBase
**  D6	 scratch  saveCCR	A6	InstructionBase
**  D7	 --- scratch ---	A7	User Stack Pointer

** Aliases:

A	EQUR	d0
B	EQUR	d1
C	EQUR	d2
D	EQUR	d3
E	EQUR	d4
L	EQUR	d5	;To indicate byte access
HL	EQUR	d5	;To indicate word access

TableB	EQUR	a0	;pointer to TableBase
Work	EQUR	a0	;pointer to the Z80_Workspace longword
PPC	EQUR	a1	;Pseudo-PC
ZSP	EQUR	a2	;Z80 Stack Pointer (only lower word used)
Z0	EQUR	a3	;pointer to Z80 address zero
CacheB	EQUR	a4	;pointer to CacheBase (corresponding to Z0)
FlagsB	EQUR	a5	;pointer to FlagsBase (corresponding to Z0)
InstrB	EQUR	a6	;pointer to InstructionBase

** The memory handler refers to most of the base pointers, by their
** aliases. The only address registers that can be used as scratch pads
** are PPC and ZSP, so I'd like them to remain in a1 and a2. If they are
** moved, changes must be done in the memory handler.

**	Remember: if you change this, you must also change the labels
**	in the Z80_RegStorage table in Z80_struct.i.

** ======================================================================

	IFD VERBOSE
	LIST
** Compiling the Z80_coding.i file.
	NOLIST
	ENDC

** Macros and local labels:
**
** Make sure any labels within a macro are truly unique, especially
** if the macro might be repeated between global labels.
**   Let local labels be on the form "<number>$", where <number>
** is > 100 in "utility" macros. Local labels in instruction routines
** (or macros defining such routines) that are on that form should have
** <number> less than 100.
**   If a macro could be called more than once between global labels, and
** the macro must contain local labels, those labels must be unique for
** each macro call (between global labels), but may not be global since
** that would undefine any other local labels. Standard local labels
** (<number>$) can't be auto-generated, since the macro 'parameter' \@
** expands to "_<number>" (plain stupid, if you ask me).
**   My solution (while I can't use Devpac-style local labels here),
** is to use an extra parameter (the last) to specify a "usage number"
** to be joined with the local label numbers, i.e. "<number>\3$".
** This is certainly ugly, but it will work.

** Reserved digit sequences:
**	100-110 	testreq
**	(111-119)...	putz (i.e. anything beginning with 111 to 119.)
**	200-210 	opcode_2_bytes
**	300-310 	opcode_3_bytes


** End of instruction, execute next.
next	MACRO
		move.w	(PPC)+,d7
		jmp	(InstrB,d7.w)
	ENDM
** ----

** Test for requests. Has a built-in "next" function.
** May only occur once in an instruction routine.
testreq MACRO
		move.w	Z80_Request(TableB),d7
		bne.s	102$	;skip if no request
101$		move.w	(PPC)+,d7
102$		jmp	(InstrB,d7.w)
	ENDM
	;101$ is supposed to be a known entry point used to
	;exit to next instruction without testing requests.
	;Most jumps/calls use this "feature".
** ----

** Read from z80 memory. Address is a register.
getz	MACRO	;address,value
		move.b	(Z0,\1.w),\2
	ENDM
** ----

** Write a byte to memory, marking the cache pointer 'changed'.
** Address is a register. Memory flags are not checked here. See putz.
	IFD UPDATECACHE
writemem MACRO	;value,address
		move.b	\1,(Z0,\2.w)
		add.w	\2,CacheB
		clr.w	(CacheB,\2.w)
		sub.w	\2,CacheB
	ENDM
	ELSE
writemem MACRO	;value,address
		move.b	\1,(Z0,\2.w)	;write to z80 memory
	ENDM
	IFD VERBOSE
	LIST
**   Writemem does not mark the cache pointer.
	NOLIST
	ENDC
	ENDC ;IFD UPDATECACHE
** ----

** Write to z80 memory. Address is a register.
	IFND	Z80_MEMCHECK
putz	MACRO	;value,address
		writemem <\1>,<\2>
	ENDM
	ELSE
** As above, but do address exception testing.
** May occur several times in a single instruction routine,
** therefore, calls beyond the first must specify a "usage number"
** (preferably a single digit).
putz	MACRO	;value,address[,use]
		tst.b	(FlagsB,\2.w)
		beq.s	111\3$
		move.w	\2,-(sp)
		move.b	\1,-(sp)
		jsr	memhandler(InstrB)
		addq.l	#4,sp
		bra.s	112\3$
111\3$		writemem <\1>,<\2>
112\3$
	ENDM

	;If the handler is called, the write part is skipped. If
	;the value should be written, the handler will do it.
	;When the memory handler is reached, the stack should
	;look like this:
	; sp+6	word	address
	;	byte	padding (caused by move.b to stack)
	; sp+4	byte	value
	; sp->	long	return address

WRITE_ADDR = 6	;the offsets used by memhandler
WRITE_VAL = 4

	ENDC ;IFND Z80_MEMCHECK
** ----

** Word-sized Increment
incw	MACRO	;dest
		addq.w	#1,\1
	ENDM
** ----

** Word-sized decrement
decw	MACRO	;dest
		subq.w	#1,\1
	ENDM
** ----

** Byte-sized increment
incb	MACRO	;dest
		addq.b	#1,\1
	ENDM
** ----

** Byte-sized decrement
decb	MACRO	;dest
		subq.b	#1,\1
	ENDM
** ----

** Move PPC 'count' words forward. (Max 4)
skip	MACRO	;count
		addq.l	#2*(\1),PPC
	ENDM
** ----

** Calculate the real 16-bit Z80 PC (result in d7).
getRPC	MACRO
		move.l	PPC,d7
		sub.l	CacheB,d7
		lsr.l	#1,d7
	ENDM
** ----

** Make new PPC from the Real PC in d7.
** PPC=CacheB+2*(extended d7.w)
makePPC MACRO
		lea	(CacheB,d7.w),PPC
		add.w	d7,PPC
	ENDM
** ----

** Test parity. Bits 8-15 must be zero.
parity	MACRO	;register
		or.b	Z80_Parity(TableB,\1.w),d6
	ENDM
** ----

** Store the status register / condition code register.
	;Move from SR is privileged on 68010 and higher. On those,
	;use Move from CCR (which doesn't exist on 68000).
	IFNE	PROCESSOR<68010

putsr	MACRO	;dest
		move	SR,\1
	ENDM
	IFD VERBOSE
	LIST
**   putsr uses Move from SR.
	NOLIST
	ENDC

	ELSE

putsr	MACRO	;dest
		move	CCR,\1
	ENDM
	IFD VERBOSE
	LIST
**   putsr uses Move from CCR.
	NOLIST
	ENDC

	ENDC ;IFND CCR_VERSION
** ----

** Load the condition code register from d6.
getsr	MACRO
		move	d6,CCR
	ENDM
** ----

** Make a word of two bytes. Result in d7.
join	MACRO	;High,Low
		move.b	\1,(Work)
		move.w	(Work),d7
		move.b	\2,d7
	ENDM
** ----

** Index register + offset to d7. Offset is always the third byte.
** The PPC has been increased by one.
index	MACRO	;X or Y
		getRPC
		incw	d7
		getz	d7,d7
		ext.w	d7
		add.w	Z80_I\1(TableB),d7
	ENDM
** ----

** Execute macro/instruction with all r but H as parameter.
do_r	MACRO ;instruction
	\1 A
	\1 B
	\1 C
	\1 D
	\1 E
	\1 L
	ENDM
** ----

** Execute macro/instruction with B,C and D,E as parameters.
do_ss	MACRO ;instruction
	\1 B,C
	\1 D,E
	ENDM
** ----

** Execute macro/instruction with X and Y as parameter
do_xy	MACRO ;instruction
	\1 X
	\1 Y
	ENDM
** ----

** Test multi-byte opcodes for modified code.
** Only negative cache values are allowed for the second and third
** bytes of the opcode.


** This tests the instructions on the form
**	prefix	(DD/CB)
**	opcode
**	[offset]
**	[data]

	;May only occur once in an instruction routine

	IFD MODIFIEDCODE
opcode_2_bytes MACRO
		tst.w	(PPC)
		bmi.s	201$
		jmp	stale_ptr(InstrB)
201$
	ENDM
	ELSE
opcode_2_bytes MACRO
	;do nothing
	ENDM
	IFD VERBOSE
	LIST
**   No tests for modified code in 2-byte opcodes are made.
	NOLIST
	ENDC
	ENDC ;IFD MODIFIEDCODE


** This tests the instructions on the form
**	prefix	(DD/FD)
**	prefix	(CB)
**	offset
**	opcode

	;May only occur once in an instruction routine

	IFD MODIFIEDCODE
opcode_3_bytes MACRO
		move.w	(PPC),d7
		or.w	4(PPC),d7
		bmi.s	301$
		jmp	stale_ptr(InstrB)
301$
	ENDM
	ELSE
opcode_3_bytes MACRO
	;do nothing
	ENDM
	IFD VERBOSE
	LIST
**   No tests for modified code in 3-byte opcodes are made.
	NOLIST
	ENDC
	ENDC ;IFD MODIFIEDCODE

** =======================================================================
