cc65/libsrc/pce/memcpy.s

105 lines
3.1 KiB
ArmAsm

;
; This file, instead of "common/memcpy.s", will be assembled for the pce
; target. This version is smaller and faster because it uses the HuC6280's
; block-copy instructions.
;
; 2003-08-20, Ullrich von Bassewitz
; 2015-11-02, Greg King
;
; void* __fastcall__ memcpy (void* dest, const void* src, size_t size);
;
; NOTE: This function contains entry points for memmove(), which resorts to
; memcpy() for incrementing copies. The PC-Engine memset() uses this memcpy()
; to fill memory quickly. Don't change this module without looking at
; "pce/memmove.s" and "pce/memset.s"!
;
.export _memcpy
.export memcpy_increment, memcpy_transfer, memcpy_getparams
.import incsp2, popax, popptr1
.importzp sp, ptr1, ptr2, ptr3
; The structure of the transfer instructions
.struct
opcode .byte
source .addr
destination .addr
length .word
.endstruct
; ----------------------------------------------------------------------
_memcpy:
jsr memcpy_getparams
memcpy_increment:
ldy #$73 ; TII opcode
memcpy_transfer:
sty transfer + opcode
lda ptr1
ldx ptr1+1
sta transfer + source
stx transfer + source+1
lda ptr2
ldx ptr2+1
sta transfer + destination
stx transfer + destination+1
lda ptr3
ldx ptr3+1
sta transfer + length
stx transfer + length+1
jmp transfer
; ----------------------------------------------------------------------
; Get the parameters from the stack, as follows:
;
; size --> ptr3
; src --> ptr1
; dest --> ptr2
;
; The first argument (dest) will remain on the stack; and, is returned in .XA!
memcpy_getparams:
sta ptr3
stx ptr3+1 ; save size
ora ptr3+1
bne @L1
; The size is zero; copy nothing; just return the dest address.
; (The HuC6280's transfer instructions can't copy $0000 bytes;
; they would copy $10000 [64K] bytes instead.)
ply ; drop return address
plx
jsr incsp2 ; drop src address
jmp popax ; get pointer; return it as result
@L1: jsr popptr1 ; save src
; (Direct stack access is six cycles faster [total cycle count].)
iny ; (Y=0 by popptr1, need '1' here) save dest
lda (sp),y ; get high byte
tax
lda (sp) ; get low byte
sta ptr2
stx ptr2+1
rts ; return dest address (for memmove)
; ----------------------------------------------------------------------
; The transfer instructions use inline arguments.
; Therefore, we must build the instruction in the DATA segment.
.data
transfer:
tii $FFFF, $FFFF, $0001
jmp popax ; get pointer; return it as result