;
-; 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
--- /dev/null
+;
+; 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
+