amath  1.8.5
Simple command line calculator
memcpy.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 1990, 1993
3  * The Regents of the University of California. All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /**
34  * @file memcpy.c
35  * @brief Copy a block of memory, handling overlap.
36  *
37  * Code originate from FreeBSD base, revision 229286.
38  *
39  * The original source code can be obtained from:
40  * https://svnweb.freebsd.org/base/head/lib/libc/string/bcopy.c?revision=229286
41  *
42  */
43 
44 #include "amathc.h"
45 
46 #if __GNUC__ > 2
47 #pragma GCC diagnostic ignored "-Wcast-align"
48 #endif
49 
50 #if defined(AMIGA)
51 #include <clib/exec_protos.h>
52 #endif
53 
54 /**
55  * @brief
56  * sizeof(word) MUST BE A POWER OF TWO
57  * SO THAT wmask BELOW IS ALL ONES
58  */
59 typedef uint32_t word;
60 typedef uintptr_t mem_ptr;
61 
62 /**
63  * @brief loop-t-times
64  */
65 #define TLOOP(s) if (t) TLOOP1(s)
66 
67 /**
68  * @brief loop-t-times, t>0
69  */
70 #define TLOOP1(s) do { s; } while (--t)
71 
72 /**
73  * @brief Copy a block of memory, handling overlap.
74  */
75 void MemCopy(void* destination, const void* source, unsigned int length)
76 {
77  char* dst = (char*) destination;
78  const char* src = (const char*) source;
79  unsigned int t;
80 
81  if (length == 0 || dst == src) // nothing to do
82  return;
83 
84  if ((mem_ptr)dst < (mem_ptr)src)
85  {
86  // Copy forward
87 #if defined(AMIGA) // Take advantage of exec
88  CopyMem((void*)source, destination, length);
89 #else
90  t = (mem_ptr)src; // only need low bits
91  if ((t | (mem_ptr)dst) & wmask)
92  {
93  // Try to align operands. This cannot be done unless the low bits match.
94  if ((t ^ (mem_ptr)dst) & wmask || length < wsize)
95  t = length;
96  else
97  t = wsize - (t & wmask);
98  length -= t;
99 
100  TLOOP1(*dst++ = *src++);
101  }
102 
103  // Copy whole words, then mop up any trailing bytes.
104  t = length / wsize;
105  TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
106 
107  t = length & wmask;
108  TLOOP(*dst++ = *src++);
109 #endif
110  }
111  else
112  {
113  // Copy backwards. Otherwise essentially the same.
114  // Alignment works as before, except that it takes
115  // (t&wmask) bytes to align, not wsize-(t&wmask).
116  src += length;
117  dst += length;
118  t = (mem_ptr)src;
119  if ((t | (mem_ptr)dst) & wmask)
120  {
121  if ((t ^ (mem_ptr)dst) & wmask || length <= wsize)
122  t = length;
123  else
124  t &= wmask;
125  length -= t;
126 
127  TLOOP1(*--dst = *--src);
128  }
129 
130  t = length / wsize;
131  TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
132 
133  t = length & wmask;
134  TLOOP(*--dst = *--src);
135  }
136 }
#define wmask
Definition: amath.h:233
#define TLOOP1(s)
loop-t-times, t>0
Definition: memcpy.c:70
uint32_t word
sizeof(word) MUST BE A POWER OF TWO SO THAT wmask BELOW IS ALL ONES
Definition: memcpy.c:59
#define wsize
Definition: amath.h:232
uintptr_t mem_ptr
Definition: memcpy.c:60
void MemCopy(void *destination, const void *source, unsigned int length)
Copy a block of memory, handling overlap.
Definition: memcpy.c:75
#define TLOOP(s)
loop-t-times
Definition: memcpy.c:65