xref: /openbmc/qemu/target/openrisc/fpu_helper.c (revision 1a7c00bb)
1 /*
2  * OpenRISC float helper routines
3  *
4  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5  *                         Feng Gao <gf91597@gmail.com>
6  *
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.
11  *
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  * Lesser General Public License for more details.
16  *
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/>.
19  */
20 
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "exec/helper-proto.h"
24 #include "exception.h"
25 #include "fpu/softfloat.h"
26 
27 static int ieee_ex_to_openrisc(int fexcp)
28 {
29     int ret = 0;
30     if (fexcp & float_flag_invalid) {
31         ret |= FPCSR_IVF;
32     }
33     if (fexcp & float_flag_overflow) {
34         ret |= FPCSR_OVF;
35     }
36     if (fexcp & float_flag_underflow) {
37         ret |= FPCSR_UNF;
38     }
39     if (fexcp & float_flag_divbyzero) {
40         ret |= FPCSR_DZF;
41     }
42     if (fexcp & float_flag_inexact) {
43         ret |= FPCSR_IXF;
44     }
45     return ret;
46 }
47 
48 void HELPER(update_fpcsr)(CPUOpenRISCState *env)
49 {
50     int tmp = get_float_exception_flags(&env->fp_status);
51 
52     if (tmp) {
53         set_float_exception_flags(0, &env->fp_status);
54         tmp = ieee_ex_to_openrisc(tmp);
55         if (tmp) {
56             env->fpcsr |= tmp;
57             if (env->fpcsr & FPCSR_FPEE) {
58                 helper_exception(env, EXCP_FPE);
59             }
60         }
61     }
62 }
63 
64 uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
65 {
66     return int32_to_float64(val, &env->fp_status);
67 }
68 
69 uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
70 {
71     return int32_to_float32(val, &env->fp_status);
72 }
73 
74 uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
75 {
76     return float32_to_int64(val, &env->fp_status);
77 }
78 
79 uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
80 {
81     return float32_to_int32(val, &env->fp_status);
82 }
83 
84 #define FLOAT_CALC(name)                                                  \
85 uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
86                                      uint64_t fdt0, uint64_t fdt1)        \
87 { return float64_ ## name(fdt0, fdt1, &env->fp_status); }                 \
88 uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
89                                      uint32_t fdt0, uint32_t fdt1)        \
90 { return float32_ ## name(fdt0, fdt1, &env->fp_status); }
91 
92 FLOAT_CALC(add)
93 FLOAT_CALC(sub)
94 FLOAT_CALC(mul)
95 FLOAT_CALC(div)
96 FLOAT_CALC(rem)
97 #undef FLOAT_CALC
98 
99 
100 uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a,
101                              uint64_t b, uint64_t c)
102 {
103     /* Note that or1ksim doesn't use fused operation.  */
104     b = float64_mul(b, c, &env->fp_status);
105     return float64_add(a, b, &env->fp_status);
106 }
107 
108 uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a,
109                              uint32_t b, uint32_t c)
110 {
111     /* Note that or1ksim doesn't use fused operation.  */
112     b = float32_mul(b, c, &env->fp_status);
113     return float32_add(a, b, &env->fp_status);
114 }
115 
116 
117 #define FLOAT_CMP(name, impl)                                             \
118 target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env,           \
119                                          uint64_t fdt0, uint64_t fdt1)    \
120 { return float64_ ## impl(fdt0, fdt1, &env->fp_status); }                 \
121 target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env,           \
122                                          uint32_t fdt0, uint32_t fdt1)    \
123 { return float32_ ## impl(fdt0, fdt1, &env->fp_status); }
124 
125 FLOAT_CMP(le, le)
126 FLOAT_CMP(lt, lt)
127 FLOAT_CMP(eq, eq_quiet)
128 #undef FLOAT_CMP
129