2015-10-23 22:02:21 +00:00
|
|
|
;
|
|
|
|
; 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 22:04:46 +00:00
|
|
|
; 2015-11-02, Greg King
|
2015-10-23 22:02:21 +00:00
|
|
|
;
|
|
|
|
; void* __fastcall__ memcpy (void* dest, const void* src, size_t size);
|
|
|
|
;
|
2015-11-07 04:59:19 +00:00
|
|
|
; 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"!
|
2015-10-23 22:02:21 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
.export _memcpy
|
|
|
|
.export memcpy_increment, memcpy_transfer, memcpy_getparams
|
|
|
|
|
2018-05-20 13:30:18 +00:00
|
|
|
.import incsp2, popax, popptr1
|
2015-10-23 22:02:21 +00:00
|
|
|
.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:
|
2015-11-07 05:29:07 +00:00
|
|
|
ldy #$73 ; TII opcode
|
2015-10-23 22:02:21 +00:00
|
|
|
|
|
|
|
memcpy_transfer:
|
2015-11-07 05:29:07 +00:00
|
|
|
sty transfer + opcode
|
2015-10-23 22:02:21 +00:00
|
|
|
|
|
|
|
lda ptr1
|
|
|
|
ldx ptr1+1
|
2015-11-07 05:29:07 +00:00
|
|
|
sta transfer + source
|
|
|
|
stx transfer + source+1
|
2015-10-23 22:02:21 +00:00
|
|
|
|
|
|
|
lda ptr2
|
|
|
|
ldx ptr2+1
|
2015-11-07 05:29:07 +00:00
|
|
|
sta transfer + destination
|
|
|
|
stx transfer + destination+1
|
2015-10-23 22:02:21 +00:00
|
|
|
|
|
|
|
lda ptr3
|
|
|
|
ldx ptr3+1
|
2015-11-07 05:29:07 +00:00
|
|
|
sta transfer + length
|
|
|
|
stx transfer + length+1
|
2015-10-23 22:02:21 +00:00
|
|
|
|
|
|
|
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
|
2015-11-02 22:04:46 +00:00
|
|
|
ora ptr3+1
|
|
|
|
bne @L1
|
2015-10-23 22:02:21 +00:00
|
|
|
|
2015-11-02 22:04:46 +00:00
|
|
|
; 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
|
|
|
|
|
2018-05-20 13:30:18 +00:00
|
|
|
@L1: jsr popptr1 ; save src
|
2015-10-23 22:02:21 +00:00
|
|
|
|
2015-11-02 22:04:46 +00:00
|
|
|
; (Direct stack access is six cycles faster [total cycle count].)
|
2015-10-23 22:02:21 +00:00
|
|
|
|
2018-05-20 13:30:18 +00:00
|
|
|
iny ; (Y=0 by popptr1, need '1' here) save dest
|
2015-10-23 22:02:21 +00:00
|
|
|
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.
|
2017-02-01 16:52:30 +00:00
|
|
|
; Therefore, we must build the instruction in the DATA segment.
|
2015-10-23 22:02:21 +00:00
|
|
|
|
|
|
|
.data
|
|
|
|
|
|
|
|
transfer:
|
|
|
|
tii $FFFF, $FFFF, $0001
|
2015-11-02 22:04:46 +00:00
|
|
|
jmp popax ; get pointer; return it as result
|