489 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			489 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* TCC ARM runtime EABI
 | 
						|
   Copyright (C) 2013 Thomas Preud'homme
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
						|
of this software and associated documentation files (the "Software"), to deal
 | 
						|
in the Software without restriction, including without limitation the rights
 | 
						|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
						|
copies of the Software, and to permit persons to whom the Software is
 | 
						|
furnished to do so, subject to the following conditions:
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
						|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
						|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
						|
THE SOFTWARE.*/
 | 
						|
 | 
						|
#include <limits.h>
 | 
						|
 | 
						|
/* We rely on the little endianness and EABI calling convention for this to
 | 
						|
   work */
 | 
						|
 | 
						|
typedef struct double_unsigned_struct {
 | 
						|
    unsigned low;
 | 
						|
    unsigned high;
 | 
						|
} double_unsigned_struct;
 | 
						|
 | 
						|
typedef struct unsigned_int_struct {
 | 
						|
    unsigned low;
 | 
						|
    int high;
 | 
						|
} unsigned_int_struct;
 | 
						|
 | 
						|
#define REGS_RETURN(name, type) \
 | 
						|
    void name ## _return(type ret) {}
 | 
						|
 | 
						|
 | 
						|
/* Float helper functions */
 | 
						|
 | 
						|
#define FLOAT_EXP_BITS 8
 | 
						|
#define FLOAT_FRAC_BITS 23
 | 
						|
 | 
						|
#define DOUBLE_EXP_BITS 11
 | 
						|
#define DOUBLE_FRAC_BITS 52
 | 
						|
 | 
						|
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
 | 
						|
 | 
						|
REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
 | 
						|
REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
 | 
						|
 | 
						|
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
 | 
						|
 | 
						|
 | 
						|
/* float to [unsigned] long long conversion */
 | 
						|
#define DEFINE__AEABI_F2XLZ(name, with_sign)                                 \
 | 
						|
void __aeabi_ ## name(unsigned val)                                          \
 | 
						|
{                                                                            \
 | 
						|
    int exp, high_shift, sign;                                               \
 | 
						|
    double_unsigned_struct ret;                                              \
 | 
						|
                                                                             \
 | 
						|
    /* compute sign */                                                       \
 | 
						|
    sign = val >> 31;                                                        \
 | 
						|
                                                                             \
 | 
						|
    /* compute real exponent */                                              \
 | 
						|
    exp = val >> FLOAT_FRAC_BITS;                                            \
 | 
						|
    exp &= (1 << FLOAT_EXP_BITS) - 1;                                        \
 | 
						|
    exp -= ONE_EXP(FLOAT);                                                   \
 | 
						|
                                                                             \
 | 
						|
    /* undefined behavior if truncated value cannot be represented */        \
 | 
						|
    if (with_sign) {                                                         \
 | 
						|
        if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
 | 
						|
            return;                                                          \
 | 
						|
    } else {                                                                 \
 | 
						|
        if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */  \
 | 
						|
            return;                                                          \
 | 
						|
    }                                                                        \
 | 
						|
                                                                             \
 | 
						|
    val &= (1 << FLOAT_FRAC_BITS) - 1;                                       \
 | 
						|
    if (exp >= 32) {                                                         \
 | 
						|
        ret.high = 1 << (exp - 32);                                          \
 | 
						|
        if (exp - 32 >= FLOAT_FRAC_BITS) {                                   \
 | 
						|
            ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS);                 \
 | 
						|
            ret.low = 0;                                                     \
 | 
						|
        } else {                                                             \
 | 
						|
            high_shift = FLOAT_FRAC_BITS - (exp - 32);                       \
 | 
						|
            ret.high |= val >> high_shift;                                   \
 | 
						|
            ret.low = val << (32 - high_shift);                              \
 | 
						|
        }                                                                    \
 | 
						|
    } else {                                                                 \
 | 
						|
        ret.high = 0;                                                        \
 | 
						|
        ret.low = 1 << exp;                                                  \
 | 
						|
        if (exp > FLOAT_FRAC_BITS)                                           \
 | 
						|
            ret.low |= val << (exp - FLOAT_FRAC_BITS);                       \
 | 
						|
        else                                                                 \
 | 
						|
            ret.low |= val >> (FLOAT_FRAC_BITS - exp);                       \
 | 
						|
    }                                                                        \
 | 
						|
                                                                             \
 | 
						|
    /* encode negative integer using 2's complement */                       \
 | 
						|
    if (with_sign && sign) {                                                 \
 | 
						|
        ret.low = ~ret.low;                                                  \
 | 
						|
        ret.high = ~ret.high;                                                \
 | 
						|
        if (ret.low == UINT_MAX) {                                           \
 | 
						|
            ret.low = 0;                                                     \
 | 
						|
            ret.high++;                                                      \
 | 
						|
        } else                                                               \
 | 
						|
            ret.low++;                                                       \
 | 
						|
    }                                                                        \
 | 
						|
                                                                             \
 | 
						|
    double_unsigned_struct_return(ret);                                      \
 | 
						|
}
 | 
						|
 | 
						|
