/[qemu]/qemu/target-arm/op_helper.c
ViewVC logotype

Diff of /qemu/target-arm/op_helper.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by bellard, Tue Feb 22 19:27:29 2005 UTC revision 1.2 by bellard, Sun Mar 13 18:50:12 2005 UTC
# Line 17  Line 17 
17   * License along with this library; if not, write to the Free Software   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   */   */
   
 #include <math.h>  
 #include <fenv.h>  
20  #include "exec.h"  #include "exec.h"
21    
 /* If the host doesn't define C99 math intrinsics then use the normal  
    operators.  This may generate excess exceptions, but it's probably  
    near enough for most things.  */  
 #ifndef isless  
 #define isless(x, y) (x < y)  
 #endif  
 #ifndef isgreater  
 #define isgreater(x, y) (x > y)  
 #endif  
 #ifndef isunordered  
 #define isunordered(x, y) (!((x < y) || (x >= y)))  
 #endif  
   
22  void raise_exception(int tt)  void raise_exception(int tt)
23  {  {
24      env->exception_index = tt;      env->exception_index = tt;
# Line 59  void cpu_unlock(void) Line 43  void cpu_unlock(void)
43    
44  void do_vfp_abss(void)  void do_vfp_abss(void)
45  {  {
46    FT0s = fabsf(FT0s);      FT0s = float32_abs(FT0s);
47  }  }
48    
49  void do_vfp_absd(void)  void do_vfp_absd(void)
50  {  {
51    FT0d = fabs(FT0d);      FT0d = float64_abs(FT0d);
52  }  }
53    
54  void do_vfp_sqrts(void)  void do_vfp_sqrts(void)
55  {  {
56    FT0s = sqrtf(FT0s);      FT0s = float32_sqrt(FT0s, &env->vfp.fp_status);
57  }  }
58    
59  void do_vfp_sqrtd(void)  void do_vfp_sqrtd(void)
60  {  {
61    FT0d = sqrt(FT0d);      FT0d = float64_sqrt(FT0d, &env->vfp.fp_status);
62  }  }
63    
64  /* We use an == operator first to generate teh correct floating point  /* XXX: check quiet/signaling case */
65     exception.  Subsequent comparisons use the exception-safe macros.  */  #define DO_VFP_cmp(p, size)               \
 #define DO_VFP_cmp(p)                     \  
66  void do_vfp_cmp##p(void)                  \  void do_vfp_cmp##p(void)                  \
67  {                                         \  {                                         \
68      uint32_t flags;                       \      uint32_t flags;                       \
69      if (FT0##p == FT1##p)                 \      switch(float ## size ## _compare_quiet(FT0##p, FT1##p, &env->vfp.fp_status)) {\
70          flags = 0xc;                      \      case 0: flags = 0xc; break;\
71      else if (isless (FT0##p, FT1##p))     \      case -1: flags = 0x8; break;\
72          flags = 0x8;                      \      case 1: flags = 0x2; break;\
73      else if (isgreater (FT0##p, FT1##p))  \      default: case 2: flags = 0x3; break;\
74          flags = 0x2;                      \      }\
     else /* unordered */                  \  
         flags = 0x3;                      \  
75      env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \      env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
76      FORCE_RET();                          \      FORCE_RET();                          \
77  }  }\
78  DO_VFP_cmp(s)  \
 DO_VFP_cmp(d)  
 #undef DO_VFP_cmp  
   
 /* We use a > operator first to get FP exceptions right.  */  
 #define DO_VFP_cmpe(p)                      \  
79  void do_vfp_cmpe##p(void)                   \  void do_vfp_cmpe##p(void)                   \
80  {                                           \  {                                           \
81      uint32_t flags;                         \      uint32_t flags;                       \
82      if (FT0##p > FT1##p)                    \      switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\
83          flags = 0x2;                        \      case 0: flags = 0xc; break;\
84      else if (isless (FT0##p, FT1##p))       \      case -1: flags = 0x8; break;\
85          flags = 0x8;                        \      case 1: flags = 0x2; break;\
86      else if (isunordered (FT0##p, FT1##p))  \      default: case 2: flags = 0x3; break;\
87          flags = 0x3;                        \      }\
     else /* equal */                        \  
         flags = 0xc;                        \  
88      env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \      env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
89      FORCE_RET();                            \      FORCE_RET();                          \
90  }  }
91  DO_VFP_cmpe(s)  DO_VFP_cmp(s, 32)
92  DO_VFP_cmpe(d)  DO_VFP_cmp(d, 64)
93  #undef DO_VFP_cmpe  #undef DO_VFP_cmp
94    
95  /* Convert host exception flags to vfp form.  */  /* Convert host exception flags to vfp form.  */
96  int vfp_exceptbits_from_host(int host_bits)  static inline int vfp_exceptbits_from_host(int host_bits)
97  {  {
98      int target_bits = 0;      int target_bits = 0;
99    
100  #ifdef FE_INVALID      if (host_bits & float_flag_invalid)
     if (host_bits & FE_INVALID)  
101          target_bits |= 1;          target_bits |= 1;
102  #endif      if (host_bits & float_flag_divbyzero)
 #ifdef FE_DIVBYZERO  
     if (host_bits & FE_DIVBYZERO)  
103          target_bits |= 2;          target_bits |= 2;
104  #endif      if (host_bits & float_flag_overflow)
 #ifdef FE_OVERFLOW  
     if (host_bits & FE_OVERFLOW)  
105          target_bits |= 4;          target_bits |= 4;
106  #endif      if (host_bits & float_flag_underflow)
 #ifdef FE_UNDERFLOW  
     if (host_bits & FE_UNDERFLOW)  
107          target_bits |= 8;          target_bits |= 8;
108  #endif      if (host_bits & float_flag_inexact)
 #ifdef FE_INEXACT  
     if (host_bits & FE_INEXACT)  
109          target_bits |= 0x10;          target_bits |= 0x10;
 #endif  
     /* C doesn't define an inexact exception.  */  
110      return target_bits;      return target_bits;
111  }  }
112    
113  /* Convert vfp exception flags to target form.  */  /* Convert vfp exception flags to target form.  */
114  int vfp_host_exceptbits_to_host(int target_bits)  static inline int vfp_exceptbits_to_host(int target_bits)
115  {  {
116      int host_bits = 0;      int host_bits = 0;
117    
 #ifdef FE_INVALID  
118      if (target_bits & 1)      if (target_bits & 1)
119          host_bits |= FE_INVALID;          host_bits |= float_flag_invalid;
 #endif  
 #ifdef FE_DIVBYZERO  
120      if (target_bits & 2)      if (target_bits & 2)
121          host_bits |= FE_DIVBYZERO;          host_bits |= float_flag_divbyzero;
 #endif  
 #ifdef FE_OVERFLOW  
122      if (target_bits & 4)      if (target_bits & 4)
123          host_bits |= FE_OVERFLOW;          host_bits |= float_flag_overflow;
 #endif  
 #ifdef FE_UNDERFLOW  
124      if (target_bits & 8)      if (target_bits & 8)
125          host_bits |= FE_UNDERFLOW;          host_bits |= float_flag_underflow;
 #endif  
 #ifdef FE_INEXACT  
126      if (target_bits & 0x10)      if (target_bits & 0x10)
127          host_bits |= FE_INEXACT;          host_bits |= float_flag_inexact;
 #endif  
128      return host_bits;      return host_bits;
129  }  }
130    
# Line 190  void do_vfp_set_fpscr(void) Line 143  void do_vfp_set_fpscr(void)
143          i = (T0 >> 22) & 3;          i = (T0 >> 22) & 3;
144          switch (i) {          switch (i) {
145          case 0:          case 0:
146              i = FE_TONEAREST;              i = float_round_nearest_even;
147              break;              break;
148          case 1:          case 1:
149              i = FE_UPWARD;              i = float_round_up;
150              break;              break;
151          case 2:          case 2:
152              i = FE_DOWNWARD;              i = float_round_down;
153              break;              break;
154          case 3:          case 3:
155              i = FE_TOWARDZERO;              i = float_round_to_zero;
156              break;              break;
157          }          }
158          fesetround (i);          set_float_rounding_mode(i, &env->vfp.fp_status);
159      }      }
160    
161      /* Clear host exception flags.  */      i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
162      feclearexcept(FE_ALL_EXCEPT);      set_float_exception_flags(i, &env->vfp.fp_status);
   
 #ifdef feenableexcept  
     if (changed & 0x1f00) {  
         i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);  
         feenableexcept (i);  
         fedisableexcept (FE_ALL_EXCEPT & ~i);  
     }  
 #endif  
163      /* XXX: FZ and DN are not implemented.  */      /* XXX: FZ and DN are not implemented.  */
164  }  }
165    
# Line 224  void do_vfp_get_fpscr(void) Line 169  void do_vfp_get_fpscr(void)
169    
170      T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)      T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)
171            | (env->vfp.vec_stride << 20);            | (env->vfp.vec_stride << 20);
172      i = fetestexcept(FE_ALL_EXCEPT);      i = get_float_exception_flags(&env->vfp.fp_status);
173      T0 |= vfp_exceptbits_from_host(i);      T0 |= vfp_exceptbits_from_host(i);
174  }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26