1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #include <linux/types.h>
3 #include <asm/string.h>
4 
5 #define OPSIZ (BITS_PER_LONG/8)
6 typedef unsigned long op_t;
7 
8 void *
memset(void * dstpp,int sc,size_t len)9 memset (void *dstpp, int sc, size_t len)
10 {
11   unsigned int c = sc;
12   long int dstp = (long int) dstpp;
13 
14   if (len >= 8)
15     {
16       size_t xlen;
17       op_t cccc;
18 
19       cccc = (unsigned char) c;
20       cccc |= cccc << 8;
21       cccc |= cccc << 16;
22       if (OPSIZ > 4)
23 	/* Do the shift in two steps to avoid warning if long has 32 bits.  */
24 	cccc |= (cccc << 16) << 16;
25 
26       /* There are at least some bytes to set.
27 	 No need to test for LEN == 0 in this alignment loop.  */
28       while (dstp % OPSIZ != 0)
29 	{
30 	  ((unsigned char *) dstp)[0] = c;
31 	  dstp += 1;
32 	  len -= 1;
33 	}
34 
35       /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
36       xlen = len / (OPSIZ * 8);
37       while (xlen > 0)
38 	{
39 	  ((op_t *) dstp)[0] = cccc;
40 	  ((op_t *) dstp)[1] = cccc;
41 	  ((op_t *) dstp)[2] = cccc;
42 	  ((op_t *) dstp)[3] = cccc;
43 	  ((op_t *) dstp)[4] = cccc;
44 	  ((op_t *) dstp)[5] = cccc;
45 	  ((op_t *) dstp)[6] = cccc;
46 	  ((op_t *) dstp)[7] = cccc;
47 	  dstp += 8 * OPSIZ;
48 	  xlen -= 1;
49 	}
50       len %= OPSIZ * 8;
51 
52       /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
53       xlen = len / OPSIZ;
54       while (xlen > 0)
55 	{
56 	  ((op_t *) dstp)[0] = cccc;
57 	  dstp += OPSIZ;
58 	  xlen -= 1;
59 	}
60       len %= OPSIZ;
61     }
62 
63   /* Write the last few bytes.  */
64   while (len > 0)
65     {
66       ((unsigned char *) dstp)[0] = c;
67       dstp += 1;
68       len -= 1;
69     }
70 
71   return dstpp;
72 }
73