/* float to unsigned long long conversion */
 | 
						|
DEFINE__AEABI_F2XLZ(f2ulz, 0)
 | 
						|
 | 
						|
/* float to long long conversion */
 | 
						|
DEFINE__AEABI_F2XLZ(f2lz, 1)
 | 
						|
 | 
						|
/* double to [unsigned] long long conversion */
 | 
						|
#define DEFINE__AEABI_D2XLZ(name, with_sign)                                 \
 | 
						|
void __aeabi_ ## name(double_unsigned_struct val)                            \
 | 
						|
{                                                                            \
 | 
						|
    int exp, high_shift, sign;                                               \
 | 
						|
    double_unsigned_struct ret;                                              \
 | 
						|
                                                                             \
 | 
						|
    /* compute sign */                                                       \
 | 
						|
    sign = val.high >> 31;                                                   \
 | 
						|
                                                                             \
 | 
						|
    /* compute real exponent */                                              \
 | 
						|
    exp = (val.high >> (DOUBLE_FRAC_BITS - 32));                             \
 | 
						|
    exp &= (1 << DOUBLE_EXP_BITS) - 1;                                       \
 | 
						|
    exp -= ONE_EXP(DOUBLE);                                                  \
 | 
						|
                                                                             \
 | 
						|
    /* undefined behavior if truncated value cannot be represented */        \
 | 
						|
    if (with_sign) {                                                         \
 | 
						|
        if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
 | 
						|
            return;                                                          \
 | 
						|
    } else {                                                                 \
 | 
						|
        if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */  \
 | 
						|
            return;                                                          \
 | 
						|
    }                                                                        \
 | 
						|
                                                                             \
 | 
						|
    val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1;                          \
 | 
						|
    if (exp >= 32) {                                                         \
 | 
						|
        ret.high = 1 << (exp - 32);                                          \
 | 
						|
        if (exp >= DOUBLE_FRAC_BITS) {                                       \
 | 
						|
            high_shift = exp - DOUBLE_FRAC_BITS;                             \
 | 
						|
            ret.high |= val.high << high_shift;                              \
 | 
						|
            ret.high |= val.low >> (32 - high_shift);                        \
 | 
						|
            ret.low = val.low << high_shift;                                 \
 | 
						|
        } else {                                                             \
 | 
						|
            high_shift = DOUBLE_FRAC_BITS - exp;                             \
 | 
						|
            ret.high |= val.high >> high_shift;                              \
 | 
						|
            ret.low = val.high << (32 - high_shift);                         \
 | 
						|
            ret.low |= val.low >> high_shift;                                \
 | 
						|
        }                                                                    \
 | 
						|
    } else {                                                                 \
 | 
						|
        ret.high = 0;                                                        \
 | 
						|
        ret.low = 1 << exp;                                                  \
 | 
						|
        if (exp > DOUBLE_FRAC_BITS - 32) {                                   \
 | 
						|
            high_shift = exp - DOUBLE_FRAC_BITS - 32;                        \
 | 
						|
            ret.low |= val.high << high_shift;                               \
 | 
						|
            ret.low |= val.low >> (32 - high_shift);                         \
 | 
						|
        } else                                                               \
 | 
						|
            ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp);            \
 | 
						|
    }                                                                        \
 | 
						|
                                                                             \
 | 
						|
    /* encode negative integer using 2's complement */                       \
 | 
						|
    if (with_sign && sign) {                                                 \
 | 
						|
        ret.low = ~ret.low;                                                  \
 | 
						|
        ret.high = ~ret.high;                                                \
 | 
						|
        if (ret.low == UINT_MAX) {                                           \
 | 
						|
            ret.low = 0;                                                     \
 | 
						|
            ret.high++;                                                      \
 | 
						|
        } else                                                               \
 | 
						|
            ret.low++;                                                       \
 | 
						|
    }                                                                        \
 | 
						|
                                                                             \
 | 
						|
    double_unsigned_struct_return(ret);                                      \
 | 
						|
}
 | 
						|
 | 
						|
