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