Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6429 siemargl 1
/* TCC ARM runtime EABI
2
   Copyright (C) 2013 Thomas Preud'homme
3
 
4
Permission is hereby granted, free of charge, to any person obtaining a copy
5
of this software and associated documentation files (the "Software"), to deal
6
in the Software without restriction, including without limitation the rights
7
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
copies of the Software, and to permit persons to whom the Software is
9
furnished to do so, subject to the following conditions:
10
 
11
The above copyright notice and this permission notice shall be included in
12
all copies or substantial portions of the software.
13
 
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
THE SOFTWARE.*/
21
 
22
#include 
23
 
24
/* We rely on the little endianness and EABI calling convention for this to
25
   work */
26
 
27
typedef struct double_unsigned_struct {
28
    unsigned low;
29
    unsigned high;
30
} double_unsigned_struct;
31
 
32
typedef struct unsigned_int_struct {
33
    unsigned low;
34
    int high;
35
} unsigned_int_struct;
36
 
37
#define REGS_RETURN(name, type) \
38
    void name ## _return(type ret) {}
39
 
40
 
41
/* Float helper functions */
42
 
43
#define FLOAT_EXP_BITS 8
44
#define FLOAT_FRAC_BITS 23
45
 
46
#define DOUBLE_EXP_BITS 11
47
#define DOUBLE_FRAC_BITS 52
48
 
49
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
50
 
51
REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
52
REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
53
 
54
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
55
 
56
 
57
/* float to [unsigned] long long conversion */
58
#define DEFINE__AEABI_F2XLZ(name, with_sign)                                 \
59
void __aeabi_ ## name(unsigned val)                                          \
60
{                                                                            \
61
    int exp, high_shift, sign;                                               \
62
    double_unsigned_struct ret;                                              \
63
                                                                             \
64
    /* compute sign */                                                       \
65
    sign = val >> 31;                                                        \
66
                                                                             \
67
    /* compute real exponent */                                              \
68
    exp = val >> FLOAT_FRAC_BITS;                                            \
69
    exp &= (1 << FLOAT_EXP_BITS) - 1;                                        \
70
    exp -= ONE_EXP(FLOAT);                                                   \
71
                                                                             \
72
    /* undefined behavior if truncated value cannot be represented */        \
73
    if (with_sign) {                                                         \
74
        if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
75
            return;                                                          \
76
    } else {                                                                 \
77
        if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */  \
78
            return;                                                          \
79
    }                                                                        \
80
                                                                             \
81
    val &= (1 << FLOAT_FRAC_BITS) - 1;                                       \
82
    if (exp >= 32) {                                                         \
83
        ret.high = 1 << (exp - 32);                                          \
84
        if (exp - 32 >= FLOAT_FRAC_BITS) {                                   \
85
            ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS);                 \
86
            ret.low = 0;                                                     \
87
        } else {                                                             \
88
            high_shift = FLOAT_FRAC_BITS - (exp - 32);                       \
89
            ret.high |= val >> high_shift;                                   \
90
            ret.low = val << (32 - high_shift);                              \
91
        }                                                                    \
92
    } else {                                                                 \
93
        ret.high = 0;                                                        \
94
        ret.low = 1 << exp;                                                  \
95
        if (exp > FLOAT_FRAC_BITS)                                           \
96
            ret.low |= val << (exp - FLOAT_FRAC_BITS);                       \
97
        else                                                                 \
98
            ret.low |= val >> (FLOAT_FRAC_BITS - exp);                       \
99
    }                                                                        \
100
                                                                             \
101
    /* encode negative integer using 2's complement */                       \
102
    if (with_sign && sign) {                                                 \
103
        ret.low = ~ret.low;                                                  \
104
        ret.high = ~ret.high;                                                \
105
        if (ret.low == UINT_MAX) {                                           \
106
            ret.low = 0;                                                     \
107
            ret.high++;                                                      \
108
        } else                                                               \
109
            ret.low++;                                                       \
110
    }                                                                        \
111
                                                                             \
112
    double_unsigned_struct_return(ret);                                      \
113
}
114
 
115
/* float to unsigned long long conversion */
116
DEFINE__AEABI_F2XLZ(f2ulz, 0)
117
 
118
/* float to long long conversion */
119
DEFINE__AEABI_F2XLZ(f2lz, 1)
120
 