/* double to unsigned long long conversion */
 | 
						|
DEFINE__AEABI_D2XLZ(d2ulz, 0)
 | 
						|
 | 
						|
/* double to long long conversion */
 | 
						|
DEFINE__AEABI_D2XLZ(d2lz, 1)
 | 
						|
 | 
						|
/* long long to float conversion */
 | 
						|
#define DEFINE__AEABI_XL2F(name, with_sign)                             \
 | 
						|
unsigned __aeabi_ ## name(unsigned long long v)                         \
 | 
						|
{                                                                       \
 | 
						|
    int s /* shift */, flb /* first lost bit */, sign = 0;              \
 | 
						|
    unsigned p = 0 /* power */, ret;                                    \
 | 
						|
    double_unsigned_struct val;                                         \
 | 
						|
                                                                        \
 | 
						|
    /* fraction in negative float is encoded in 1's complement */       \
 | 
						|
    if (with_sign && (v & (1ULL << 63))) {                              \
 | 
						|
        sign = 1;                                                       \
 | 
						|
        v = ~v + 1;                                                     \
 | 
						|
    }                                                                   \
 | 
						|
    val.low = v;                                                        \
 | 
						|
    val.high = v >> 32;                                                 \
 | 
						|
    /* fill fraction bits */                                            \
 | 
						|
    for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1);      \
 | 
						|
    if (p) {                                                            \
 | 
						|
        ret = val.high & (p - 1);                                       \
 | 
						|
        if (s < FLOAT_FRAC_BITS) {                                      \
 | 
						|
            ret <<= FLOAT_FRAC_BITS - s;                                \
 | 
						|
            ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s));             \
 | 
						|
            flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1;    \
 | 
						|
        } else {                                                        \
 | 
						|
            flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1;               \
 | 
						|
            ret >>= s - FLOAT_FRAC_BITS;                                \
 | 
						|
        }                                                               \
 | 
						|
        s += 32;                                                        \
 | 
						|
    } else {                                                            \
 | 
						|
        for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1);   \
 | 
						|
        if (p) {                                                        \
 | 
						|
            ret = val.low & (p - 1);                                    \
 | 
						|
            if (s <= FLOAT_FRAC_BITS) {                                 \
 | 
						|
                ret <<= FLOAT_FRAC_BITS - s;                            \
 | 
						|
                flb = 0;                                                \
 | 
						|
	    } else {                                                    \
 | 
						|
                flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1;           \
 | 
						|
                ret >>= s - FLOAT_FRAC_BITS;                            \
 | 
						|
	    }                                                           \
 | 
						|
        } else                                                          \
 | 
						|
            return 0;                                                   \
 | 
						|
    }                                                                   \
 | 
						|
    if (flb)                                                            \
 | 
						|
        ret++;                                                          \
 | 
						|
                                                                        \
 | 
						|
    /* fill exponent bits */                                            \
 | 
						|
    ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS;                     \
 | 
						|
                                                                        \
 | 
						|
    /* fill sign bit */                                                 \
 | 
						|
    ret |= sign << 31;                                                  \
 | 
						|
                                                                        \
 | 
						|
    return ret;                                                         \
 | 
						|
}
 | 
						|
 | 
						|
