xref: /qemu/target/openrisc/fpu_helper.c (revision 24f91e81b65fcdd0552d1f0fcb0ea7cfe3829c19)
15b569507SJia Liu /*
25b569507SJia Liu  * OpenRISC float helper routines
35b569507SJia Liu  *
45b569507SJia Liu  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
55b569507SJia Liu  *                         Feng Gao <gf91597@gmail.com>
65b569507SJia Liu  *
75b569507SJia Liu  * This library is free software; you can redistribute it and/or
85b569507SJia Liu  * modify it under the terms of the GNU Lesser General Public
95b569507SJia Liu  * License as published by the Free Software Foundation; either
105b569507SJia Liu  * version 2 of the License, or (at your option) any later version.
115b569507SJia Liu  *
125b569507SJia Liu  * This library is distributed in the hope that it will be useful,
135b569507SJia Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
145b569507SJia Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
155b569507SJia Liu  * Lesser General Public License for more details.
165b569507SJia Liu  *
175b569507SJia Liu  * You should have received a copy of the GNU Lesser General Public
185b569507SJia Liu  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
195b569507SJia Liu  */
205b569507SJia Liu 
21ed2decc6SPeter Maydell #include "qemu/osdep.h"
225b569507SJia Liu #include "cpu.h"
232ef6175aSRichard Henderson #include "exec/helper-proto.h"
245b569507SJia Liu #include "exception.h"
25*24f91e81SAlex Bennée #include "fpu/softfloat.h"
265b569507SJia Liu 
275b569507SJia Liu static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp)
285b569507SJia Liu {
295b569507SJia Liu     int ret = 0;
305b569507SJia Liu     if (fexcp) {
315b569507SJia Liu         if (fexcp & float_flag_invalid) {
325b569507SJia Liu             cpu->env.fpcsr |= FPCSR_IVF;
335b569507SJia Liu             ret = 1;
345b569507SJia Liu         }
355b569507SJia Liu         if (fexcp & float_flag_overflow) {
365b569507SJia Liu             cpu->env.fpcsr |= FPCSR_OVF;
375b569507SJia Liu             ret = 1;
385b569507SJia Liu         }
395b569507SJia Liu         if (fexcp & float_flag_underflow) {
405b569507SJia Liu             cpu->env.fpcsr |= FPCSR_UNF;
415b569507SJia Liu             ret = 1;
425b569507SJia Liu         }
435b569507SJia Liu         if (fexcp & float_flag_divbyzero) {
445b569507SJia Liu             cpu->env.fpcsr |= FPCSR_DZF;
455b569507SJia Liu             ret = 1;
465b569507SJia Liu         }
475b569507SJia Liu         if (fexcp & float_flag_inexact) {
485b569507SJia Liu             cpu->env.fpcsr |= FPCSR_IXF;
495b569507SJia Liu             ret = 1;
505b569507SJia Liu         }
515b569507SJia Liu     }
525b569507SJia Liu 
535b569507SJia Liu     return ret;
545b569507SJia Liu }
555b569507SJia Liu 
565b569507SJia Liu static inline void update_fpcsr(OpenRISCCPU *cpu)
575b569507SJia Liu {
585b569507SJia Liu     int tmp = ieee_ex_to_openrisc(cpu,
595b569507SJia Liu                               get_float_exception_flags(&cpu->env.fp_status));
605b569507SJia Liu 
615b569507SJia Liu     SET_FP_CAUSE(cpu->env.fpcsr, tmp);
625b569507SJia Liu     if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
635b569507SJia Liu         (cpu->env.fpcsr & FPCSR_FPEE)) {
645b569507SJia Liu         helper_exception(&cpu->env, EXCP_FPE);
655b569507SJia Liu     } else {
665b569507SJia Liu         UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
675b569507SJia Liu     }
685b569507SJia Liu }
695b569507SJia Liu 
705b569507SJia Liu uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
715b569507SJia Liu {
725b569507SJia Liu     uint64_t itofd;
73dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
745b569507SJia Liu 
755b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
765b569507SJia Liu     itofd = int32_to_float64(val, &cpu->env.fp_status);
775b569507SJia Liu     update_fpcsr(cpu);
785b569507SJia Liu 
795b569507SJia Liu     return itofd;
805b569507SJia Liu }
815b569507SJia Liu 
825b569507SJia Liu uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
835b569507SJia Liu {
845b569507SJia Liu     uint32_t itofs;
85dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
865b569507SJia Liu 
875b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
885b569507SJia Liu     itofs = int32_to_float32(val, &cpu->env.fp_status);
895b569507SJia Liu     update_fpcsr(cpu);
905b569507SJia Liu 
915b569507SJia Liu     return itofs;
925b569507SJia Liu }
935b569507SJia Liu 
945b569507SJia Liu uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
955b569507SJia Liu {
965b569507SJia Liu     uint64_t ftoid;
97dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
985b569507SJia Liu 
995b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
1005b569507SJia Liu     ftoid = float32_to_int64(val, &cpu->env.fp_status);
1015b569507SJia Liu     update_fpcsr(cpu);
1025b569507SJia Liu 
1035b569507SJia Liu     return ftoid;
1045b569507SJia Liu }
1055b569507SJia Liu 
1065b569507SJia Liu uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
1075b569507SJia Liu {
1085b569507SJia Liu     uint32_t ftois;
109dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
1105b569507SJia Liu 
1115b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
1125b569507SJia Liu     ftois = float32_to_int32(val, &cpu->env.fp_status);
1135b569507SJia Liu     update_fpcsr(cpu);
1145b569507SJia Liu 
1155b569507SJia Liu     return ftois;
1165b569507SJia Liu }
1175b569507SJia Liu 
1185b569507SJia Liu #define FLOAT_OP(name, p) void helper_float_##_##p(void)
1195b569507SJia Liu 
1205b569507SJia Liu #define FLOAT_CALC(name)                                                  \
1215b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
1225b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
1235b569507SJia Liu {                                                                         \
1245b569507SJia Liu     uint64_t result;                                                      \
125dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1265b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1275b569507SJia Liu     result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
1285b569507SJia Liu     update_fpcsr(cpu);                                                    \
1295b569507SJia Liu     return result;                                                        \
1305b569507SJia Liu }                                                                         \
1315b569507SJia Liu                                                                           \
1325b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
1335b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
1345b569507SJia Liu {                                                                         \
1355b569507SJia Liu     uint32_t result;                                                      \
136dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1375b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1385b569507SJia Liu     result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
1395b569507SJia Liu     update_fpcsr(cpu);                                                    \
1405b569507SJia Liu     return result;                                                        \
1415b569507SJia Liu }                                                                         \
1425b569507SJia Liu 
1435b569507SJia Liu FLOAT_CALC(add)
1445b569507SJia Liu FLOAT_CALC(sub)
1455b569507SJia Liu FLOAT_CALC(mul)
1465b569507SJia Liu FLOAT_CALC(div)
1475b569507SJia Liu FLOAT_CALC(rem)
1485b569507SJia Liu #undef FLOAT_CALC
1495b569507SJia Liu 
150762e22edSRichard Henderson 
151762e22edSRichard Henderson uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a,
152762e22edSRichard Henderson                              uint64_t b, uint64_t c)
153762e22edSRichard Henderson {
154762e22edSRichard Henderson     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
155762e22edSRichard Henderson     uint64_t result;
156762e22edSRichard Henderson     set_float_exception_flags(0, &cpu->env.fp_status);
157762e22edSRichard Henderson     /* Note that or1ksim doesn't use merged operation.  */
158762e22edSRichard Henderson     result = float64_mul(b, c, &cpu->env.fp_status);
159762e22edSRichard Henderson     result = float64_add(result, a, &cpu->env.fp_status);
160762e22edSRichard Henderson     update_fpcsr(cpu);
161762e22edSRichard Henderson     return result;
1625b569507SJia Liu }
1635b569507SJia Liu 
164762e22edSRichard Henderson uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a,
165762e22edSRichard Henderson                              uint32_t b, uint32_t c)
166762e22edSRichard Henderson {
167762e22edSRichard Henderson     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
168762e22edSRichard Henderson     uint32_t result;
169762e22edSRichard Henderson     set_float_exception_flags(0, &cpu->env.fp_status);
170762e22edSRichard Henderson     /* Note that or1ksim doesn't use merged operation.  */
171762e22edSRichard Henderson     result = float32_mul(b, c, &cpu->env.fp_status);
172762e22edSRichard Henderson     result = float32_add(result, a, &cpu->env.fp_status);
173762e22edSRichard Henderson     update_fpcsr(cpu);
174762e22edSRichard Henderson     return result;
175762e22edSRichard Henderson }
1765b569507SJia Liu 
1775b569507SJia Liu 
1785b569507SJia Liu #define FLOAT_CMP(name)                                                   \
1795b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
1805b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
1815b569507SJia Liu {                                                                         \
1825b569507SJia Liu     int res;                                                              \
183dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1845b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1855b569507SJia Liu     res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
1865b569507SJia Liu     update_fpcsr(cpu);                                                    \
1875b569507SJia Liu     return res;                                                           \
1885b569507SJia Liu }                                                                         \
1895b569507SJia Liu                                                                           \
1905b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
1915b569507SJia Liu                                              uint32_t fdt0, uint32_t fdt1)\
1925b569507SJia Liu {                                                                         \
1935b569507SJia Liu     int res;                                                              \
194dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1955b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1965b569507SJia Liu     res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
1975b569507SJia Liu     update_fpcsr(cpu);                                                    \
1985b569507SJia Liu     return res;                                                           \
1995b569507SJia Liu }
2005b569507SJia Liu 
2015b569507SJia Liu FLOAT_CMP(le)
2025b569507SJia Liu FLOAT_CMP(eq)
2035b569507SJia Liu FLOAT_CMP(lt)
2045b569507SJia Liu #undef FLOAT_CMP
2055b569507SJia Liu 
2065b569507SJia Liu 
2075b569507SJia Liu #define FLOAT_CMPNE(name)                                                 \
2085b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
2095b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
2105b569507SJia Liu {                                                                         \
2115b569507SJia Liu     int res;                                                              \
212dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2135b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2145b569507SJia Liu     res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
2155b569507SJia Liu     update_fpcsr(cpu);                                                    \
2165b569507SJia Liu     return res;                                                           \
2175b569507SJia Liu }                                                                         \
2185b569507SJia Liu                                                                           \
2195b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
2205b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
2215b569507SJia Liu {                                                                         \
2225b569507SJia Liu     int res;                                                              \
223dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2245b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2255b569507SJia Liu     res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
2265b569507SJia Liu     update_fpcsr(cpu);                                                    \
2275b569507SJia Liu     return res;                                                           \
2285b569507SJia Liu }
2295b569507SJia Liu 
2305b569507SJia Liu FLOAT_CMPNE(ne)
2315b569507SJia Liu #undef FLOAT_CMPNE
2325b569507SJia Liu 
2335b569507SJia Liu #define FLOAT_CMPGT(name)                                                 \
2345b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
2355b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
2365b569507SJia Liu {                                                                         \
2375b569507SJia Liu     int res;                                                              \
238dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2395b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2405b569507SJia Liu     res = !float64_le(fdt0, fdt1, &cpu->env.fp_status);                   \
2415b569507SJia Liu     update_fpcsr(cpu);                                                    \
2425b569507SJia Liu     return res;                                                           \
2435b569507SJia Liu }                                                                         \
2445b569507SJia Liu                                                                           \
2455b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
2465b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
2475b569507SJia Liu {                                                                         \
2485b569507SJia Liu     int res;                                                              \
249dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2505b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2515b569507SJia Liu     res = !float32_le(fdt0, fdt1, &cpu->env.fp_status);                   \
2525b569507SJia Liu     update_fpcsr(cpu);                                                    \
2535b569507SJia Liu     return res;                                                           \
2545b569507SJia Liu }
2555b569507SJia Liu FLOAT_CMPGT(gt)
2565b569507SJia Liu #undef FLOAT_CMPGT
2575b569507SJia Liu 
2585b569507SJia Liu #define FLOAT_CMPGE(name)                                                 \
2595b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
2605b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
2615b569507SJia Liu {                                                                         \
2625b569507SJia Liu     int res;                                                              \
263dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2645b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2655b569507SJia Liu     res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
2665b569507SJia Liu     update_fpcsr(cpu);                                                    \
2675b569507SJia Liu     return res;                                                           \
2685b569507SJia Liu }                                                                         \
2695b569507SJia Liu                                                                           \
2705b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
2715b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
2725b569507SJia Liu {                                                                         \
2735b569507SJia Liu     int res;                                                              \
274dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2755b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2765b569507SJia Liu     res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
2775b569507SJia Liu     update_fpcsr(cpu);                                                    \
2785b569507SJia Liu     return res;                                                           \
2795b569507SJia Liu }
2805b569507SJia Liu 
2815b569507SJia Liu FLOAT_CMPGE(ge)
2825b569507SJia Liu #undef FLOAT_CMPGE
283