121
/* double to [unsigned] long long conversion */
122
#define DEFINE__AEABI_D2XLZ(name, with_sign)                                 \
123
void __aeabi_ ## name(double_unsigned_struct val)                            \
124
{                                                                            \
125
    int exp, high_shift, sign;                                               \
126
    double_unsigned_struct ret;                                              \
127
                                                                             \
128
    /* compute sign */                                                       \
129
    sign = val.high >> 31;                                                   \
130
                                                                             \
131
    /* compute real exponent */                                              \
132
    exp = (val.high >> (DOUBLE_FRAC_BITS - 32));                             \
133
    exp &= (1 << DOUBLE_EXP_BITS) - 1;                                       \
134
    exp -= ONE_EXP(DOUBLE);                                                  \
135
                                                                             \
136
    /* undefined behavior if truncated value cannot be represented */        \
137
    if (with_sign) {                                                         \
138
        if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
139
            return;                                                          \
140
    } else {                                                                 \
141
        if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */  \
142
            return;                                                          \
143
    }                                                                        \
144
                                                                             \
145
    val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1;                          \
146
    if (exp >= 32) {                                                         \
147
        ret.high = 1 << (exp - 32);                                          \
148
        if (exp >= DOUBLE_FRAC_BITS) {                                       \
149
            high_shift = exp - DOUBLE_FRAC_BITS;                             \
150
            ret.high |= val.high << high_shift;                              \
151
            ret.high |= val.low >> (32 - high_shift);                        \
152
            ret.low = val.low << high_shift;                                 \
153
        } else {                                                             \
154
            high_shift = DOUBLE_FRAC_BITS - exp;                             \
155
            ret.high |= val.high >> high_shift;                              \
156
            ret.low = val.high << (32 - high_shift);                         \
157
            ret.low |= val.low >> high_shift;                                \
158
        }                                                                    \
159
    } else {                                                                 \
160
        ret.high = 0;                                                        \
161
        ret.low = 1 << exp;                                                  \
162
        if (exp > DOUBLE_FRAC_BITS - 32) {                                   \
163
            high_shift = exp - DOUBLE_FRAC_BITS - 32;                        \
164
            ret.low |= val.high << high_shift;                               \
165
            ret.low |= val.low >> (32 - high_shift);                         \
166
        } else                                                               \
167
            ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp);            \
168
    }                                                                        \
169
                                                                             \
170
    /* encode negative integer using 2's complement */                       \
171
    if (with_sign && sign) {                                                 \
172
        ret.low = ~ret.low;                                                  \
173
        ret.high = ~ret.high;                                                \
174
        if (ret.low == UINT_MAX) {                                           \
175
            ret.low = 0;                                                     \
176
            ret.high++;                                                      \
177
        } else                                                               \
178
            ret.low++;                                                       \
179
    }                                                                        \
180
                                                                             \
181
    double_unsigned_struct_return(ret);                                      \
182
}
183
 
184
/* double to unsigned long long conversion */
185
DEFINE__AEABI_D2XLZ(d2ulz, 0)
186
 
187
/* double to long long conversion */
188
DEFINE__AEABI_D2XLZ(d2lz, 1)
189
 
190
/* long long to float conversion */
191
#define DEFINE__AEABI_XL2F(name, with_sign)                             \
192
unsigned __aeabi_ ## name(unsigned long long v)                         \
193
{                                                                       \
194
    int s /* shift */, flb /* first lost bit */, sign = 0;              \
195
    unsigned p = 0 /* power */, ret;                                    \
196
    double_unsigned_struct val;                                         \
197
                                                                        \
198
    /* fraction in negative float is encoded in 1's complement */       \
199
    if (with_sign && (v & (1ULL << 63))) {                              \
200
        sign = 1;                                                       \
201
        v = ~v + 1;                                                     \
202
    }                                                                   \
203
    val.low = v;                                                        \
204
    val.high = v >> 32;                                                 \
205
    /* fill fraction bits */                                            \
206
    for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1);      \
207
    if (p) {                                                            \
208
        ret = val.high & (p - 1);                                       \
209
        if (s < FLOAT_FRAC_BITS) {                                      \
210
            ret <<= FLOAT_FRAC_BITS - s;                                \
211
            ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s));             \
212
            flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1;    \
213
        } else {                                                        \
214
            flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1;               \
215
            ret >>= s - FLOAT_FRAC_BITS;                                \
216
        }                                                               \
217
        s += 32;                                                        \
218
    } else {                                                            \
219
        for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1);   \
220
        if (p) {                                                        \
221
            ret = val.low & (p - 1);                                    \
222
            if (s <= FLOAT_FRAC_BITS) {                                 \
223
                ret <<= FLOAT_FRAC_BITS - s;                            \
224
                flb = 0;                                                \
225
	    } else {                                                    \
226
                flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1;           \
227
                ret >>= s - FLOAT_FRAC_BITS;                            \
228
	    }                                                           \
229
        } else                                                          \
230
            return 0;                                                   \