/* unsigned long long to float conversion */
 | 
						|
DEFINE__AEABI_XL2F(ul2f, 0)
 | 
						|
 | 
						|
/* long long to float conversion */
 | 
						|
DEFINE__AEABI_XL2F(l2f, 1)
 | 
						|
 | 
						|
/* long long to double conversion */
 | 
						|
#define __AEABI_XL2D(name, with_sign)                                   \
 | 
						|
void __aeabi_ ## name(unsigned long long v)                             \
 | 
						|
{                                                                       \
 | 
						|
    int s /* shift */, high_shift, sign = 0;                            \
 | 
						|
    unsigned tmp, p = 0;                                                \
 | 
						|
    double_unsigned_struct val, ret;                                    \
 | 
						|
                                                                        \
 | 
						|
    /* fraction in negative float is encoded in 1's complement */       \
 | 
						|
    if (with_sign && (v & (1ULL << 63))) {                              \
 | 
						|
        sign = 1;                                                       \
 | 
						|
        v = ~v + 1;                                                     \
 | 
						|
    }                                                                   \
 | 
						|
    val.low = v;                                                        \
 | 
						|
    val.high = v >> 32;                                                 \
 | 
						|
                                                                        \
 | 
						|
    /* fill fraction bits */                                            \
 | 
						|
    for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1);      \
 | 
						|
    if (p) {                                                            \
 | 
						|
        tmp = val.high & (p - 1);                                       \
 | 
						|
        if (s < DOUBLE_FRAC_BITS - 32) {                                \
 | 
						|
            high_shift = DOUBLE_FRAC_BITS - 32 - s;                     \
 | 
						|
            ret.high = tmp << high_shift;                               \
 | 
						|
            ret.high |= val.low >> (32 - high_shift);                   \
 | 
						|
            ret.low = val.low << high_shift;                            \
 | 
						|
        } else {                                                        \
 | 
						|
            high_shift = s - (DOUBLE_FRAC_BITS - 32);                   \
 | 
						|
            ret.high = tmp >> high_shift;                               \
 | 
						|
            ret.low = tmp << (32 - high_shift);                         \
 | 
						|
            ret.low |= val.low >> high_shift;                           \
 | 
						|
            if ((val.low >> (high_shift - 1)) & 1) {                    \
 | 
						|
                if (ret.low == UINT_MAX) {                              \
 | 
						|
                    ret.high++;                                         \
 | 
						|
                    ret.low = 0;                                        \
 | 
						|
		} else                                                  \
 | 
						|
                    ret.low++;                                          \
 | 
						|
            }                                                           \
 | 
						|
        }                                                               \
 | 
						|
        s += 32;                                                        \
 | 
						|
    } else {                                                            \
 | 
						|
        for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1);   \
 | 
						|
        if (p) {                                                        \
 | 
						|
            tmp = val.low & (p - 1);                                    \
 | 
						|
            if (s <= DOUBLE_FRAC_BITS - 32) {                           \
 | 
						|
                high_shift = DOUBLE_FRAC_BITS - 32 - s;                 \
 | 
						|
                ret.high = tmp << high_shift;                           \
 | 
						|
                ret.low = 0;                                            \
 | 
						|
	    } else {                                                    \
 | 
						|
                high_shift = s - (DOUBLE_FRAC_BITS - 32);               \
 | 
						|
                ret.high = tmp >> high_shift;                           \
 | 
						|
                ret.low = tmp << (32 - high_shift);                     \
 | 
						|
            }                                                           \
 | 
						|
        } else {                                                        \
 | 
						|
            ret.high = ret.low = 0;                                     \
 | 
						|
            double_unsigned_struct_return(ret);                         \
 | 
						|
        }                                                               \
 | 
						|
    }                                                                   \
 | 
						|
                                                                        \
 | 
						|
    /* fill exponent bits */                                            \
 | 
						|
    ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32);       \
 | 
						|
                                                                        \
 | 
						|
    /* fill sign bit */                                                 \
 | 
						|
    ret.high |= sign << 31;                                             \
 | 
						|
                                                                        \
 | 
						|
    double_unsigned_struct_return(ret);                                 \
 | 
						|
}
 | 
						|
 | 
						|
