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  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file CDDL.Schily.txt from this distribution.
17  */
18 
19 #include <schily/standard.h>
20 #include <schily/align.h>
21 #include <schily/types.h>
22 #include <schily/schily.h>
23 
24 #define	DO8(a)	a; a; a; a; a; a; a; a;
25 
26 /*
27  * movebytes(from, to, cnt) is the same as memmove(to, from, cnt)
28  */
29 EXPORT char *
30 movebytes(fromv, tov, cnt)
31 	const void	*fromv;
32 	void		*tov;
33 	ssize_t		cnt;
34 {
35 	register const char	*from	= fromv;
36 	register char		*to	= tov;
37 	register ssize_t	n;
38 
39 	/*
40 	 * If we change cnt to be unsigned, check for == instead of <=
41 	 */
42 	if ((n = cnt) <= 0)
43 		return (to);
44 
45 	if (from >= to) {
46 		/*
47 		 * source is on higher addresses than destination:
48 		 *	move bytes forwards
49 		 */
50 		if (n >= (ssize_t)(8 * sizeof (long))) {
51 			if (l2aligned(from, to)) {
52 				register const long *froml = (const long *)from;
53 				register long *tol = (long *)to;
54 				register ssize_t rem = n % (8 * sizeof (long));
55 
56 				n /= (8 * sizeof (long));
57 				do {
58 					DO8 (*tol++ = *froml++);
59 				} while (--n > 0);
60 
61 				from = (const char *)froml;
62 				to = (char *)tol;
63 				n = rem;
64 			}
65 
66 			if (n >= 8) {
67 				n -= 8;
68 				do {
69 					DO8 (*to++ = *from++);
70 				} while ((n -= 8) >= 0);
71 				n += 8;
72 			}
73 
74 			if (n > 0) do {
75 				*to++ = *from++;
76 			} while (--n > 0);
77 			return (to);
78 		}
79 		if (n > 0) do {
80 			*to++ = *from++;
81 		} while (--n > 0);
82 		return (to);
83 	} else {
84 		char *ep;
85 
86 		/*
87 		 * source is on lower addresses than destination:
88 		 *	move bytes backwards
89 		 */
90 		to += n;
91 		from += n;
92 		ep = to;
93 		if (n >= (ssize_t)(8 * sizeof (long))) {
94 			if (l2aligned(from, to)) {
95 				register const long *froml = (const long *)from;
96 				register long *tol = (long *)to;
97 				register ssize_t rem = n % (8 * sizeof (long));
98 
99 				n /= (8 * sizeof (long));
100 				do {
101 					DO8 (*--tol = *--froml);
102 				} while (--n > 0);
103 
104 				from = (const char *)froml;
105 				to = (char *)tol;
106 				n = rem;
107 			}
108 			if (n >= 8) {
109 				n -= 8;
110 				do {
111 					DO8 (*--to = *--from);
112 				} while ((n -= 8) >= 0);
113 				n += 8;
114 			}
115 			if (n > 0) do {
116 				*--to = *--from;
117 			} while (--n > 0);
118 			return (ep);
119 		}
120 		if (n > 0) do {
121 			*--to = *--from;
122 		} while (--n > 0);
123 		return (ep);
124 	}
125 }
126