1 /* @(#)movebytes.c	1.18 09/10/17 Copyright 1985, 1989, 1995-2009 J. Schilling */
2 /*
3  *	move data
4  *
5  *	Copyright (c) 1985, 1989, 1995-2009 J. Schilling
6  */
7 /*
8  * The contents of this file are subject to the terms of the
9  * Common Development and Distribution License, Version 1.0 only
10  * (the "License").  You may not use this file except in compliance
11  * with the License.
12  *
13  * See the file CDDL.Schily.txt in this distribution for details.
14  * A copy of the CDDL is also available via the Internet at
15  * http://www.opensource.org/licenses/cddl1.txt
16  *
17  * When distributing Covered Code, include this CDDL HEADER in each
18  * file and include the License file CDDL.Schily.txt from this distribution.
19  */
20 
21 #include <schily/standard.h>
22 #include <schily/align.h>
23 #include <schily/types.h>
24 #include <schily/schily.h>
25 
26 #define	DO8(a)	a; a; a; a; a; a; a; a;
27 
28 /*
29  * movebytes(from, to, cnt) is the same as memmove(to, from, cnt)
30  */
31 EXPORT char *
movebytes(fromv,tov,cnt)32 movebytes(fromv, tov, cnt)
33 	const void	*fromv;
34 	void		*tov;
35 	ssize_t		cnt;
36 {
37 	register const char	*from	= fromv;
38 	register char		*to	= tov;
39 	register ssize_t	n;
40 
41 	/*
42 	 * If we change cnt to be unsigned, check for == instead of <=
43 	 */
44 	if ((n = cnt) <= 0)
45 		return (to);
46 
47 	if (from >= to) {
48 		/*
49 		 * source is on higher addresses than destination:
50 		 *	move bytes forwards
51 		 */
52 		if (n >= (ssize_t)(8 * sizeof (long))) {
53 			if (l2aligned(from, to)) {
54 				register const long *froml = (const long *)from;
55 				register long *tol = (long *)to;
56 				register ssize_t rem = n % (8 * sizeof (long));
57 
58 				n /= (8 * sizeof (long));
59 				do {
60 					DO8 (*tol++ = *froml++);
61 				} while (--n > 0);
62 
63 				from = (const char *)froml;
64 				to = (char *)tol;
65 				n = rem;
66 			}
67 
68 			if (n >= 8) {
69 				n -= 8;
70 				do {
71 					DO8 (*to++ = *from++);
72 				} while ((n -= 8) >= 0);
73 				n += 8;
74 			}
75 
76 			if (n > 0) do {
77 				*to++ = *from++;
78 			} while (--n > 0);
79 			return (to);
80 		}
81 		if (n > 0) do {
82 			*to++ = *from++;
83 		} while (--n > 0);
84 		return (to);
85 	} else {
86 		char *ep;
87 
88 		/*
89 		 * source is on lower addresses than destination:
90 		 *	move bytes backwards
91 		 */
92 		to += n;
93 		from += n;
94 		ep = to;
95 		if (n >= (ssize_t)(8 * sizeof (long))) {
96 			if (l2aligned(from, to)) {
97 				register const long *froml = (const long *)from;
98 				register long *tol = (long *)to;
99 				register ssize_t rem = n % (8 * sizeof (long));
100 
101 				n /= (8 * sizeof (long));
102 				do {
103 					DO8 (*--tol = *--froml);
104 				} while (--n > 0);
105 
106 				from = (const char *)froml;
107 				to = (char *)tol;
108 				n = rem;
109 			}
110 			if (n >= 8) {
111 				n -= 8;
112 				do {
113 					DO8 (*--to = *--from);
114 				} while ((n -= 8) >= 0);
115 				n += 8;
116 			}
117 			if (n > 0) do {
118 				*--to = *--from;
119 			} while (--n > 0);
120 			return (ep);
121 		}
122 		if (n > 0) do {
123 			*--to = *--from;
124 		} while (--n > 0);
125 		return (ep);
126 	}
127 }
128