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)
6typedef unsigned long op_t;
7
8void *
9memset (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