Commit 53cd6637924a83481038b2266c59dc1e1ff7bb11
1 parent
7a0e1f41
soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1337 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
119 additions
and
166 deletions
cpu-all.h
... | ... | @@ -119,7 +119,7 @@ static inline void tswap64s(uint64_t *s) |
119 | 119 | /* NOTE: arm FPA is horrible as double 32 bit words are stored in big |
120 | 120 | endian ! */ |
121 | 121 | typedef union { |
122 | - double d; | |
122 | + float64 d; | |
123 | 123 | #if defined(WORDS_BIGENDIAN) || (defined(__arm__) && !defined(__VFP_FP__)) |
124 | 124 | struct { |
125 | 125 | uint32_t upper; |
... | ... | @@ -268,27 +268,27 @@ static inline void stq_p(void *ptr, uint64_t v) |
268 | 268 | |
269 | 269 | /* float access */ |
270 | 270 | |
271 | -static inline float ldfl_p(void *ptr) | |
271 | +static inline float32 ldfl_p(void *ptr) | |
272 | 272 | { |
273 | 273 | union { |
274 | - float f; | |
274 | + float32 f; | |
275 | 275 | uint32_t i; |
276 | 276 | } u; |
277 | 277 | u.i = ldl_p(ptr); |
278 | 278 | return u.f; |
279 | 279 | } |
280 | 280 | |
281 | -static inline void stfl_p(void *ptr, float v) | |
281 | +static inline void stfl_p(void *ptr, float32 v) | |
282 | 282 | { |
283 | 283 | union { |
284 | - float f; | |
284 | + float32 f; | |
285 | 285 | uint32_t i; |
286 | 286 | } u; |
287 | 287 | u.f = v; |
288 | 288 | stl_p(ptr, u.i); |
289 | 289 | } |
290 | 290 | |
291 | -static inline double ldfq_p(void *ptr) | |
291 | +static inline float64 ldfq_p(void *ptr) | |
292 | 292 | { |
293 | 293 | CPU_DoubleU u; |
294 | 294 | u.l.lower = ldl_p(ptr); |
... | ... | @@ -296,7 +296,7 @@ static inline double ldfq_p(void *ptr) |
296 | 296 | return u.d; |
297 | 297 | } |
298 | 298 | |
299 | -static inline void stfq_p(void *ptr, double v) | |
299 | +static inline void stfq_p(void *ptr, float64 v) | |
300 | 300 | { |
301 | 301 | CPU_DoubleU u; |
302 | 302 | u.d = v; |
... | ... | @@ -397,27 +397,27 @@ static inline void stq_p(void *ptr, uint64_t v) |
397 | 397 | |
398 | 398 | /* float access */ |
399 | 399 | |
400 | -static inline float ldfl_p(void *ptr) | |
400 | +static inline float32 ldfl_p(void *ptr) | |
401 | 401 | { |
402 | 402 | union { |
403 | - float f; | |
403 | + float32 f; | |
404 | 404 | uint32_t i; |
405 | 405 | } u; |
406 | 406 | u.i = ldl_p(ptr); |
407 | 407 | return u.f; |
408 | 408 | } |
409 | 409 | |
410 | -static inline void stfl_p(void *ptr, float v) | |
410 | +static inline void stfl_p(void *ptr, float32 v) | |
411 | 411 | { |
412 | 412 | union { |
413 | - float f; | |
413 | + float32 f; | |
414 | 414 | uint32_t i; |
415 | 415 | } u; |
416 | 416 | u.f = v; |
417 | 417 | stl_p(ptr, u.i); |
418 | 418 | } |
419 | 419 | |
420 | -static inline double ldfq_p(void *ptr) | |
420 | +static inline float64 ldfq_p(void *ptr) | |
421 | 421 | { |
422 | 422 | CPU_DoubleU u; |
423 | 423 | u.l.upper = ldl_p(ptr); |
... | ... | @@ -425,7 +425,7 @@ static inline double ldfq_p(void *ptr) |
425 | 425 | return u.d; |
426 | 426 | } |
427 | 427 | |
428 | -static inline void stfq_p(void *ptr, double v) | |
428 | +static inline void stfq_p(void *ptr, float64 v) | |
429 | 429 | { |
430 | 430 | CPU_DoubleU u; |
431 | 431 | u.d = v; |
... | ... | @@ -472,24 +472,24 @@ static inline void stq_p(void *ptr, uint64_t v) |
472 | 472 | |
473 | 473 | /* float access */ |
474 | 474 | |
475 | -static inline float ldfl_p(void *ptr) | |
475 | +static inline float32 ldfl_p(void *ptr) | |
476 | 476 | { |
477 | - return *(float *)ptr; | |
477 | + return *(float32 *)ptr; | |
478 | 478 | } |
479 | 479 | |
480 | -static inline double ldfq_p(void *ptr) | |
480 | +static inline float64 ldfq_p(void *ptr) | |
481 | 481 | { |
482 | - return *(double *)ptr; | |
482 | + return *(float64 *)ptr; | |
483 | 483 | } |
484 | 484 | |
485 | -static inline void stfl_p(void *ptr, float v) | |
485 | +static inline void stfl_p(void *ptr, float32 v) | |
486 | 486 | { |
487 | - *(float *)ptr = v; | |
487 | + *(float32 *)ptr = v; | |
488 | 488 | } |
489 | 489 | |
490 | -static inline void stfq_p(void *ptr, double v) | |
490 | +static inline void stfq_p(void *ptr, float64 v) | |
491 | 491 | { |
492 | - *(double *)ptr = v; | |
492 | + *(float64 *)ptr = v; | |
493 | 493 | } |
494 | 494 | #endif |
495 | 495 | ... | ... |
target-arm/cpu.h
... | ... | @@ -24,6 +24,8 @@ |
24 | 24 | |
25 | 25 | #include "cpu-defs.h" |
26 | 26 | |
27 | +#include "softfloat.h" | |
28 | + | |
27 | 29 | #define EXCP_UDEF 1 /* undefined instruction */ |
28 | 30 | #define EXCP_SWI 2 /* software interrupt */ |
29 | 31 | #define EXCP_PREFETCH_ABORT 3 |
... | ... | @@ -70,8 +72,8 @@ typedef struct CPUARMState { |
70 | 72 | /* VFP coprocessor state. */ |
71 | 73 | struct { |
72 | 74 | union { |
73 | - float s[32]; | |
74 | - double d[16]; | |
75 | + float32 s[32]; | |
76 | + float64 d[16]; | |
75 | 77 | } regs; |
76 | 78 | |
77 | 79 | /* We store these fpcsr fields separately for convenience. */ |
... | ... | @@ -81,9 +83,10 @@ typedef struct CPUARMState { |
81 | 83 | uint32_t fpscr; |
82 | 84 | |
83 | 85 | /* Temporary variables if we don't have spare fp regs. */ |
84 | - float tmp0s, tmp1s; | |
85 | - double tmp0d, tmp1d; | |
86 | - | |
86 | + float32 tmp0s, tmp1s; | |
87 | + float64 tmp0d, tmp1d; | |
88 | + | |
89 | + float_status fp_status; | |
87 | 90 | } vfp; |
88 | 91 | |
89 | 92 | /* user data */ | ... | ... |
target-arm/op.c
... | ... | @@ -864,19 +864,19 @@ void OPPROTO op_undef_insn(void) |
864 | 864 | |
865 | 865 | #define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void) |
866 | 866 | |
867 | -#define VFP_BINOP(name, op) \ | |
867 | +#define VFP_BINOP(name) \ | |
868 | 868 | VFP_OP(name, s) \ |
869 | 869 | { \ |
870 | - FT0s = FT0s op FT1s; \ | |
870 | + FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status); \ | |
871 | 871 | } \ |
872 | 872 | VFP_OP(name, d) \ |
873 | 873 | { \ |
874 | - FT0d = FT0d op FT1d; \ | |
874 | + FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status); \ | |
875 | 875 | } |
876 | -VFP_BINOP(add, +) | |
877 | -VFP_BINOP(sub, -) | |
878 | -VFP_BINOP(mul, *) | |
879 | -VFP_BINOP(div, /) | |
876 | +VFP_BINOP(add) | |
877 | +VFP_BINOP(sub) | |
878 | +VFP_BINOP(mul) | |
879 | +VFP_BINOP(div) | |
880 | 880 | #undef VFP_BINOP |
881 | 881 | |
882 | 882 | #define VFP_HELPER(name) \ |
... | ... | @@ -898,41 +898,51 @@ VFP_HELPER(cmpe) |
898 | 898 | without looking at the rest of the value. */ |
899 | 899 | VFP_OP(neg, s) |
900 | 900 | { |
901 | - FT0s = -FT0s; | |
901 | + FT0s = float32_chs(FT0s); | |
902 | 902 | } |
903 | 903 | |
904 | 904 | VFP_OP(neg, d) |
905 | 905 | { |
906 | - FT0d = -FT0d; | |
906 | + FT0d = float64_chs(FT0d); | |
907 | 907 | } |
908 | 908 | |
909 | 909 | VFP_OP(F1_ld0, s) |
910 | 910 | { |
911 | - FT1s = 0.0f; | |
911 | + union { | |
912 | + uint32_t i; | |
913 | + float32 s; | |
914 | + } v; | |
915 | + v.i = 0; | |
916 | + FT1s = v.s; | |
912 | 917 | } |
913 | 918 | |
914 | 919 | VFP_OP(F1_ld0, d) |
915 | 920 | { |
916 | - FT1d = 0.0; | |
921 | + union { | |
922 | + uint64_t i; | |
923 | + float64 d; | |
924 | + } v; | |
925 | + v.i = 0; | |
926 | + FT1d = v.d; | |
917 | 927 | } |
918 | 928 | |
919 | 929 | /* Helper routines to perform bitwise copies between float and int. */ |
920 | -static inline float vfp_itos(uint32_t i) | |
930 | +static inline float32 vfp_itos(uint32_t i) | |
921 | 931 | { |
922 | 932 | union { |
923 | 933 | uint32_t i; |
924 | - float s; | |
934 | + float32 s; | |
925 | 935 | } v; |
926 | 936 | |
927 | 937 | v.i = i; |
928 | 938 | return v.s; |
929 | 939 | } |
930 | 940 | |
931 | -static inline uint32_t vfp_stoi(float s) | |
941 | +static inline uint32_t vfp_stoi(float32 s) | |
932 | 942 | { |
933 | 943 | union { |
934 | 944 | uint32_t i; |
935 | - float s; | |
945 | + float32 s; | |
936 | 946 | } v; |
937 | 947 | |
938 | 948 | v.s = s; |
... | ... | @@ -942,111 +952,106 @@ static inline uint32_t vfp_stoi(float s) |
942 | 952 | /* Integer to float conversion. */ |
943 | 953 | VFP_OP(uito, s) |
944 | 954 | { |
945 | - FT0s = (float)(uint32_t)vfp_stoi(FT0s); | |
955 | + FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); | |
946 | 956 | } |
947 | 957 | |
948 | 958 | VFP_OP(uito, d) |
949 | 959 | { |
950 | - FT0d = (double)(uint32_t)vfp_stoi(FT0s); | |
960 | + FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); | |
951 | 961 | } |
952 | 962 | |
953 | 963 | VFP_OP(sito, s) |
954 | 964 | { |
955 | - FT0s = (float)(int32_t)vfp_stoi(FT0s); | |
965 | + FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); | |
956 | 966 | } |
957 | 967 | |
958 | 968 | VFP_OP(sito, d) |
959 | 969 | { |
960 | - FT0d = (double)(int32_t)vfp_stoi(FT0s); | |
970 | + FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); | |
961 | 971 | } |
962 | 972 | |
963 | 973 | /* Float to integer conversion. */ |
964 | 974 | VFP_OP(toui, s) |
965 | 975 | { |
966 | - FT0s = vfp_itos((uint32_t)FT0s); | |
976 | + FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status)); | |
967 | 977 | } |
968 | 978 | |
969 | 979 | VFP_OP(toui, d) |
970 | 980 | { |
971 | - FT0s = vfp_itos((uint32_t)FT0d); | |
981 | + FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status)); | |
972 | 982 | } |
973 | 983 | |
974 | 984 | VFP_OP(tosi, s) |
975 | 985 | { |
976 | - FT0s = vfp_itos((int32_t)FT0s); | |
986 | + FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status)); | |
977 | 987 | } |
978 | 988 | |
979 | 989 | VFP_OP(tosi, d) |
980 | 990 | { |
981 | - FT0s = vfp_itos((int32_t)FT0d); | |
991 | + FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status)); | |
982 | 992 | } |
983 | 993 | |
984 | 994 | /* TODO: Set rounding mode properly. */ |
985 | 995 | VFP_OP(touiz, s) |
986 | 996 | { |
987 | - FT0s = vfp_itos((uint32_t)FT0s); | |
997 | + FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status)); | |
988 | 998 | } |
989 | 999 | |
990 | 1000 | VFP_OP(touiz, d) |
991 | 1001 | { |
992 | - FT0s = vfp_itos((uint32_t)FT0d); | |
1002 | + FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status)); | |
993 | 1003 | } |
994 | 1004 | |
995 | 1005 | VFP_OP(tosiz, s) |
996 | 1006 | { |
997 | - FT0s = vfp_itos((int32_t)FT0s); | |
1007 | + FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status)); | |
998 | 1008 | } |
999 | 1009 | |
1000 | 1010 | VFP_OP(tosiz, d) |
1001 | 1011 | { |
1002 | - FT0s = vfp_itos((int32_t)FT0d); | |
1012 | + FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status)); | |
1003 | 1013 | } |
1004 | 1014 | |
1005 | 1015 | /* floating point conversion */ |
1006 | 1016 | VFP_OP(fcvtd, s) |
1007 | 1017 | { |
1008 | - FT0d = (double)FT0s; | |
1018 | + FT0d = float32_to_float64(FT0s, &env->vfp.fp_status); | |
1009 | 1019 | } |
1010 | 1020 | |
1011 | 1021 | VFP_OP(fcvts, d) |
1012 | 1022 | { |
1013 | - FT0s = (float)FT0d; | |
1023 | + FT0s = float64_to_float32(FT0d, &env->vfp.fp_status); | |
1014 | 1024 | } |
1015 | 1025 | |
1016 | 1026 | /* Get and Put values from registers. */ |
1017 | 1027 | VFP_OP(getreg_F0, d) |
1018 | 1028 | { |
1019 | - FT0d = *(double *)((char *) env + PARAM1); | |
1029 | + FT0d = *(float64 *)((char *) env + PARAM1); | |
1020 | 1030 | } |
1021 | 1031 | |
1022 | 1032 | VFP_OP(getreg_F0, s) |
1023 | 1033 | { |
1024 | - FT0s = *(float *)((char *) env + PARAM1); | |
1034 | + FT0s = *(float32 *)((char *) env + PARAM1); | |
1025 | 1035 | } |
1026 | 1036 | |
1027 | 1037 | VFP_OP(getreg_F1, d) |
1028 | 1038 | { |
1029 | - FT1d = *(double *)((char *) env + PARAM1); | |
1039 | + FT1d = *(float64 *)((char *) env + PARAM1); | |
1030 | 1040 | } |
1031 | 1041 | |
1032 | 1042 | VFP_OP(getreg_F1, s) |
1033 | 1043 | { |
1034 | - FT1s = *(float *)((char *) env + PARAM1); | |
1044 | + FT1s = *(float32 *)((char *) env + PARAM1); | |
1035 | 1045 | } |
1036 | 1046 | |
1037 | 1047 | VFP_OP(setreg_F0, d) |
1038 | 1048 | { |
1039 | - *(double *)((char *) env + PARAM1) = FT0d; | |
1049 | + *(float64 *)((char *) env + PARAM1) = FT0d; | |
1040 | 1050 | } |
1041 | 1051 | |
1042 | 1052 | VFP_OP(setreg_F0, s) |
1043 | 1053 | { |
1044 | - *(float *)((char *) env + PARAM1) = FT0s; | |
1045 | -} | |
1046 | - | |
1047 | -VFP_OP(foobar, d) | |
1048 | -{ | |
1049 | - FT0d = env->vfp.regs.s[3]; | |
1054 | + *(float32 *)((char *) env + PARAM1) = FT0s; | |
1050 | 1055 | } |
1051 | 1056 | |
1052 | 1057 | void OPPROTO op_vfp_movl_T0_fpscr(void) | ... | ... |
target-arm/op_helper.c
... | ... | @@ -17,24 +17,8 @@ |
17 | 17 | * License along with this library; if not, write to the Free Software |
18 | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | 19 | */ |
20 | - | |
21 | -#include <math.h> | |
22 | -#include <fenv.h> | |
23 | 20 | #include "exec.h" |
24 | 21 | |
25 | -/* If the host doesn't define C99 math intrinsics then use the normal | |
26 | - operators. This may generate excess exceptions, but it's probably | |
27 | - near enough for most things. */ | |
28 | -#ifndef isless | |
29 | -#define isless(x, y) (x < y) | |
30 | -#endif | |
31 | -#ifndef isgreater | |
32 | -#define isgreater(x, y) (x > y) | |
33 | -#endif | |
34 | -#ifndef isunordered | |
35 | -#define isunordered(x, y) (!((x < y) || (x >= y))) | |
36 | -#endif | |
37 | - | |
38 | 22 | void raise_exception(int tt) |
39 | 23 | { |
40 | 24 | env->exception_index = tt; |
... | ... | @@ -59,119 +43,88 @@ void cpu_unlock(void) |
59 | 43 | |
60 | 44 | void do_vfp_abss(void) |
61 | 45 | { |
62 | - FT0s = fabsf(FT0s); | |
46 | + FT0s = float32_abs(FT0s); | |
63 | 47 | } |
64 | 48 | |
65 | 49 | void do_vfp_absd(void) |
66 | 50 | { |
67 | - FT0d = fabs(FT0d); | |
51 | + FT0d = float64_abs(FT0d); | |
68 | 52 | } |
69 | 53 | |
70 | 54 | void do_vfp_sqrts(void) |
71 | 55 | { |
72 | - FT0s = sqrtf(FT0s); | |
56 | + FT0s = float32_sqrt(FT0s, &env->vfp.fp_status); | |
73 | 57 | } |
74 | 58 | |
75 | 59 | void do_vfp_sqrtd(void) |
76 | 60 | { |
77 | - FT0d = sqrt(FT0d); | |
61 | + FT0d = float64_sqrt(FT0d, &env->vfp.fp_status); | |
78 | 62 | } |
79 | 63 | |
80 | -/* We use an == operator first to generate teh correct floating point | |
81 | - exception. Subsequent comparisons use the exception-safe macros. */ | |
82 | -#define DO_VFP_cmp(p) \ | |
64 | +/* XXX: check quiet/signaling case */ | |
65 | +#define DO_VFP_cmp(p, size) \ | |
83 | 66 | void do_vfp_cmp##p(void) \ |
84 | 67 | { \ |
85 | 68 | uint32_t flags; \ |
86 | - if (FT0##p == FT1##p) \ | |
87 | - flags = 0xc; \ | |
88 | - else if (isless (FT0##p, FT1##p)) \ | |
89 | - flags = 0x8; \ | |
90 | - else if (isgreater (FT0##p, FT1##p)) \ | |
91 | - flags = 0x2; \ | |
92 | - else /* unordered */ \ | |
93 | - flags = 0x3; \ | |
69 | + switch(float ## size ## _compare_quiet(FT0##p, FT1##p, &env->vfp.fp_status)) {\ | |
70 | + case 0: flags = 0xc; break;\ | |
71 | + case -1: flags = 0x8; break;\ | |
72 | + case 1: flags = 0x2; break;\ | |
73 | + default: case 2: flags = 0x3; break;\ | |
74 | + }\ | |
94 | 75 | env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \ |
95 | 76 | FORCE_RET(); \ |
96 | -} | |
97 | -DO_VFP_cmp(s) | |
98 | -DO_VFP_cmp(d) | |
99 | -#undef DO_VFP_cmp | |
100 | - | |
101 | -/* We use a > operator first to get FP exceptions right. */ | |
102 | -#define DO_VFP_cmpe(p) \ | |
77 | +}\ | |
78 | +\ | |
103 | 79 | void do_vfp_cmpe##p(void) \ |
104 | 80 | { \ |
105 | - uint32_t flags; \ | |
106 | - if (FT0##p > FT1##p) \ | |
107 | - flags = 0x2; \ | |
108 | - else if (isless (FT0##p, FT1##p)) \ | |
109 | - flags = 0x8; \ | |
110 | - else if (isunordered (FT0##p, FT1##p)) \ | |
111 | - flags = 0x3; \ | |
112 | - else /* equal */ \ | |
113 | - flags = 0xc; \ | |
81 | + uint32_t flags; \ | |
82 | + switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\ | |
83 | + case 0: flags = 0xc; break;\ | |
84 | + case -1: flags = 0x8; break;\ | |
85 | + case 1: flags = 0x2; break;\ | |
86 | + default: case 2: flags = 0x3; break;\ | |
87 | + }\ | |
114 | 88 | env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \ |
115 | - FORCE_RET(); \ | |
89 | + FORCE_RET(); \ | |
116 | 90 | } |
117 | -DO_VFP_cmpe(s) | |
118 | -DO_VFP_cmpe(d) | |
119 | -#undef DO_VFP_cmpe | |
91 | +DO_VFP_cmp(s, 32) | |
92 | +DO_VFP_cmp(d, 64) | |
93 | +#undef DO_VFP_cmp | |
120 | 94 | |
121 | 95 | /* Convert host exception flags to vfp form. */ |
122 | -int vfp_exceptbits_from_host(int host_bits) | |
96 | +static inline int vfp_exceptbits_from_host(int host_bits) | |
123 | 97 | { |
124 | 98 | int target_bits = 0; |
125 | 99 | |
126 | -#ifdef FE_INVALID | |
127 | - if (host_bits & FE_INVALID) | |
100 | + if (host_bits & float_flag_invalid) | |
128 | 101 | target_bits |= 1; |
129 | -#endif | |
130 | -#ifdef FE_DIVBYZERO | |
131 | - if (host_bits & FE_DIVBYZERO) | |
102 | + if (host_bits & float_flag_divbyzero) | |
132 | 103 | target_bits |= 2; |
133 | -#endif | |
134 | -#ifdef FE_OVERFLOW | |
135 | - if (host_bits & FE_OVERFLOW) | |
104 | + if (host_bits & float_flag_overflow) | |
136 | 105 | target_bits |= 4; |
137 | -#endif | |
138 | -#ifdef FE_UNDERFLOW | |
139 | - if (host_bits & FE_UNDERFLOW) | |
106 | + if (host_bits & float_flag_underflow) | |
140 | 107 | target_bits |= 8; |
141 | -#endif | |
142 | -#ifdef FE_INEXACT | |
143 | - if (host_bits & FE_INEXACT) | |
108 | + if (host_bits & float_flag_inexact) | |
144 | 109 | target_bits |= 0x10; |
145 | -#endif | |
146 | - /* C doesn't define an inexact exception. */ | |
147 | 110 | return target_bits; |
148 | 111 | } |
149 | 112 | |
150 | 113 | /* Convert vfp exception flags to target form. */ |
151 | -int vfp_host_exceptbits_to_host(int target_bits) | |
114 | +static inline int vfp_exceptbits_to_host(int target_bits) | |
152 | 115 | { |
153 | 116 | int host_bits = 0; |
154 | 117 | |
155 | -#ifdef FE_INVALID | |
156 | 118 | if (target_bits & 1) |
157 | - host_bits |= FE_INVALID; | |
158 | -#endif | |
159 | -#ifdef FE_DIVBYZERO | |
119 | + host_bits |= float_flag_invalid; | |
160 | 120 | if (target_bits & 2) |
161 | - host_bits |= FE_DIVBYZERO; | |
162 | -#endif | |
163 | -#ifdef FE_OVERFLOW | |
121 | + host_bits |= float_flag_divbyzero; | |
164 | 122 | if (target_bits & 4) |
165 | - host_bits |= FE_OVERFLOW; | |
166 | -#endif | |
167 | -#ifdef FE_UNDERFLOW | |
123 | + host_bits |= float_flag_overflow; | |
168 | 124 | if (target_bits & 8) |
169 | - host_bits |= FE_UNDERFLOW; | |
170 | -#endif | |
171 | -#ifdef FE_INEXACT | |
125 | + host_bits |= float_flag_underflow; | |
172 | 126 | if (target_bits & 0x10) |
173 | - host_bits |= FE_INEXACT; | |
174 | -#endif | |
127 | + host_bits |= float_flag_inexact; | |
175 | 128 | return host_bits; |
176 | 129 | } |
177 | 130 | |
... | ... | @@ -190,31 +143,23 @@ void do_vfp_set_fpscr(void) |
190 | 143 | i = (T0 >> 22) & 3; |
191 | 144 | switch (i) { |
192 | 145 | case 0: |
193 | - i = FE_TONEAREST; | |
146 | + i = float_round_nearest_even; | |
194 | 147 | break; |
195 | 148 | case 1: |
196 | - i = FE_UPWARD; | |
149 | + i = float_round_up; | |
197 | 150 | break; |
198 | 151 | case 2: |
199 | - i = FE_DOWNWARD; | |
152 | + i = float_round_down; | |
200 | 153 | break; |
201 | 154 | case 3: |
202 | - i = FE_TOWARDZERO; | |
155 | + i = float_round_to_zero; | |
203 | 156 | break; |
204 | 157 | } |
205 | - fesetround (i); | |
158 | + set_float_rounding_mode(i, &env->vfp.fp_status); | |
206 | 159 | } |
207 | 160 | |
208 | - /* Clear host exception flags. */ | |
209 | - feclearexcept(FE_ALL_EXCEPT); | |
210 | - | |
211 | -#ifdef feenableexcept | |
212 | - if (changed & 0x1f00) { | |
213 | - i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f); | |
214 | - feenableexcept (i); | |
215 | - fedisableexcept (FE_ALL_EXCEPT & ~i); | |
216 | - } | |
217 | -#endif | |
161 | + i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f); | |
162 | + set_float_exception_flags(i, &env->vfp.fp_status); | |
218 | 163 | /* XXX: FZ and DN are not implemented. */ |
219 | 164 | } |
220 | 165 | |
... | ... | @@ -224,6 +169,6 @@ void do_vfp_get_fpscr(void) |
224 | 169 | |
225 | 170 | T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16) |
226 | 171 | | (env->vfp.vec_stride << 20); |
227 | - i = fetestexcept(FE_ALL_EXCEPT); | |
172 | + i = get_float_exception_flags(&env->vfp.fp_status); | |
228 | 173 | T0 |= vfp_exceptbits_from_host(i); |
229 | 174 | } | ... | ... |