hv: refine memcpy_s

Use enhanced rep fast-string operation to refine memcpy_s.
And assume that the destination and the source would not overlap.

Tracked-On: #861
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
This commit is contained in:
Li, Fei1 2018-12-17 22:55:09 +08:00 committed by wenlingz
parent 2d1b3dd98d
commit 10c49ae6fd
2 changed files with 23 additions and 83 deletions

View File

@ -28,7 +28,7 @@ char *strncpy_s(char *d_arg, size_t dmax, const char *s_arg, size_t slen_arg);
char *strchr(char *s_arg, char ch); char *strchr(char *s_arg, char ch);
size_t strnlen_s(const char *str_arg, size_t maxlen_arg); size_t strnlen_s(const char *str_arg, size_t maxlen_arg);
void *memset(void *base, uint8_t v, size_t n); void *memset(void *base, uint8_t v, size_t n);
void *memcpy_s(void *d, size_t dmax, const void *s, size_t slen_arg); void *memcpy_s(void *d, size_t dmax, const void *s, size_t slen);
int32_t atoi(const char *str); int32_t atoi(const char *str);
long strtol_deci(const char *nptr); long strtol_deci(const char *nptr);
uint64_t strtoul_hex(const char *nptr); uint64_t strtoul_hex(const char *nptr);

View File

@ -274,96 +274,36 @@ void *memchr(const void *void_s, int32_t c, size_t n)
return NULL; return NULL;
} }
/*********************************************************************** static inline void memcpy_erms(void *d, const void *s, size_t slen)
* {
* FUNCTION asm volatile ("rep; movsb"
* : "=&D"(d), "=&S"(s)
* memcpy_s : "c"(slen), "0" (d), "1" (s)
* : "memory");
* DESCRIPTION }
*
* Copies at most slen bytes from src address to dest address, /*
* up to dmax. * @brief Copies at most slen bytes from src address to dest address, up to dmax.
* *
* INPUTS * INPUTS
* *
* d pointer to Destination address * @param[in] d pointer to Destination address
* dmax maximum length of dest * @param[in] dmax maximum length of dest
* s pointer to Source address * @param[in] s pointer to Source address
* slen maximum number of bytes of src to copy * @param[in] slen maximum number of bytes of src to copy
* *
* OUTPUTS * @return pointer to destination address.
* *
* void * pointer to destination address if successful, * @pre d and s will not overlap.
* or else return null. */
* void *memcpy_s(void *d, size_t dmax, const void *s, size_t slen)
***********************************************************************/
void *memcpy_s(void *d, size_t dmax, const void *s, size_t slen_arg)
{ {
uint8_t *dest8; if ((slen != 0U) && (dmax != 0U) && (dmax >= slen)) {
uint8_t *src8; /* same memory block, no need to copy */
size_t slen = slen_arg; if (d != s) {
memcpy_erms(d, s, slen);
if ((slen == 0U) || (dmax == 0U) || (dmax < slen)) {
ASSERT(false);
}
if ((((d) > (s)) && ((d) <= ((s + slen) - 1U)))
|| (((d) < (s)) && ((s) <= ((d + dmax) - 1U)))) {
ASSERT(false);
}
/* same memory block, no need to copy */
if (d == s) {
return d;
}
dest8 = (uint8_t *)d;
src8 = (uint8_t *)s;
/* small data block */
if (slen < 8U) {
while (slen != 0U) {
*dest8 = *src8;
dest8++;
src8++;
slen--;
}
return d;
}
/* make sure 8bytes-aligned for at least one addr. */
if ((!mem_aligned_check((uint64_t)src8, 8UL)) &&
(!mem_aligned_check((uint64_t)dest8, 8UL))) {
for (; (slen != 0U) && ((((uint64_t)src8) & 7UL) != 0UL);
slen--) {
*dest8 = *src8;
dest8++;
src8++;
} }
} }
/* copy main data blocks, with rep prefix */
if (slen > 8U) {
uint32_t ecx;
asm volatile ("cld; rep; movsq"
: "=&c"(ecx), "=&D"(dest8), "=&S"(src8)
: "0" (slen >> 3), "1" (dest8), "2" (src8)
: "memory");
slen = slen & 0x7U;
}
/* tail bytes */
while (slen != 0U) {
*dest8 = *src8;
dest8++;
src8++;
slen--;
}
return d; return d;
} }