File: memcpy.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (104 lines) | stat: -rw-r--r-- 3,133 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
;
; 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