** Helper functions (that is, the emulator would work without them,
** but you wouldn't want to be without them).

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

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

** This subroutine makes the emulator update the private fields of the
** control structure when changes to any of the public fields have taken
** place, for instance if the Z80_Memory field is changed. Do not call
** this routine while the emulator is running.
**   Call Z80_Exitreq and make sure the emulator has stopped before
** reallocating memory (remember to copy the old memory contents to the
** new areas), then update the corresponding entries in the control
** structure (Z80_Memory, Z80_Cachemem and Z80_Flagmem). Calling
** Z80_NewSettings will then make sure that Z80_Continue will properly
** resume the emulation from the new addresses.
**   a0 must point to the control structure.
**   The return value in d0 is nonzero if an error occurred, and zero
** otherwise.

Z80_NewSettings	;(a0)	(ctrl)
		move.l	Z80_Memory(a0),d0
		add.l	#Z80_0_OFFSET,d0
		move.l	d0,Z80_Z0(a0)
		move.l	d0,Z80_zero(a0)

		move.l	Z80_Cachemem(a0),d0
		add.l	#CACHE_0_OFFSET,d0
		move.l	d0,Z80_CacheB(a0)
		move.l	d0,Z80_cachezero(a0)

		IFD	Z80_MEMCHECK
		move.l	Z80_Flagmem(a0),d0
		add.l	#FLAGS_0_OFFSET,d0
		move.l	d0,Z80_FlagsB(a0)
		move.l	d0,Z80_flagzero(a0)
		ENDC

		moveq	#0,d0
		rts	;return zero (No Error)

** ----------------------------------------------------------------------

** These routines access the Z80 address space, mirroring any changes
** in the cache and handling the wraparound of addresses transparently.
** They do *not* respect any memory protection flags - a write always
** takes effect.
** I recommend that they are used rathed than writing directly into
** the Z80 address space.
**
**	Z80_SetByte	(a0,d0,d1)	(ctrl, addr, BYTE val)
**	Z80_SetWordLH	(a0,d0,d1)	(ctrl, addr, WORD val)
**	Z80_GetByte	(a0,d0)		(ctrl, addr)
**	Z80_GetWordLH	(a0,d0)		(ctrl, addr)
**	Z80_SetBlock	(a0,d0,d1,d2)	(ctrl, start_addr, size, BYTE val)
**	Z80_ReadBlock	(a0,a1,d0,d1)	(ctrl, buf, start_addr, size)
**	Z80_WriteBlock	(a0,a1,d0,d1)	(ctrl, buf, start_addr, size)
**
**   All need a pointer to the control structure in a0. The Z80 address
** (word-sized) is passed in d0 (for block functions this is the
** block start address).
**   Z80_SetByte is passed a byte value to be written in d1. It returns
** nothing.
**   Z80_SetWordLH is passed a (high-end first) word value to be written
** in d1 and writes it low-end first. It returns nothing.
**   Z80_GetByte returns the byte value in d0.
**   Z80_GetWordLH reads a (low-end first) word value and returns it
** high-end first in d0.
**   All block functions are passed the block size (an unsigned longword)
** in d1. They return nothing.
**   Z80_SetBlock is passed the byte value to be written in d2.
**   Z80_ReadBlock and Z80_WriteBlock are passed the buffer address
** (in the 680x0 address space) in a1.
**   All Z80 address arithmetic is word-sized. For instance, calling
** Z80_SetWordLH(ctrl, $ffff, $1234) will set address $ffff to $34 and
** address $0000 to $12. The block functions will also wrap at $ffff.


Z80_SetByte	;(a0,d0,d1)	(ctrl, addr, BYTE val)
		move.l	a1,-(a7)
		move.l	Z80_zero(a0),a1
		move.b	d1,(a1,d0.w)
		move.l	Z80_cachezero(a0),a1
		add.w	d0,a1
		clr.w	(a1,d0.w)
		move.l	(a7)+,a1
		rts	;return nothing
** ------------

Z80_SetWordLH	;(a0,d0,d1)	(ctrl, addr, WORD val)
		move.l	a1,-(a7)
		movea.l	Z80_zero(a0),a1
		move.b	d1,(a1,d0.w)
		lsr.w	#8,d1
		addq.w	#1,d0	;second byte
		move.b	d1,(a1,d0.w)
		move.l	Z80_cachezero(a0),a1
		movea.l	a1,a0 ;keep cachezero
		add.w	d0,a1
		clr.w	(a1,d0.w) ;mark cache
		subq.w	#1,d0	;first byte
		movea.l	a0,a1 ;get cachezero
		add.w	d0,a1
		clr.w	(a1,d0.w) ;mark cache
		move.l	(a7)+,a1
		rts	;return nothing
** ------------

Z80_GetByte	;(a0,d0)		(ctrl, addr)
		movea.l	Z80_zero(a0),a0
		move.b	(a0,d0.w),d0
		ext.w	d0	;sign extend
		ext.l	d0
		rts	;return (signed) byte in d0
** ------------

Z80_GetWordLH	;(a0,d0)		(ctrl, addr)
		movea.l	Z80_zero(a0),a0
		move.w	d0,-(sp)	;create word on stack
		move.b	(a0,d0.w),1(sp)	;low byte
		addq.w	#1,d0
		move.b	(a0,d0.w),(sp)	;high byte
		move.w	(sp)+,d0
		ext.l	d0	;sign extend
		rts	;return (signed) word in d0
** ------------

Z80_SetBlock	;(a0,d0,d1,d2)	(ctrl, start_addr, size, BYTE val)
		movem.l	a1/a2,-(a7)
		movea.l	Z80_zero(a0),a1
		movea.l	Z80_cachezero(a0),a2
.loop		move.b	d2,(a1,d0.w)
		movea.l	a2,a0
		adda.w	d0,a0
		clr.w	(a0,d0.w) ;mark cache
		addq.w	#1,d0
		subq.l	#1,d1
		bne.s	.loop
		movem.l	(a7)+,a1/a2
		rts	;return nothing
** ------------

Z80_ReadBlock	;(a0,a1,d0,d1)	(ctrl, buf, start_addr, size)
		movea.l	Z80_zero(a0),a0
.loop		move.b	(a0,d0.w),(a1)+
		addq.w	#1,d0
		subq.l	#1,d1
		bne.s	.loop
		rts	;return nothing
** ------------

Z80_WriteBlock	;(a0,a1,d0,d1)	(ctrl, buf, start_addr, size)
		movem.l	a2/a3,-(a7)
		movea.l	Z80_zero(a0),a2
		movea.l	Z80_cachezero(a0),a3
.loop		move.b	(a1)+,(a2,d0.w)
		movea.l	a3,a0
		adda.w	d0,a0
		clr.l	(a0,d0.w) ;mark cache
		addq.w	#1,d0
		subq.l	#1,d1
		bne.s	.loop
		movem.l	(a7)+,a2/a3
		rts	;return nothing

** ------------------------------------------------------------------------

** This routine sets Z80 memory control flags. If the Z80_Flagmem field
** in the control structure is zero, the function has no effect.
**	Z80_SetMemFlag	(a0,d0,d1,d2)	(ctrl, start_addr, size, flag)
**
** As for the memory access functions, the Z80 address is word-sized and
** passed in d0, and the size is an unsigned longword. The flag is a
** byte-sized value, and its possible meanings are defined in Z80.i.
** Nothing is returned.

Z80_SetMemFlag	;(a0,d0,d1,d2)	(ctrl, start_addr, size, flag)
		tst.l	Z80_Flagmem(a0)
		beq.s	.end
		move.l	Z80_flagzero(a0),a0
.loop		move.b	d2,(a0,d0.w)
		addq.w	#1,d0
		subq.l	#1,d1
		bne.s	.loop
.end		rts	;return nothing


** This routine returns the memory control flag for an address, in case
** you should forget it. If the Z80_Flagmem field in the control
** structure is zero, the function has no effect, and returns zero (RAM).
**	Z80_GetMemFlag	(a0,d0)	(ctrl, addr)
**
** The Z80 address is word-sized and passed in d0. The flag value is
** returned in (the whole of) d0, and has the range -128 to +127.

Z80_GetMemFlag	;(a0,d0)	(ctrl, addr)
		tst.l	Z80_Flagmem(a0)
		beq.s	.end
		move.l	Z80_flagzero(a0),d1
		move.b	(a0,d0.w),d0
		ext.w	d0
		ext.l	d0
.end		rts	;return flag in d0

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