Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
/* * required_arithmetic.h * * by Ian Ollmann * * Copyright (c) Apple Inc, 2007. All Rights Reserved. * * The function of this header is to provide various cLibm routines with * interfaces that cause arithmetic to *always* happen. This header is needed * in various places in Libm, because we use arithmetic to set floating point * state flags. Frequently the product of that arithmetic is not used for the * numerical result of the function, so the compiler erroneously optimizes * it away. The intent of this header is to provide basic operators that * utilize compiler and/or platform specific devices (such as volatile asms) * to prevent the compiler from optimizing away the arithmetic. If no such * device is available, you can encapsulate these operations as non-inlined * functions with the implementation in a separate compilation unit or static * library as required to prevent the compiler from removing them. * * Sample implementations are provided for __i386__, both as sample code and * so we can test the library. Other architectures are required to provide * their own implementation. * */ #if defined( __GNUC__ ) #define ALWAYS_INLINE_NO_DEBUG __attribute__ (( __always_inline__, __nodebug__ ))#else #define ALWAYS_INLINE_NO_DEBUG#endif
#ifndef __arm__ #error This file is for ARM with VFP only#endif
#pragma mark -#pragma mark Declarations
static inline float required_add_float( float a, float b ) ALWAYS_INLINE_NO_DEBUG;static inline float required_multiply_float( float a, float b ) ALWAYS_INLINE_NO_DEBUG;static inline float required_divide_float( float a, float b ) ALWAYS_INLINE_NO_DEBUG;static inline int required_convert_float_to_int( float a ) ALWAYS_INLINE_NO_DEBUG;
static inline double required_add_double( double a, double b ) ALWAYS_INLINE_NO_DEBUG;static inline double required_multiply_double( double a, double b ) ALWAYS_INLINE_NO_DEBUG;static inline double required_divide_double( double a, double b ) ALWAYS_INLINE_NO_DEBUG;static inline int required_convert_double_to_int( double a ) ALWAYS_INLINE_NO_DEBUG;
#pragma mark -#pragma mark Implementation
// --------------------- single precision -------------------------
static inline float required_add_float( float a, float b ){ register float r; __asm__ __volatile__ ( "fadds %0, %1, %2" : "=w" (r) : "w" (a), "w" (b) ); return r;}
static inline float required_multiply_float( float a, float b ){ register float r; __asm__ __volatile__ ( "fmuls %0, %1, %2" : "=w" (r) : "w" (a), "w" (b) ); return r;}
static inline float required_divide_float( float a, float b ){ register float r; __asm__ __volatile__ ( "fdivs %0, %1, %2" : "=w" (r) : "w" (a), "w" (b) ); return r;}
//rounds toward zerostatic inline int required_convert_float_to_int( float a ){ register float temp; register int result; __asm__ __volatile__ ( "ftosizs %0, %1" : "=w" (temp) : "w" (a) ); __asm__ __volatile__ ( "fmrs %0, %1" : "=r" (result) : "w" (temp) );
return result;}
// ---------------- double precision --------------------------
static inline double required_add_double( double a, double b ){ register double r; __asm__ __volatile__ ( "faddd %P0, %P1, %P2" : "=w" (r) : "w" (a), "w" (b) ); return r;}
static inline double required_multiply_double( double a, double b ){ register double r; __asm__ __volatile__ ( "fmuld %P0, %P1, %P2" : "=w" (r) : "w" (a), "w" (b) ); return r;}
static inline double required_divide_double( double a, double b ){ register double r; __asm__ __volatile__ ( "fdivd %P0, %P1, %P2" : "=w" (r) : "w" (a), "w" (b) ); return r;}
//rounds toward zerostatic inline int required_convert_double_to_int( double a ){ register float temp; register int result; __asm__ __volatile__ ( "ftosizd %0, %P1" : "=w" (temp) : "w" (a) ); __asm__ __volatile__ ( "fmrs %0, %1" : "=r" (result) : "w" (temp) );
return result;}