231
    }                                                                   \
232
    if (flb)                                                            \
233
        ret++;                                                          \
234
                                                                        \
235
    /* fill exponent bits */                                            \
236
    ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS;                     \
237
                                                                        \
238
    /* fill sign bit */                                                 \
239
    ret |= sign << 31;                                                  \
240
                                                                        \
241
    return ret;                                                         \
242
}
243
 
244
/* unsigned long long to float conversion */
245
DEFINE__AEABI_XL2F(ul2f, 0)
246
 
247
/* long long to float conversion */
248
DEFINE__AEABI_XL2F(l2f, 1)
249
 
250
/* long long to double conversion */
251
#define __AEABI_XL2D(name, with_sign)                                   \
252
void __aeabi_ ## name(unsigned long long v)                             \
253
{                                                                       \
254
    int s /* shift */, high_shift, sign = 0;                            \
255
    unsigned tmp, p = 0;                                                \
256
    double_unsigned_struct val, ret;                                    \
257
                                                                        \
258
    /* fraction in negative float is encoded in 1's complement */       \
259
    if (with_sign && (v & (1ULL << 63))) {                              \
260
        sign = 1;                                                       \
261
        v = ~v + 1;                                                     \
262
    }                                                                   \
263
    val.low = v;                                                        \
264
    val.high = v >> 32;                                                 \
265
                                                                        \
266
    /* fill fraction bits */                                            \
267
    for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1);      \
268
    if (p) {                                                            \
269
        tmp = val.high & (p - 1);                                       \
270
        if (s < DOUBLE_FRAC_BITS - 32) {                                \
271
            high_shift = DOUBLE_FRAC_BITS - 32 - s;                     \
272
            ret.high = tmp << high_shift;                               \
273
            ret.high |= val.low >> (32 - high_shift);                   \
274
            ret.low = val.low << high_shift;                            \
275
        } else {                                                        \
276
            high_shift = s - (DOUBLE_FRAC_BITS - 32);                   \
277
            ret.high = tmp >> high_shift;                               \
278
            ret.low = tmp << (32 - high_shift);                         \
279
            ret.low |= val.low >> high_shift;                           \
280
            if ((val.low >> (high_shift - 1)) & 1) {                    \
281
                if (ret.low == UINT_MAX) {                              \
282
                    ret.high++;                                         \
283
                    ret.low = 0;                                        \
284
		} else                                                  \
285
                    ret.low++;                                          \
286
            }                                                           \
287
        }                                                               \
288
        s += 32;                                                        \
289
    } else {                                                            \
290
        for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1);   \
291
        if (p) {                                                        \
292
            tmp = val.low & (p - 1);                                    \
293
            if (s <= DOUBLE_FRAC_BITS - 32) {                           \
294
                high_shift = DOUBLE_FRAC_BITS - 32 - s;                 \
295
                ret.high = tmp << high_shift;                           \
296
                ret.low = 0;                                            \
297
	    } else {                                                    \
298
                high_shift = s - (DOUBLE_FRAC_BITS - 32);               \
299
                ret.high = tmp >> high_shift;                           \
300
                ret.low = tmp << (32 - high_shift);                     \
301
            }                                                           \
302
        } else {                                                        \
303
            ret.high = ret.low = 0;                                     \
304
            double_unsigned_struct_return(ret);                         \
305
        }                                                               \
306
    }                                                                   \
307
                                                                        \
308
    /* fill exponent bits */                                            \
309
    ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32);       \
310
                                                                        \
311
    /* fill sign bit */                                                 \
312
    ret.high |= sign << 31;                                             \
313
                                                                        \
314
    double_unsigned_struct_return(ret);                                 \
315
}
316
 
317
/* unsigned long long to double conversion */
318
__AEABI_XL2D(ul2d, 0)
319
 
320
/* long long to double conversion */
321
__AEABI_XL2D(l2d, 1)
322
 
323
 
324
/* Long long helper functions */
325
 
326
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
327
 
328
#define define_aeabi_xdivmod_signed_type(basetype, type) \
329
typedef struct type {                                    \
330
    basetype quot;                                       \
331
    unsigned basetype rem;                               \
332
} type
333
 
334
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
335
typedef struct type {                                      \
336
    basetype quot;                                         \
337
    basetype rem;                                          \
338
} type
339
 
