From 2d168babe9c17459959815e1a2ede88ed639c48f Mon Sep 17 00:00:00 2001 From: cuz Date: Wed, 20 Aug 2003 10:17:53 +0000 Subject: [PATCH] Split memcpy and memmove, since the former is used a lot more often than the latter. Optimized the code for smaller size and greater speed. git-svn-id: svn://svn.cc65.org/cc65/trunk@2382 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/common/Makefile | 1 + libsrc/common/memcpy.s | 145 ++++++++++++++-------------------------- libsrc/common/memmove.s | 67 +++++++++++++++++++ 3 files changed, 119 insertions(+), 94 deletions(-) create mode 100644 libsrc/common/memmove.s diff --git a/libsrc/common/Makefile b/libsrc/common/Makefile index 3d4ce5592..21ed8aa29 100644 --- a/libsrc/common/Makefile +++ b/libsrc/common/Makefile @@ -109,6 +109,7 @@ S_OBJS = _cwd.o \ memchr.o \ memcmp.o \ memcpy.o \ + memmove.o \ memset.o \ modfree.o \ modload.o \ diff --git a/libsrc/common/memcpy.s b/libsrc/common/memcpy.s index 4ef141df0..b61b82c1f 100644 --- a/libsrc/common/memcpy.s +++ b/libsrc/common/memcpy.s @@ -1,113 +1,70 @@ ; -; void* memcpy (void* dest, const void* src, size_t n); -; void* memmove (void* dest, const void* src, size_t n); +; Ullrich von Bassewitz, 2003-08-20 ; -; Ullrich von Bassewitz, 10.12.1998 +; void* __fastcall__ memcpy (void* dest, const void* src, size_t n); +; +; NOTE: This function contains entry points for memmove, which will ressort +; to memcpy for an upwards copy. Don't change this module without looking +; at memmove! ; - .export _memcpy, _memmove - .import popax - .importzp ptr1, ptr2, ptr3, tmp1, tmp2 + .export _memcpy, memcpy_upwards, memcpy_getparams + .import popax + .importzp ptr1, ptr2, ptr3, tmp1 ; ---------------------------------------------------------------------- _memcpy: - jsr getparms ; Get the parameters from stack - -; Copy upwards - -copyup: ldy #0 ; set up to move 256 - ldx tmp2 ; hi byte of n - beq @L2 - -@L1: lda (ptr1),y ; get a byte - sta (ptr2),y ; store it - iny - bne @L1 - inc ptr1+1 ; bump ptrs - inc ptr2+1 - dex - bne @L1 ; do another block - -@L2: ldx tmp1 ; get low byte of n - beq done ; jump if done - -@L3: lda (ptr1),y ; get a byte - sta (ptr2),y ; store it - iny - dex - bne @L3 - -done: lda ptr3 - ldx ptr3+1 ; get function result (dest) + jsr memcpy_getparams + +memcpy_upwards: + ldy #0 + ldx ptr3 ; Get low counter byte + +; Copy loop + +@L1: inx ; Bump low counter byte + beq @L2 ; Jump on overflow + lda (ptr1),y + sta (ptr2),y + iny + bne @L1 + inc ptr1+1 ; Bump pointers + inc ptr2+1 + bne @L1 ; Branch always +@L2: inc ptr3+1 ; Bump high counter byte + bne @L1 + +; Done. The low byte of dest is still in ptr2 + +done: lda ptr2 + ldx tmp1 ; get function result (dest) rts - ; ---------------------------------------------------------------------- -_memmove: - jsr getparms ; Get the parameters from stack - - cpx ptr1+1 ; dest > src? - bne @L1 - cmp ptr1 -@L1: beq done ; Both pointers are equal - nothing to copy - bcc copyup ; Copy upwards - -; Copy downwards - - clc - lda ptr1+1 - adc tmp2 - sta ptr1+1 - - clc - lda ptr2+1 - adc tmp2 - sta ptr2+1 - -; Copy the incomplete page - - ldy tmp1 ; Get low byte of count - beq @L3 - -@L2: dey - lda (ptr1),y - sta (ptr2),y - tya ; Test Y - bne @L2 ; Jump if not zero - -; Copy complete pages - -@L3: ldx tmp2 ; Get hi byte of count - beq done - -@L4: dec ptr1+1 - dec ptr2+1 -@L5: dey - lda (ptr1),y - sta (ptr2),y - tya - bne @L5 - dex - bne @L4 - -; Done +; Get the parameters from stack as follows: +; +; -(size-1) --> ptr3 +; src --> ptr1 +; dest --> ptr2 +; high(dest) --> tmp1 +; +; dest is returned in a/x. - beq done +memcpy_getparams: + eor #$FF + sta ptr3 + txa + eor #$FF + sta ptr3+1 ; Save -(size-1) -; ---------------------------------------------------------------------- -; Get the parameters from stack - -getparms: - sta tmp1 ; Save n - stx tmp2 jsr popax ; src sta ptr1 stx ptr1+1 + jsr popax ; dest sta ptr2 - stx ptr2+1 ; save work copy - sta ptr3 - stx ptr3+1 ; save function result - rts + stx ptr2+1 ; Save work copy + stx tmp1 ; Save for function result + rts diff --git a/libsrc/common/memmove.s b/libsrc/common/memmove.s new file mode 100644 index 000000000..f344f9df8 --- /dev/null +++ b/libsrc/common/memmove.s @@ -0,0 +1,67 @@ +; +; Ullrich von Bassewitz, 2003-08-20 +; +; 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 + .importzp ptr1, ptr2, ptr3, ptr4, tmp1 + + .macpack generic + .macpack longbranch + +; ---------------------------------------------------------------------- +_memmove: + sta ptr4 + stx ptr4+1 ; Size -> ptr4 + + 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 ptr4+1 + sta ptr1+1 + + lda ptr2+1 + add ptr4+1 + sta ptr2+1 + +; Load the low offset into Y, and the counter low byte into X. + + ldy ptr4 + ldx ptr3 + jmp @L2 + +; Copy loop + +@L1: dey + lda (ptr1),y + sta (ptr2),y + +@L2: inx ; Bump counter low byte + bne @L1 + dec ptr1+1 + dec ptr2+1 + inc ptr3+1 ; Bump counter high byte + bne @L1 + +; Done, return dest + +done: lda ptr2 + ldx tmp1 ; get function result (dest) + rts + -- 2.39.5