4 * Copyright (c) 2006-2007 CodeSourcery
5 * Written by Paul Brook
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include "exec/helper-proto.h"
24 #include "exec/exec-all.h"
26 int32_t HELPER(reds32)(CPUM68KState *env, FPReg *val)
28 return floatx80_to_int32(val->d, &env->fp_status);
31 float32 HELPER(redf32)(CPUM68KState *env, FPReg *val)
33 return floatx80_to_float32(val->d, &env->fp_status);
36 void HELPER(exts32)(CPUM68KState *env, FPReg *res, int32_t val)
38 res->d = int32_to_floatx80(val, &env->fp_status);
41 void HELPER(extf32)(CPUM68KState *env, FPReg *res, float32 val)
43 res->d = float32_to_floatx80(val, &env->fp_status);
46 void HELPER(extf64)(CPUM68KState *env, FPReg *res, float64 val)
48 res->d = float64_to_floatx80(val, &env->fp_status);
51 float64 HELPER(redf64)(CPUM68KState *env, FPReg *val)
53 return floatx80_to_float64(val->d, &env->fp_status);
56 void HELPER(firound)(CPUM68KState *env, FPReg *res, FPReg *val)
58 res->d = floatx80_round_to_int(val->d, &env->fp_status);
61 static void m68k_restore_precision_mode(CPUM68KState *env)
63 switch (env->fpcr & FPCR_PREC_MASK) {
64 case FPCR_PREC_X: /* extended */
65 set_floatx80_rounding_precision(80, &env->fp_status);
67 case FPCR_PREC_S: /* single */
68 set_floatx80_rounding_precision(32, &env->fp_status);
70 case FPCR_PREC_D: /* double */
71 set_floatx80_rounding_precision(64, &env->fp_status);
73 case FPCR_PREC_U: /* undefined */
79 static void cf_restore_precision_mode(CPUM68KState *env)
81 if (env->fpcr & FPCR_PREC_S) { /* single */
82 set_floatx80_rounding_precision(32, &env->fp_status);
84 set_floatx80_rounding_precision(64, &env->fp_status);
88 static void restore_rounding_mode(CPUM68KState *env)
90 switch (env->fpcr & FPCR_RND_MASK) {
91 case FPCR_RND_N: /* round to nearest */
92 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
94 case FPCR_RND_Z: /* round to zero */
95 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
97 case FPCR_RND_M: /* round toward minus infinity */
98 set_float_rounding_mode(float_round_down, &env->fp_status);
100 case FPCR_RND_P: /* round toward positive infinity */
101 set_float_rounding_mode(float_round_up, &env->fp_status);
106 void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val)
108 env->fpcr = val & 0xffff;
110 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
111 cf_restore_precision_mode(env);
113 m68k_restore_precision_mode(env);
115 restore_rounding_mode(env);
118 void HELPER(fitrunc)(CPUM68KState *env, FPReg *res, FPReg *val)
120 int rounding_mode = get_float_rounding_mode(&env->fp_status);
121 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
122 res->d = floatx80_round_to_int(val->d, &env->fp_status);
123 set_float_rounding_mode(rounding_mode, &env->fp_status);
126 void HELPER(set_fpcr)(CPUM68KState *env, uint32_t val)
128 cpu_m68k_set_fpcr(env, val);
131 void HELPER(fsqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
133 res->d = floatx80_sqrt(val->d, &env->fp_status);
136 void HELPER(fabs)(CPUM68KState *env, FPReg *res, FPReg *val)
138 res->d = floatx80_abs(val->d);
141 void HELPER(fchs)(CPUM68KState *env, FPReg *res, FPReg *val)
143 res->d = floatx80_chs(val->d);
146 void HELPER(fadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
148 res->d = floatx80_add(val0->d, val1->d, &env->fp_status);
151 void HELPER(fsub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
153 res->d = floatx80_sub(val1->d, val0->d, &env->fp_status);
156 void HELPER(fmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
158 res->d = floatx80_mul(val0->d, val1->d, &env->fp_status);
161 void HELPER(fdiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
163 res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
166 static int float_comp_to_cc(int float_compare)
168 switch (float_compare) {
169 case float_relation_equal:
171 case float_relation_less:
173 case float_relation_unordered:
175 case float_relation_greater:
178 g_assert_not_reached();
182 void HELPER(fcmp)(CPUM68KState *env, FPReg *val0, FPReg *val1)
186 float_compare = floatx80_compare(val1->d, val0->d, &env->fp_status);
187 env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | float_comp_to_cc(float_compare);
190 void HELPER(ftst)(CPUM68KState *env, FPReg *val)
194 if (floatx80_is_neg(val->d)) {
198 if (floatx80_is_any_nan(val->d)) {
200 } else if (floatx80_is_infinity(val->d)) {
202 } else if (floatx80_is_zero(val->d)) {
205 env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | cc;