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