this repo has no description
1
2/*
3 * required_arithmetic.h
4 *
5 * by Ian Ollmann
6 *
7 * Copyright (c) Apple Inc, 2007. All Rights Reserved.
8 *
9 * The function of this header is to provide various cLibm routines with
10 * interfaces that cause arithmetic to *always* happen. This header is needed
11 * in various places in Libm, because we use arithmetic to set floating point
12 * state flags. Frequently the product of that arithmetic is not used for the
13 * numerical result of the function, so the compiler erroneously optimizes
14 * it away. The intent of this header is to provide basic operators that
15 * utilize compiler and/or platform specific devices (such as volatile asms)
16 * to prevent the compiler from optimizing away the arithmetic. If no such
17 * device is available, you can encapsulate these operations as non-inlined
18 * functions with the implementation in a separate compilation unit or static
19 * library as required to prevent the compiler from removing them.
20 *
21 * Sample implementations are provided for __i386__, both as sample code and
22 * so we can test the library. Other architectures are required to provide
23 * their own implementation.
24 *
25 */
26
27#if defined( __GNUC__ )
28 #define ALWAYS_INLINE_NO_DEBUG __attribute__ (( __always_inline__, __nodebug__ ))
29#else
30 #define ALWAYS_INLINE_NO_DEBUG
31#endif
32
33#ifndef __arm__
34 #error This file is for ARM with VFP only
35#endif
36
37
38#pragma mark -
39#pragma mark Declarations
40
41static inline float required_add_float( float a, float b ) ALWAYS_INLINE_NO_DEBUG;
42static inline float required_multiply_float( float a, float b ) ALWAYS_INLINE_NO_DEBUG;
43static inline float required_divide_float( float a, float b ) ALWAYS_INLINE_NO_DEBUG;
44static inline int required_convert_float_to_int( float a ) ALWAYS_INLINE_NO_DEBUG;
45
46static inline double required_add_double( double a, double b ) ALWAYS_INLINE_NO_DEBUG;
47static inline double required_multiply_double( double a, double b ) ALWAYS_INLINE_NO_DEBUG;
48static inline double required_divide_double( double a, double b ) ALWAYS_INLINE_NO_DEBUG;
49static inline int required_convert_double_to_int( double a ) ALWAYS_INLINE_NO_DEBUG;
50
51#pragma mark -
52#pragma mark Implementation
53
54// --------------------- single precision -------------------------
55
56static inline float required_add_float( float a, float b )
57{
58 register float r;
59 __asm__ __volatile__ ( "fadds %0, %1, %2" : "=w" (r) : "w" (a), "w" (b) );
60 return r;
61}
62
63static inline float required_multiply_float( float a, float b )
64{
65 register float r;
66 __asm__ __volatile__ ( "fmuls %0, %1, %2" : "=w" (r) : "w" (a), "w" (b) );
67 return r;
68}
69
70static inline float required_divide_float( float a, float b )
71{
72 register float r;
73 __asm__ __volatile__ ( "fdivs %0, %1, %2" : "=w" (r) : "w" (a), "w" (b) );
74 return r;
75}
76
77//rounds toward zero
78static inline int required_convert_float_to_int( float a )
79{
80 register float temp;
81 register int result;
82
83 __asm__ __volatile__ ( "ftosizs %0, %1" : "=w" (temp) : "w" (a) );
84 __asm__ __volatile__ ( "fmrs %0, %1" : "=r" (result) : "w" (temp) );
85
86 return result;
87}
88
89// ---------------- double precision --------------------------
90
91static inline double required_add_double( double a, double b )
92{
93 register double r;
94 __asm__ __volatile__ ( "faddd %P0, %P1, %P2" : "=w" (r) : "w" (a), "w" (b) );
95 return r;
96}
97
98static inline double required_multiply_double( double a, double b )
99{
100 register double r;
101 __asm__ __volatile__ ( "fmuld %P0, %P1, %P2" : "=w" (r) : "w" (a), "w" (b) );
102 return r;
103}
104
105static inline double required_divide_double( double a, double b )
106{
107 register double r;
108 __asm__ __volatile__ ( "fdivd %P0, %P1, %P2" : "=w" (r) : "w" (a), "w" (b) );
109 return r;
110}
111
112//rounds toward zero
113static inline int required_convert_double_to_int( double a )
114{
115 register float temp;
116 register int result;
117
118 __asm__ __volatile__ ( "ftosizd %0, %P1" : "=w" (temp) : "w" (a) );
119 __asm__ __volatile__ ( "fmrs %0, %1" : "=r" (result) : "w" (temp) );
120
121 return result;
122}
123