1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <assert.h> 8#include <stdint.h> 9#include <util.h> 10 11/* 12 * memzero needs a custom type that allows us to use a word 13 * that has the aliasing properties of a char. 14 */ 15typedef unsigned long __attribute__((__may_alias__)) ulong_alias; 16 17/* 18 * Zero 'n' bytes of memory starting from 's'. 19 * 20 * 'n' and 's' must be word aligned. 21 */ 22void memzero(void *s, unsigned long n) 23{ 24 uint8_t *p = s; 25 26 /* Ensure alignment constraints are met. */ 27 assert((unsigned long)s % sizeof(unsigned long) == 0); 28 assert(n % sizeof(unsigned long) == 0); 29 30 /* We will never memzero an area larger than the largest current 31 live object */ 32 /** GHOSTUPD: "(gs_get_assn cap_get_capSizeBits_'proc \<acute>ghost'state = 0 33 \<or> \<acute>n <= gs_get_assn cap_get_capSizeBits_'proc \<acute>ghost'state, id)" */ 34 35 /* Write out words. */ 36 while (n != 0) { 37 *(ulong_alias *)p = 0; 38 p += sizeof(ulong_alias); 39 n -= sizeof(ulong_alias); 40 } 41} 42 43void *VISIBLE memset(void *s, unsigned long c, unsigned long n) 44{ 45 uint8_t *p; 46 47 /* 48 * If we are only writing zeros and we are word aligned, we can 49 * use the optimized 'memzero' function. 50 */ 51 if (likely(c == 0 && ((unsigned long)s % sizeof(unsigned long)) == 0 && (n % sizeof(unsigned long)) == 0)) { 52 memzero(s, n); 53 } else { 54 /* Otherwise, we use a slower, simple memset. */ 55 for (p = (uint8_t *)s; n > 0; n--, p++) { 56 *p = (uint8_t)c; 57 } 58 } 59 60 return s; 61} 62 63void *VISIBLE memcpy(void *ptr_dst, const void *ptr_src, unsigned long n) 64{ 65 uint8_t *p; 66 const uint8_t *q; 67 68 for (p = (uint8_t *)ptr_dst, q = (const uint8_t *)ptr_src; n; n--, p++, q++) { 69 *p = *q; 70 } 71 72 return ptr_dst; 73} 74 75int PURE strncmp(const char *s1, const char *s2, int n) 76{ 77 word_t i; 78 int diff; 79 80 for (i = 0; i < n; i++) { 81 diff = ((unsigned char *)s1)[i] - ((unsigned char *)s2)[i]; 82 if (diff != 0 || s1[i] == '\0') { 83 return diff; 84 } 85 } 86 87 return 0; 88} 89 90long CONST char_to_long(char c) 91{ 92 if (c >= '0' && c <= '9') { 93 return c - '0'; 94 } else if (c >= 'A' && c <= 'F') { 95 return c - 'A' + 10; 96 } else if (c >= 'a' && c <= 'f') { 97 return c - 'a' + 10; 98 } 99 return -1; 100} 101 102long PURE str_to_long(const char *str) 103{ 104 unsigned int base; 105 long res; 106 long val = 0; 107 char c; 108 109 /*check for "0x" */ 110 if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { 111 base = 16; 112 str += 2; 113 } else { 114 base = 10; 115 } 116 117 if (!*str) { 118 return -1; 119 } 120 121 c = *str; 122 while (c != '\0') { 123 res = char_to_long(c); 124 if (res == -1 || res >= base) { 125 return -1; 126 } 127 val = val * base + res; 128 str++; 129 c = *str; 130 } 131 132 return val; 133} 134 135#ifdef CONFIG_ARCH_RISCV 136uint32_t __clzsi2(uint32_t x) 137{ 138 uint32_t count = 0; 139 while (!(x & 0x80000000U) && count < 34) { 140 x <<= 1; 141 count++; 142 } 143 return count; 144} 145 146uint32_t __ctzsi2(uint32_t x) 147{ 148 uint32_t count = 0; 149 while (!(x & 0x000000001) && count <= 32) { 150 x >>= 1; 151 count++; 152 } 153 return count; 154} 155 156uint32_t __clzdi2(uint64_t x) 157{ 158 uint32_t count = 0; 159 while (!(x & 0x8000000000000000U) && count < 65) { 160 x <<= 1; 161 count++; 162 } 163 return count; 164} 165 166uint32_t __ctzdi2(uint64_t x) 167{ 168 uint32_t count = 0; 169 while (!(x & 0x00000000000000001) && count <= 64) { 170 x >>= 1; 171 count++; 172 } 173 return count; 174} 175#endif /* CONFIG_ARCH_RISCV */ 176