memset.c 1.5 KB

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