diff options
Diffstat (limited to 'lib/src')
-rw-r--r-- | lib/src/common.c | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/lib/src/common.c b/lib/src/common.c index dd806bf..aa8d2ba 100644 --- a/lib/src/common.c +++ b/lib/src/common.c @@ -18,15 +18,53 @@ void* memset(void* s, int c, size_t n) { } void* memcpy(void* d, const void* s, size_t n) { - // When `d` points into `[s, s+n[` we would override `s` while copying into `d`. - // |------------|--------| - // s d s+n - // -> We don't support. - // - // When `d` points into `]s-n, s[` it is destructive for `s` but all data - // from `s` are copied into `d`. The user gets what he asks for. - // -> Supported. + // Cases to distinguish resulting from s and d pointers. + // + // Case 1 - same + // |------------| + // s s+n + // d d+n + // + // -> Nothing to copy. + // + // Case 2 - disjunct + // |------------| |------------| + // s s+n d d+n + // + // -> Nothing to worry, just copy the bytes from s to d. + // + // Case 3 - head overlap + // |------------| + // s s+n + // |------------| + // d d+n + // + // -> Destructive copy for s but all bytes get properly copied from s to d. + // The user gets what he/she asked for. + // + // Case 4 - tail overlap + // |------------| + // s s+n + // |------------| + // d d+n + // + // -> With a simple forward copy we would override the tail of s while + // copying into the head of d. This is destructive for s but we would + // also copy "wrong" bytes into d when we copy the tail of s (as it is + // already overwritten). + // This copy could be done properly by copying backwards (on x86 we + // could use the direction flag for string operations). + // -> We don't support this here as it is not needed any of the examples. + + // Case 4. ERROR_ON(s <= d && d < (void*)((unsigned char*)s + n), "memcpy: Unsupported overlap!"); + + // Case 1. + if (d == s) { + return d; + } + + // Case 2/3. asm volatile( "cld" "\n" |