340
#define AEABI_UXDIVMOD(name,type, rettype, typemacro)                     \
341
static inline rettype aeabi_ ## name (type num, type den)                 \
342
{                                                                         \
343
    rettype ret;                                                          \
344
    type quot = 0;                                                        \
345
                                                                          \
346
    /* Increase quotient while it is less than numerator */               \
347
    while (num >= den) {                                                  \
348
        type q = 1;                                                       \
349
                                                                          \
350
        /* Find closest power of two */                                   \
351
        while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
352
            q <<= 1;                                                      \
353
                                                                          \
354
        /* Compute difference between current quotient and numerator */   \
355
        num -= q * den;                                                   \
356
        quot += q;                                                        \
357
    }                                                                     \
358
    ret.quot = quot;                                                      \
359
    ret.rem = num;                                                        \
360
    return ret;                                                           \
361
}
362
 
363
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro)     \
364
void __aeabi_ ## name(type numerator, type denominator)                       \
365
{                                                                             \
366
    unsigned type num, den;                                                   \
367
    urettype uxdiv_ret;                                                       \
368
    rettype ret;                                                              \
369
                                                                              \
370
    if (numerator >= 0)                                                       \
371
      num = numerator;                                                        \
372
    else                                                                      \
373
      num = 0 - numerator;                                                    \
374
    if (denominator >= 0)                                                     \
375
      den = denominator;                                                      \
376
    else                                                                      \
377
      den = 0 - denominator;                                                  \
378
    uxdiv_ret = aeabi_ ## uiname(num, den);                                   \
379
    /* signs differ */                                                        \
380
    if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
381
        ret.quot = 0 - uxdiv_ret.quot;                                        \
382
    else                                                                      \
383
        ret.quot = uxdiv_ret.quot;                                            \
384
    if (numerator < 0)                                                        \
385
        ret.rem = 0 - uxdiv_ret.rem;                                          \
386
    else                                                                      \
387
        ret.rem = uxdiv_ret.rem;                                              \
388
                                                                              \
389
    rettype ## _return(ret);                                                  \
390
}
391
 
392
define_aeabi_xdivmod_signed_type(long long, lldiv_t);
393
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
394
define_aeabi_xdivmod_signed_type(int, idiv_t);
395
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
396
 
397
REGS_RETURN(lldiv_t, lldiv_t)
398
REGS_RETURN(ulldiv_t, ulldiv_t)
399
REGS_RETURN(idiv_t, idiv_t)
400
REGS_RETURN(uidiv_t, uidiv_t)
401
 
402
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG)
403
 
404
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
405
 
406
void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
407
{
408
    ulldiv_t_return(aeabi_uldivmod(num, den));
409
}
410
 
411
void __aeabi_llsl(double_unsigned_struct val, int shift)
412
{
413
    double_unsigned_struct ret;
414
 
415
    if (shift >= 32) {
416
        val.high = val.low;
417
        val.low = 0;
418
        shift -= 32;
419
    }
420
    if (shift > 0) {
421
        ret.low = val.low << shift;
422
        ret.high = (val.high << shift) | (val.low >> (32 - shift));
423
        double_unsigned_struct_return(ret);
424
	return;
425
    }
426
    double_unsigned_struct_return(val);
427
}
428
 
429
#define aeabi_lsr(val, shift, fill, type)                          \
430
    type ## _struct ret;                                           \
431
                                                                   \
432
    if (shift >= 32) {                                             \
433
        val.low = val.high;                                        \
434
        val.high = fill;                                           \
435
        shift -= 32;                                               \
436
    }                                                              \
437
    if (shift > 0) {                                               \
438
        ret.high = val.high >> shift;                              \
439
        ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
440
        type ## _struct_return(ret);                               \
441
	return;                                                    \
442
    }                                                              \
443
    type ## _struct_return(val);
444
 
445
void __aeabi_llsr(double_unsigned_struct val, int shift)
446
{
447
    aeabi_lsr(val, shift, 0, double_unsigned);
448
}
449
 
450
void __aeabi_lasr(unsigned_int_struct val, int shift)
451
{
452
    aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
453
}
454
 
455
 
456
/* Integer division functions */
457
 
458
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
459
 
460
int __aeabi_idiv(int numerator, int denominator)
461
{
462
    unsigned num, den;
463
    uidiv_t ret;
464
 
465
    if (numerator >= 0)
466
        num = numerator;
467
    else
468
        num = 0 - numerator;
469
    if (denominator >= 0)
470
        den = denominator;
471
    else
472
        den = 0 - denominator;
473
    ret = aeabi_uidivmod(num, den);
474
    if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
475
        ret.quot *= -1;
476
    return ret.quot;
477
}
478
 
479
unsigned __aeabi_uidiv(unsigned num, unsigned den)
480
{
481
    return aeabi_uidivmod(num, den).quot;
482
}
483
 
484
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
485
 
486
void __aeabi_uidivmod(unsigned num, unsigned den)
487
{
488
    uidiv_t_return(aeabi_uidivmod(num, den));
489
}