;
; Ullrich von Bassewitz, 2003-08-20
; Performance increase (about 20%) by
; Christian Krueger, 2009-09-13
;
; void* __fastcall__ memmove (void* dest, const void* src, size_t size);
;
; NOTE: This function uses entry points from memcpy!
;

       	.export	    	_memmove
        .import         memcpy_getparams, memcpy_upwards, popax
       	.importzp      	ptr1, ptr2, ptr3, ptr4, tmp1

        .macpack        generic
        .macpack        longbranch

; ----------------------------------------------------------------------
_memmove:
        jsr     memcpy_getparams

; Check for the copy direction. If dest < src, we must copy upwards (start at
; low addresses and increase pointers), otherwise we must copy downwards
; (start at high addresses and decrease pointers).

        sec
        sbc     ptr1
        txa
        sbc     ptr1+1
        jcc     memcpy_upwards  ; Branch if dest < src (upwards copy)

; Copy downwards. Adjust the pointers to the end of the memory regions.

        lda	ptr1+1
       	add	ptr3+1
	sta	ptr1+1

	lda	ptr2+1
	add	ptr3+1
	sta	ptr2+1

; handle fractions of a page size first

	ldy	ptr3		; count, low byte
	bne	@entry		; something to copy?
	beq	PageSizeCopy	; here like bra...

@copyByte:
	lda	(ptr1),y
	sta     (ptr2),y
@entry:
	dey
	bne	@copyByte
	lda	(ptr1),y	; copy remaining byte
	sta     (ptr2),y

PageSizeCopy:			; assert Y = 0
	ldx	ptr3+1		; number of pages
	beq	done		; none? -> done

@initBase:
	dec	ptr1+1		; adjust base...
	dec	ptr2+1
	dey			; in entry case: 0 -> FF
        lda     (ptr1),y	; need to copy this 'intro byte'
        sta     (ptr2),y	; to 'land' later on Y=0! (as a result of the '.repeat'-block!)
	dey			; FF ->FE
@copyBytes:
	.repeat 2		; Unroll this a bit to make it faster...
        lda     (ptr1),y
        sta     (ptr2),y
	dey
	.endrepeat
@copyEntry:			; in entry case: 0 -> FF
	bne	@copyBytes
	lda     (ptr1),y	; Y = 0, copy last byte
        sta     (ptr2),y
	dex			; one page to copy less
	bne	@initBase	; still a page to copy?

; Done, return dest

done:  	jmp	popax		; Pop ptr and return as result
                
