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