xref: /rk3399_ARM-atf/lib/libc/memmove.c (revision 277d7dd6c192f350bc80ccbb65c36562e59f8e07)
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 	 */
19*277d7dd6SMaheedhar Bollapalli 	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;
274661abc7SAntonio Nino Diaz 		while (d != end)
284661abc7SAntonio Nino Diaz 			*--d = *--s;
294661abc7SAntonio Nino Diaz 	}
304661abc7SAntonio Nino Diaz 	return dst;
314661abc7SAntonio Nino Diaz }
32