/* unsigned long long to double conversion */
 | 
						|
__AEABI_XL2D(ul2d, 0)
 | 
						|
 | 
						|
/* long long to double conversion */
 | 
						|
__AEABI_XL2D(l2d, 1)
 | 
						|
 | 
						|
 | 
						|
/* Long long helper functions */
 | 
						|
 | 
						|
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
 | 
						|
 | 
						|
#define define_aeabi_xdivmod_signed_type(basetype, type) \
 | 
						|
typedef struct type {                                    \
 | 
						|
    basetype quot;                                       \
 | 
						|
    unsigned basetype rem;                               \
 | 
						|
} type
 | 
						|
 | 
						|
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
 | 
						|
typedef struct type {                                      \
 | 
						|
    basetype quot;                                         \
 | 
						|
    basetype rem;                                          \
 | 
						|
} type
 | 
						|
 | 
						|
#define AEABI_UXDIVMOD(name,type, rettype, typemacro)                     \
 | 
						|
static inline rettype aeabi_ ## name (type num, type den)                 \
 | 
						|
{                                                                         \
 | 
						|
    rettype ret;                                                          \
 | 
						|
    type quot = 0;                                                        \
 | 
						|
                                                                          \
 | 
						|
    /* Increase quotient while it is less than numerator */               \
 | 
						|
    while (num >= den) {                                                  \
 | 
						|
        type q = 1;                                                       \
 | 
						|
                                                                          \
 | 
						|
        /* Find closest power of two */                                   \
 | 
						|
        while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
 | 
						|
            q <<= 1;                                                      \
 | 
						|
                                                                          \
 | 
						|
        /* Compute difference between current quotient and numerator */   \
 | 
						|
        num -= q * den;                                                   \
 | 
						|
        quot += q;                                                        \
 | 
						|
    }                                                                     \
 | 
						|
    ret.quot = quot;                                                      \
 | 
						|
    ret.rem = num;                                                        \
 | 
						|
    return ret;                                                           \
 | 
						|
}
 | 
						|
 | 
						|
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro)     \
 | 
						|
void __aeabi_ ## name(type numerator, type denominator)                       \
 | 
						|
{                                                                             \
 | 
						|
    unsigned type num, den;                                                   \
 | 
						|
    urettype uxdiv_ret;                                                       \
 | 
						|
    rettype ret;                                                              \
 | 
						|
                                                                              \
 | 
						|
    if (numerator >= 0)                                                       \
 | 
						|
      num = numerator;                                                        \
 | 
						|
    else                                                                      \
 | 
						|
      num = 0 - numerator;                                                    \
 | 
						|
    if (denominator >= 0)                                                     \
 | 
						|
      den = denominator;                                                      \
 | 
						|
    else                                                                      \
 | 
						|
      den = 0 - denominator;                                                  \
 | 
						|
    uxdiv_ret = aeabi_ ## uiname(num, den);                                   \
 | 
						|
    /* signs differ */                                                        \
 | 
						|
    if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
 | 
						|
        ret.quot = 0 - uxdiv_ret.quot;                                        \
 | 
						|
    else                                                                      \
 | 
						|
        ret.quot = uxdiv_ret.quot;                                            \
 | 
						|
    if (numerator < 0)                                                        \
 | 
						|
        ret.rem = 0 - uxdiv_ret.rem;                                          \
 | 
						|
    else                                                                      \
 | 
						|
        ret.rem = uxdiv_ret.rem;                                              \
 | 
						|
                                                                              \
 | 
						|
    rettype ## _return(ret);                                                  \
 | 
						|
}
 | 
						|
 | 
						|
