Hi-Tech memcpy

by Isaac Marino Bavaresco

This routine is a substitution for the one in the Hi-Tech PICC compiler library.

The original has some limitations that I wanted to overcome:
1 - The data destination must always be in bank 0 or bank 1.
2 - If the data source is in program memory (retlw table) it must be 256 entries long or less, and it must not cross a 256 instruction address boundary.

My version can copy data to any RAM bank, from any RAM bank or a retlw table, without any size or alignment restriction. Besides, it is over twice as fast as the original.

There are draw-backs tough:
1 - The parameter 'Dst' is declared 'const void *', when it should be declared 'void *', but a non-const pointer can point only to banks 0 and 1 or to banks 2 and 3, never to all banks. It's no problem if the programmer is a bit careful.
2 - the function returns 'void', where it should return 'void *'. I did this to save some RAM and execution time (I personally never used the return from memcpy, as it is the same destination pointer I already have). If one needs it the right way, it is easy to fix.

Note:
If a pointer to program memory is passed to 'Dst', the function returns without doing nothing.

;==============================================================================
; Copyright (c) 2008, Isaac Marino Bavaresco
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;     * Redistributions of source code must retain the above copyright
;       notice, this list of conditions and the following disclaimer.
;     * Neither the name of the author nor the
;       names of its contributors may be used to endorse or promote products
;       derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;==============================================================================
; isaacbavaresco@yahoo.com.br
;==============================================================================
INDF		equ	0
PCL		equ	2
STATUS		equ	3
FSR		equ	4
PCLATH		equ	10
;===============================================================================
_memcpy$Dst	set	?_memcpy+0
_memcpy$DstBnk	set	?_memcpy+1
_memcpy$Src	set	?_memcpy+2
_memcpy$SrcBnk	set	?_memcpy+3
_memcpy$Len	set	?_memcpy+4
;===============================================================================
; void memcpy( const void *Dst, const void *Src, unsigned char Len )

		psect	text0,local,class=CODE,delta=2

		global	_memcpy
		signat	_memcpy,0x3078
		fnsize	_memcpy,0,5
		global	?_memcpy

_memcpy:	clrf	STATUS
		;---------------------------------------------------------------
		btfss	_memcpy$DstBnk,7	; if( !( Dst & 0x8000 ))
DstInROM:	return				;    return;

		incf	_memcpy$Len,f
		;---------------------------------------------------------------
DstInRAM:	btfsc	_memcpy$SrcBnk,7	; if( Src & 0x8000 )
		goto	SrcInRAMTest
		;---------------------------------------------------------------
SrcInROM:	btfsc	_memcpy$DstBnk,0
		bsf	STATUS,7
		movf	_memcpy$Dst,w
		movwf	FSR
		
		goto	SrcInROMTest
		;---------------------------------------------------------------
SrcInROMLoop:	call	LookUp

		movwf	INDF

		pagesel	$

		incfsz	_memcpy$Src,f
		goto	$+2
		incf	_memcpy$SrcBnk,f

		incf	FSR,f

SrcInROMTest:	decfsz	_memcpy$Len,f
		goto	SrcInROMLoop
		return
		;---------------------------------------------------------------
LookUp:		movf	_memcpy$SrcBnk,w
		movwf	PCLATH
		movf	_memcpy$Src,w
		movwf	PCL
		;---------------------------------------------------------------
SrcInRAM:	bcf	STATUS,7
		btfsc	_memcpy$SrcBnk,0
		bsf	STATUS,7
		movf	_memcpy$Src,w
		movwf	FSR

		movf	INDF,w
		movwf	btemp+0

		bcf	STATUS,7
		btfsc	_memcpy$DstBnk,0
		bsf	STATUS,7
		movf	_memcpy$Dst,w
		movwf	FSR

		movf	btemp+0,w
		movwf	INDF

		incf	_memcpy$Src,f
		incf	_memcpy$Dst,f

SrcInRAMTest:	decfsz	_memcpy$Len,f
		goto	SrcInRAM
		return
;===============================================================================
		psect	temp,ovrld,class=BANK0,space=1
btemp		ds	1
;===============================================================================