blob: 8a0165ba29773778d24721f64c05ecee54292126 [file] [log] [blame]
Patrick Georgi11f00792020-03-04 15:10:45 +01001/* SPDX-License-Identifier: GPL-2.0-or-later */
Stefan Reinauer1afe51a2011-10-26 22:11:52 +00002
3/* From glibc-2.14, sysdeps/i386/memset.c */
4
5#include <string.h>
6#include <stdint.h>
Harshit Sharma51593dd2020-08-08 17:51:59 -07007#include <stdbool.h>
8#include <asan.h>
Stefan Reinauer1afe51a2011-10-26 22:11:52 +00009
10typedef uint32_t op_t;
11
12void *memset(void *dstpp, int c, size_t len)
13{
14 int d0;
Elyes Haouas2ba796e2022-11-18 15:21:37 +010015 unsigned long int dstp = (unsigned long int)dstpp;
Stefan Reinauer1afe51a2011-10-26 22:11:52 +000016
Harshit Sharma51593dd2020-08-08 17:51:59 -070017#if (ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)) || \
18 (ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE))
19 check_memory_region((unsigned long)dstpp, len, true, _RET_IP_);
20#endif
21
Stefan Reinauer1afe51a2011-10-26 22:11:52 +000022 /* This explicit register allocation improves code very much indeed. */
23 register op_t x asm("ax");
24
Elyes Haouas2ba796e2022-11-18 15:21:37 +010025 x = (unsigned char)c;
Stefan Reinauer1afe51a2011-10-26 22:11:52 +000026
27 /* Clear the direction flag, so filling will move forward. */
28 asm volatile("cld");
29
30 /* This threshold value is optimal. */
31 if (len >= 12) {
32 /* Fill X with four copies of the char we want to fill with. */
33 x |= (x << 8);
34 x |= (x << 16);
35
36 /* Adjust LEN for the bytes handled in the first loop. */
37 len -= (-dstp) % sizeof(op_t);
38
39 /*
40 * There are at least some bytes to set. No need to test for
41 * LEN == 0 in this alignment loop.
42 */
43
44 /* Fill bytes until DSTP is aligned on a longword boundary. */
45 asm volatile(
46 "rep\n"
47 "stosb" /* %0, %2, %3 */ :
48 "=D" (dstp), "=c" (d0) :
49 "0" (dstp), "1" ((-dstp) % sizeof(op_t)), "a" (x) :
50 "memory");
51
52 /* Fill longwords. */
53 asm volatile(
54 "rep\n"
55 "stosl" /* %0, %2, %3 */ :
56 "=D" (dstp), "=c" (d0) :
57 "0" (dstp), "1" (len / sizeof(op_t)), "a" (x) :
58 "memory");
59 len %= sizeof(op_t);
60 }
61
62 /* Write the last few bytes. */
63 asm volatile(
64 "rep\n"
65 "stosb" /* %0, %2, %3 */ :
66 "=D" (dstp), "=c" (d0) :
67 "0" (dstp), "1" (len), "a" (x) :
68 "memory");
69
70 return dstpp;
71}