1 #include "basic_types.h"
2 #include <stdarg.h>
3 #include <stddef.h> /* Compiler defns such as size_t, NULL etc. */
4 #include "strproc.h"
5 #include "section_config.h"
6 #include "diag.h"
7 #include "ameba_soc.h"
8
9 #pragma GCC diagnostic push
10 #pragma GCC diagnostic ignored "-Wunused-parameter"
11 #pragma GCC diagnostic ignored "-Wunused-function"
12 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
13
14 #define USHRT_MAX ((u16)(~0U))
15 #define SHRT_MAX ((s16)(USHRT_MAX>>1))
16 #define ULLONG_MAX (~0ULL)
17 #define STR_STORE_MAX_LEN 24
18 #define KSTRTOX_OVERFLOW (1U << 31)
19
20 /**
21 * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
22 *
23 * This is commonly provided by 32bit archs to provide an optimized 64bit
24 * divide.
25 */
26 //static inline
27 LIBC_ROM_TEXT_SECTION
div_u64_rem(u64 dividend,u32 divisor,u32 * remainder)28 _LONG_CALL_ static u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
29 {
30 *remainder = (u32)dividend % divisor;
31 return (u32)dividend / divisor;
32 }
33
34 /**
35 * div_s64_rem - signed 64bit divide with 32bit divisor with remainder
36 */
37 //static inline
38 //LIBC_ROM_TEXT_SECTION
39 //_LONG_CALL_ static s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
40 //{
41 // *remainder = (s32)dividend % divisor;
42 // return (s32)dividend / divisor;
43 //}
44
45 /**
46 * div_u64 - unsigned 64bit divide with 32bit divisor
47 *
48 * This is the most common 64bit divide and should be used if possible,
49 * as many 32bit archs can optimize this variant better than a full 64bit
50 * divide.
51 */
52 #ifndef div_u64
53 //static inline
54 LIBC_ROM_TEXT_SECTION
div_u64(u64 dividend,u32 divisor)55 _LONG_CALL_ static u64 div_u64(u64 dividend, u32 divisor)
56 {
57 u32 remainder;
58 return div_u64_rem(dividend, divisor, &remainder);
59 }
60 #endif
61
62 /**
63 * div_s64 - signed 64bit divide with 32bit divisor
64 */
65 #ifndef div_s64
66 //static inline
67 //LIBC_ROM_TEXT_SECTION
68 //_LONG_CALL_ static s64 div_s64(s64 dividend, s32 divisor)
69 //{
70 // s32 remainder;
71 // return div_s64_rem(dividend, divisor, &remainder);
72 //}
73 #endif
74
75 LIBC_ROM_TEXT_SECTION
_parse_integer_fixup_radix(const char * s,unsigned int * base)76 _LONG_CALL_ static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
77 {
78 if (*base == 0) {
79 if (s[0] == '0') {
80 if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
81 *base = 16;
82 else
83 *base = 8;
84 } else
85 *base = 10;
86 }
87 if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
88 s += 2;
89 return s;
90 }
91
92 /**
93 * mul64_8 - unsigned 64bit mul unsigned 8 bit
94 *add this function because we do not want link GCC in rom code.
95
96 | 32 | 8 | 24 |
97 * | 8 |
98 --------------------------------------------
99 | 24*8 |
100 + | 8*8 |
101 +| 32*8 |
102 --------------------------------------------
103 + | sum | low 24 bits |
104 */
105 LIBC_ROM_TEXT_SECTION
mul64_8(unsigned long long u,unsigned char v)106 _LONG_CALL_ static unsigned long long mul64_8 (unsigned long long u, unsigned char v)
107 {
108
109 //#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
110 // struct DWstruct {int high, low;};
111 //#else
112 struct DWstruct {unsigned int low, high;};
113 //#endif
114
115 typedef union
116 {
117 struct DWstruct s;
118 unsigned long long ll;
119 } DWunion;
120
121 const DWunion uu = {.ll = u};
122 const unsigned char vv = v;
123 unsigned int temp;
124 DWunion w ;
125
126 w.s.low = uu.s.low * vv;
127 w.s.low &= 0xFFFFFF;
128
129 w.s.high = ( uu.s.low >> 24) * vv ;
130 w.s.high += (((uu.s.low & 0xFFFFFF)*vv)>>24);
131
132 temp = w.s.high <<24;
133
134 w.s.high = (w.s.high >> 8);
135 w.s.high += uu.s.high * vv;
136
137 w.s.low |= temp;
138 return w.ll;
139
140 }
141
142 LIBC_ROM_TEXT_SECTION
_parse_integer(const char * s,unsigned int base,unsigned long long * p)143 _LONG_CALL_ static unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
144 {
145 unsigned long long res;
146 unsigned int rv;
147 int overflow;
148
149 res = 0;
150 rv = 0;
151 overflow = 0;
152 while (*s) {
153 unsigned int val;
154
155 if ('0' <= *s && *s <= '9')
156 val = *s - '0';
157 else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f')
158 val = _tolower(*s) - 'a' + 10;
159 else
160 break;
161
162 if (val >= base)
163 break;
164 /*
165 * Check for overflow only if we are within range of
166 * it in the max base we support (16)
167 */
168 if (unlikely(res & (~0ull << 60))) {
169 if (res > div_u64(ULLONG_MAX - val, base))
170 overflow = 1;
171 }
172 res = mul64_8(res , (unsigned char)base) + val;
173 rv++;
174 s++;
175 }
176 *p = res;
177 if (overflow)
178 rv |= KSTRTOX_OVERFLOW;
179 return rv;
180 }
181
182 /*
183 * _strtoull - convert a string to an unsigned long long
184 * @cp: The start of the string
185 * @endp: A pointer to the end of the parsed string will be placed here
186 * @base: The number base to use
187 *
188 * This function is obsolete. Please use kstrtoull instead.
189 */
190 LIBC_ROM_TEXT_SECTION
_strtoull(const char * cp,char ** endp,unsigned int base)191 _LONG_CALL_ unsigned long long _strtoull(const char *cp, char **endp, unsigned int base)
192 {
193 unsigned long long result;
194 unsigned int rv;
195
196 cp = _parse_integer_fixup_radix(cp, &base);
197 rv = _parse_integer(cp, base, &result);
198
199 return result;
200 }
201
202 /**
203 * _strtoll - convert a string to a signed long long
204 * @cp: The start of the string
205 * @endp: A pointer to the end of the parsed string will be placed here
206 * @base: The number base to use
207 *
208 * This function is obsolete. Please use kstrtoll instead.
209 */
210 LIBC_ROM_TEXT_SECTION
_strtoll(const char * cp,char ** endp,unsigned int base)211 _LONG_CALL_ long long _strtoll(const char *cp, char **endp, unsigned int base)
212 {
213 if (*cp == '-')
214 return -_strtoull(cp + 1, endp, base);
215
216 return _strtoull(cp, endp, base);
217 }
218
219 #pragma GCC diagnostic pop