* device/include/ds400rom.h,
[fw/sdcc] / device / lib / ds400 / memcpyx.c
1 #include <string.h>
2
3 // FIXME: can optimize even further on '400 with auto-increment/auto-toggle.
4
5 void __xdata * memcpyx (
6         void __xdata * dst,
7         void __xdata * src,
8         int count
9         ) __naked
10 {
11     /* Shut compiler up about unused parameters. */
12     dst; src; count;
13     
14 __asm
15     ; Destination is in DPTR. Save it on stack so we can return it at end.
16     
17     push dpx
18     push dph
19     push dpl
20     
21     mov  dps, #0x1        ; Alternate DPTR.
22     
23     ; count  is in _memcpyx_PARM_3
24     mov  dptr, #_memcpyx_PARM_3
25     movx a, @dptr
26     inc dptr
27     mov r2, a
28     movx a, @dptr
29     mov r3, a
30
31     ; src is in _memcpyx_PARM_2
32     mov  dptr, #_memcpyx_PARM_2
33     movx a, @dptr
34     inc  dptr
35     push acc
36     movx a, @dptr
37     inc  dptr
38     push acc
39     movx a, @dptr
40     mov  dpx1, a
41     pop  dph1
42     pop  dpl1
43
44     mov dps, #0x21      ; Current DPTR is alt DPTR, toggle after each op.
45     
46     ; src is in alt DPTR, dst is in normal DPTR, count is in r2/r3.
47     
48     ; If we have zero bytes to copy, quick out.
49     mov  a, r2
50     orl  a, r3
51     jz   _memcpy_done
52
53     ; increment r3 if r2 != 0 (makes djnz end-of-loop sequence possible).
54     inc r3
55     cjne r2, #0x0, _memcpyx_loopTop
56     dec r3
57
58 _memcpyx_loopTop:
59
60     movx a, @dptr
61     movx @dptr, a
62     inc dptr
63     inc dptr
64
65     djnz r2, _memcpyx_loopTop
66     djnz r3, _memcpyx_loopTop
67     
68 _memcpy_done:
69
70     mov dps, #0x0
71
72     pop dpl
73     pop dph
74     pop dpx
75     ret
76 __endasm;    
77     
78 }