xref: /rk3399_ARM-atf/lib/libc/memmove.c (revision 60e5aee11890da7d561e11a6c8f251de5c068bb4)
14661abc7SAntonio Nino Diaz /*
24c700c15SGovindraj Raja  * Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
34661abc7SAntonio Nino Diaz  *
44661abc7SAntonio Nino Diaz  * SPDX-License-Identifier: BSD-3-Clause
54661abc7SAntonio Nino Diaz  */
64661abc7SAntonio Nino Diaz 
74661abc7SAntonio Nino Diaz #include <string.h>
84661abc7SAntonio Nino Diaz 
94661abc7SAntonio Nino Diaz void *memmove(void *dst, const void *src, size_t len)
104661abc7SAntonio Nino Diaz {
114661abc7SAntonio Nino Diaz 	/*
124661abc7SAntonio Nino Diaz 	 * The following test makes use of unsigned arithmetic overflow to
134661abc7SAntonio Nino Diaz 	 * more efficiently test the condition !(src <= dst && dst < str+len).
144661abc7SAntonio Nino Diaz 	 * It also avoids the situation where the more explicit test would give
154661abc7SAntonio Nino Diaz 	 * incorrect results were the calculation str+len to overflow (though
164661abc7SAntonio Nino Diaz 	 * that issue is probably moot as such usage is probably undefined
174661abc7SAntonio Nino Diaz 	 * behaviour and a bug anyway.
184661abc7SAntonio Nino Diaz 	 */
194661abc7SAntonio Nino Diaz 	if ((size_t)dst - (size_t)src >= len) {
204661abc7SAntonio Nino Diaz 		/* destination not in source data, so can safely use memcpy */
214661abc7SAntonio Nino Diaz 		return memcpy(dst, src, len);
224661abc7SAntonio Nino Diaz 	} else {
234661abc7SAntonio Nino Diaz 		/* copy backwards... */
244661abc7SAntonio Nino Diaz 		const char *end = dst;
254661abc7SAntonio Nino Diaz 		const char *s = (const char *)src + len;
264661abc7SAntonio Nino Diaz 		char *d = (char *)dst + len;
27*60e5aee1SMaheedhar Bollapalli 		while (d != end) {
284661abc7SAntonio Nino Diaz 			*--d = *--s;
294661abc7SAntonio Nino Diaz 		}
30*60e5aee1SMaheedhar Bollapalli 	}
314661abc7SAntonio Nino Diaz 	return dst;
324661abc7SAntonio Nino Diaz }
33