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 * 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