extern int memcmp (void _generic *, void _generic *, int ) ;
extern void _generic *memset (void _generic *, unsigned char , int ) ;
+#if SDCC_ds390
+extern void _xdata *memcpyx(void _xdata *, void _xdata *, int);
+#endif
+
#endif
#endif
--- /dev/null
+#include <string.h>
+
+void _xdata * memcpyx (
+ void _xdata * dst,
+ void _xdata * src,
+ int count
+ )
+{
+ /* Shut compiler up about unused parameters. */
+ dst; src; count;
+
+/* AUTO_TOGGLE uses the '390 DPTS toggle bit. */
+#define AUTO_TOGGLE
+_asm
+ ; Destination is in DPTR. Save it on stack so we can return it at end.
+
+ push dpx
+ push dph
+ push dpl
+
+ mov dps, #1 ; Alternate DPTR.
+
+ ; count is in _memcpyx_PARM_3
+ mov dptr, #_memcpyx_PARM_3
+ movx a, @dptr
+ inc dptr
+ mov r2, a
+ movx a, @dptr
+ mov r3, a
+
+ ; src is in _memcpyx_PARM_2
+ mov dptr, #_memcpyx_PARM_2
+ movx a, @dptr
+ inc dptr
+ push acc
+ movx a, @dptr
+ inc dptr
+ push acc
+ movx a, @dptr
+ mov dpx1, a
+ pop dph1
+ pop dpl1
+
+#ifdef AUTO_TOGGLE
+ mov dps, #21 ; Current DPTR is alt DPTR, toggle after each op.
+#else
+ mov dps, #0 ; Current DPTR is normal DPTR, no toggle.
+#endif
+
+ ; src is in alt DPTR, dst is in normal DPTR, count is in r2/r3.
+
+ ; If we have zero bytes to copy, quick out.
+ mov a, r2
+ orl a, r3
+ jz _memcpy_done
+
+ ; increment r3 if r2 != 0 (makes djnz end-of-loop sequence possible).
+ inc r3
+ cjne r2, #0, _memcpyx_loopTop
+ dec r3
+
+_memcpyx_loopTop:
+
+#ifdef AUTO_TOGGLE
+ movx a, @dptr
+ movx @dptr, a
+ inc dptr
+ inc dptr
+#else
+ inc dps
+ movx a, @dptr
+ inc dptr
+ dec dps
+ movx @dptr, a
+ inc dptr
+#endif
+
+ djnz r2, _memcpyx_loopTop
+ djnz r3, _memcpyx_loopTop
+
+_memcpy_done:
+
+#ifdef AUTO_TOGGLE
+ mov dps, #0
+#endif
+
+ pop dpl
+ pop dph
+ pop dpx
+_endasm;
+
+}