define_aeabi_xdivmod_signed_type(long long, lldiv_t);
 | 
						|
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
 | 
						|
define_aeabi_xdivmod_signed_type(int, idiv_t);
 | 
						|
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
 | 
						|
 | 
						|
REGS_RETURN(lldiv_t, lldiv_t)
 | 
						|
REGS_RETURN(ulldiv_t, ulldiv_t)
 | 
						|
REGS_RETURN(idiv_t, idiv_t)
 | 
						|
REGS_RETURN(uidiv_t, uidiv_t)
 | 
						|
 | 
						|
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG)
 | 
						|
 | 
						|
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
 | 
						|
 | 
						|
void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
 | 
						|
{
 | 
						|
    ulldiv_t_return(aeabi_uldivmod(num, den));
 | 
						|
}
 | 
						|
 | 
						|
void __aeabi_llsl(double_unsigned_struct val, int shift)
 | 
						|
{
 | 
						|
    double_unsigned_struct ret;
 | 
						|
 | 
						|
    if (shift >= 32) {
 | 
						|
        val.high = val.low;
 | 
						|
        val.low = 0;
 | 
						|
        shift -= 32;
 | 
						|
    }
 | 
						|
    if (shift > 0) {
 | 
						|
        ret.low = val.low << shift;
 | 
						|
        ret.high = (val.high << shift) | (val.low >> (32 - shift));
 | 
						|
        double_unsigned_struct_return(ret);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    double_unsigned_struct_return(val);
 | 
						|
}
 | 
						|
 | 
						|
#define aeabi_lsr(val, shift, fill, type)                          \
 | 
						|
    type ## _struct ret;                                           \
 | 
						|
                                                                   \
 | 
						|
    if (shift >= 32) {                                             \
 | 
						|
        val.low = val.high;                                        \
 | 
						|
        val.high = fill;                                           \
 | 
						|
        shift -= 32;                                               \
 | 
						|
    }                                                              \
 | 
						|
    if (shift > 0) {                                               \
 | 
						|
        ret.high = val.high >> shift;                              \
 | 
						|
        ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
 | 
						|
        type ## _struct_return(ret);                               \
 | 
						|
	return;                                                    \
 | 
						|
    }                                                              \
 | 
						|
    type ## _struct_return(val);
 | 
						|
 | 
						|
void __aeabi_llsr(double_unsigned_struct val, int shift)
 | 
						|
{
 | 
						|
    aeabi_lsr(val, shift, 0, double_unsigned);
 | 
						|
}
 | 
						|
 | 
						|
void __aeabi_lasr(unsigned_int_struct val, int shift)
 | 
						|
{
 | 
						|
    aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Integer division functions */
 | 
						|
 | 
						|
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
 | 
						|
 | 
						|
int __aeabi_idiv(int numerator, int denominator)
 | 
						|
{
 | 
						|
    unsigned num, den;
 | 
						|
    uidiv_t ret;
 | 
						|
 | 
						|
    if (numerator >= 0)
 | 
						|
        num = numerator;
 | 
						|
    else
 | 
						|
        num = 0 - numerator;
 | 
						|
    if (denominator >= 0)
 | 
						|
        den = denominator;
 | 
						|
    else
 | 
						|
        den = 0 - denominator;
 | 
						|
    ret = aeabi_uidivmod(num, den);
 | 
						|
    if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
 | 
						|
        ret.quot *= -1;
 | 
						|
    return ret.quot;
 | 
						|
}
 | 
						|
 | 
						|
unsigned __aeabi_uidiv(unsigned num, unsigned den)
 | 
						|
{
 | 
						|
    return aeabi_uidivmod(num, den).quot;
 | 
						|
}
 | 
						|
 | 
						|
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
 | 
						|
 | 
						|
void __aeabi_uidivmod(unsigned num, unsigned den)
 | 
						|
{
 | 
						|
    uidiv_t_return(aeabi_uidivmod(num, den));
 | 
						|
}
 |