1/*
2 * memmove routine for Z8000
3 * Copyright (C) 2004 Christian Groessler <chris@groessler.org>
4 *
5 * Permission to use, copy, modify, and distribute this file
6 * for any purpose is hereby granted without fee, provided that
7 * the above copyright notice and this notice appears in all
8 * copies.
9 *
10 * This file is distributed WITHOUT ANY WARRANTY; without even the implied
11 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 */
13
14/* void *memmove(void *dest, const void *src, size_t length);
15 */
16
17#include <picolibc.h>
18
19	name	"memmove.S"
20
21	.text
22	even
23global	_memmove
24
25_memmove:
26
27#ifdef __Z8001__
28	segm
29
30#ifdef __STD_CALL__
31	ldl	rr6,rr14(#4)
32	ldl	rr4,rr14(#8)
33	ldl	rr2,rr14(#12)
34#else
35	pushl	@rr14,rr6
36#endif
37
38/* rr2  - length	(high word ignored)
39 * rr4  - src
40 * rr6  - dest
41 */
42
43	testl	rr2
44	jr	z,finish
45
46/*  check for destructive overlap (src < dest && dest < src + length) */
47
48	cpl	rr6,rr4
49	jp	ule,memmove_entry	/* non-destructive, let memcpy do the work */
50	ldl	rr0,rr2
51	addl	rr0,rr4			/* rr0 = src + length */
52	cpl	rr0,rr6
53	jp	ult,memmove_entry	/* non-destructive, let memcpy do the work */
54
55/* set-up pointers to copy backwards, add (length - 1) */
56	addl	rr4,rr2			/* src + length */
57	addl	rr6,rr2			/* dest + length */
58	subl	rr4,#1
59	subl	rr6,#1
60
61/* check alignment */
62	bitb	rl7,#0		/* odd destination address? */
63	jr	z,testsrc
64	bitb	rl5,#0		/* odd source address? */
65	jr	z,odd_copy
66	jr	even_copy
67
68testsrc:
69	bitb	rl5,#0
70	jr	nz,odd_copy	/* src even, dest odd */
71	lddb	@rr6,@rr4,r3
72	jr	ov,finish	/* jump if r5 is zero now */
73
74/* copy words */
75even_copy:
76	ld	r2,r3			/* remember length */
77	srl	r3,#1
78/*	jr	z,no_words	   it cannot be zero here */
79
80	dec	r5,#1
81	dec	r7,#1
82	lddr	@rr6,@rr4,r3
83
84no_words:
85	bitb	rl2,#0		/* odd length? */
86	jr	z,finish
87	inc	r5,#1
88	inc	r7,#1
89	lddb	@rr6,@rr4,r2	/* yes, copy last byte */
90	jr	finish
91
92/* copy bytes */
93odd_copy:
94	lddrb	@rr6,@rr4,r3
95
96finish:
97#ifdef __STD_CALL__
98	ldl	rr6,rr14(#4)
99#else
100	popl	rr2,@rr14
101#endif
102
103
104#else		/* above Z8001, below Z8002 */
105
106
107	unsegm
108
109#ifdef __STD_CALL__
110	ld	r7,r15(#2)
111	ld	r6,r15(#4)
112	ld	r5,r15(#6)
113#else
114	ld	r2,r7		/* buffer pointer return value */
115#endif
116
117/* r5  - length
118 * r6  - src
119 * r7  - dest
120 */
121	test	r5
122	jr	z,finish
123
124/*  check for destructive overlap (src < dest && dest < src + length) */
125
126	cp	r7,r6
127	jp	ule,memmove_entry	/* non-destructive, let memcpy do the work */
128	ld	r0,r5
129	add	r0,r6			/* r0 = src + length */
130	cp	r0,r7
131	jp	ult,memmove_entry	/* non-destructive, let memcpy do the work */
132
133/* set-up pointers to copy backwards, add (length - 1) */
134	add	r6,r5			/* src + length */
135	add	r7,r5			/* dest + length */
136	dec	r6,#1
137	dec	r7,#1
138
139/* check alignment */
140	bitb	rl7,#0		/* odd destination address? */
141	jr	z,testsrc
142	bitb	rl6,#0		/* odd source address? */
143	jr	z,odd_copy
144	jr	even_copy
145
146testsrc:
147	bitb	rl6,#0
148	jr	nz,odd_copy	/* src even, dest odd */
149	lddb	@r7,@r6,r5
150	jr	ov,finish	/* jump if r5 is zero now */
151
152/* copy words */
153even_copy:
154	ld	r4,r5		/* remember length */
155	srl	r5,#1
156/*	jr	z,no_words	   it cannot be zero here */
157
158	dec	r6,#1
159	dec	r7,#1
160	lddr	@r7,@r6,r5
161
162no_words:
163	bitb	rl4,#0		/* odd length? */
164	jr	z,finish
165	inc	r6,#1
166	inc	r7,#1
167	lddb	@r7,@r6,r4	/* yes, copy last byte */
168	jr	finish
169
170/* copy bytes */
171odd_copy:
172	lddrb	@r7,@r6,r5
173
174finish:
175#ifdef __STD_CALL__
176	ld	r7,r15(#2)
177#endif
178
179#endif	/* Z8002 */
180
181	ret
182	.end
183