xref: /qemu/target/openrisc/fpu_helper.c (revision 762e22edcd021035e1dbcf0dbc31b4794c5c1027)
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"
255b569507SJia Liu 
265b569507SJia Liu static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp)
275b569507SJia Liu {
285b569507SJia Liu     int ret = 0;
295b569507SJia Liu     if (fexcp) {
305b569507SJia Liu         if (fexcp & float_flag_invalid) {
315b569507SJia Liu             cpu->env.fpcsr |= FPCSR_IVF;
325b569507SJia Liu             ret = 1;
335b569507SJia Liu         }
345b569507SJia Liu         if (fexcp & float_flag_overflow) {
355b569507SJia Liu             cpu->env.fpcsr |= FPCSR_OVF;
365b569507SJia Liu             ret = 1;
375b569507SJia Liu         }
385b569507SJia Liu         if (fexcp & float_flag_underflow) {
395b569507SJia Liu             cpu->env.fpcsr |= FPCSR_UNF;
405b569507SJia Liu             ret = 1;
415b569507SJia Liu         }
425b569507SJia Liu         if (fexcp & float_flag_divbyzero) {
435b569507SJia Liu             cpu->env.fpcsr |= FPCSR_DZF;
445b569507SJia Liu             ret = 1;
455b569507SJia Liu         }
465b569507SJia Liu         if (fexcp & float_flag_inexact) {
475b569507SJia Liu             cpu->env.fpcsr |= FPCSR_IXF;
485b569507SJia Liu             ret = 1;
495b569507SJia Liu         }
505b569507SJia Liu     }
515b569507SJia Liu 
525b569507SJia Liu     return ret;
535b569507SJia Liu }
545b569507SJia Liu 
555b569507SJia Liu static inline void update_fpcsr(OpenRISCCPU *cpu)
565b569507SJia Liu {
575b569507SJia Liu     int tmp = ieee_ex_to_openrisc(cpu,
585b569507SJia Liu                               get_float_exception_flags(&cpu->env.fp_status));
595b569507SJia Liu 
605b569507SJia Liu     SET_FP_CAUSE(cpu->env.fpcsr, tmp);
615b569507SJia Liu     if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
625b569507SJia Liu         (cpu->env.fpcsr & FPCSR_FPEE)) {
635b569507SJia Liu         helper_exception(&cpu->env, EXCP_FPE);
645b569507SJia Liu     } else {
655b569507SJia Liu         UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
665b569507SJia Liu     }
675b569507SJia Liu }
685b569507SJia Liu 
695b569507SJia Liu uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
705b569507SJia Liu {
715b569507SJia Liu     uint64_t itofd;
72dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
735b569507SJia Liu 
745b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
755b569507SJia Liu     itofd = int32_to_float64(val, &cpu->env.fp_status);
765b569507SJia Liu     update_fpcsr(cpu);
775b569507SJia Liu 
785b569507SJia Liu     return itofd;
795b569507SJia Liu }
805b569507SJia Liu 
815b569507SJia Liu uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
825b569507SJia Liu {
835b569507SJia Liu     uint32_t itofs;
84dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
855b569507SJia Liu 
865b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
875b569507SJia Liu     itofs = int32_to_float32(val, &cpu->env.fp_status);
885b569507SJia Liu     update_fpcsr(cpu);
895b569507SJia Liu 
905b569507SJia Liu     return itofs;
915b569507SJia Liu }
925b569507SJia Liu 
935b569507SJia Liu uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
945b569507SJia Liu {
955b569507SJia Liu     uint64_t ftoid;
96dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
975b569507SJia Liu 
985b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
995b569507SJia Liu     ftoid = float32_to_int64(val, &cpu->env.fp_status);
1005b569507SJia Liu     update_fpcsr(cpu);
1015b569507SJia Liu 
1025b569507SJia Liu     return ftoid;
1035b569507SJia Liu }
1045b569507SJia Liu 
1055b569507SJia Liu uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
1065b569507SJia Liu {
1075b569507SJia Liu     uint32_t ftois;
108dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
1095b569507SJia Liu 
1105b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);
1115b569507SJia Liu     ftois = float32_to_int32(val, &cpu->env.fp_status);
1125b569507SJia Liu     update_fpcsr(cpu);
1135b569507SJia Liu 
1145b569507SJia Liu     return ftois;
1155b569507SJia Liu }
1165b569507SJia Liu 
1175b569507SJia Liu #define FLOAT_OP(name, p) void helper_float_##_##p(void)
1185b569507SJia Liu 
1195b569507SJia Liu #define FLOAT_CALC(name)                                                  \
1205b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
1215b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
1225b569507SJia Liu {                                                                         \
1235b569507SJia Liu     uint64_t result;                                                      \
124dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1255b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1265b569507SJia Liu     result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
1275b569507SJia Liu     update_fpcsr(cpu);                                                    \
1285b569507SJia Liu     return result;                                                        \
1295b569507SJia Liu }                                                                         \
1305b569507SJia Liu                                                                           \
1315b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
1325b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
1335b569507SJia Liu {                                                                         \
1345b569507SJia Liu     uint32_t result;                                                      \
135dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1365b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1375b569507SJia Liu     result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
1385b569507SJia Liu     update_fpcsr(cpu);                                                    \
1395b569507SJia Liu     return result;                                                        \
1405b569507SJia Liu }                                                                         \
1415b569507SJia Liu 
1425b569507SJia Liu FLOAT_CALC(add)
1435b569507SJia Liu FLOAT_CALC(sub)
1445b569507SJia Liu FLOAT_CALC(mul)
1455b569507SJia Liu FLOAT_CALC(div)
1465b569507SJia Liu FLOAT_CALC(rem)
1475b569507SJia Liu #undef FLOAT_CALC
1485b569507SJia Liu 
149*762e22edSRichard Henderson 
150*762e22edSRichard Henderson uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a,
151*762e22edSRichard Henderson                              uint64_t b, uint64_t c)
152*762e22edSRichard Henderson {
153*762e22edSRichard Henderson     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
154*762e22edSRichard Henderson     uint64_t result;
155*762e22edSRichard Henderson     set_float_exception_flags(0, &cpu->env.fp_status);
156*762e22edSRichard Henderson     /* Note that or1ksim doesn't use merged operation.  */
157*762e22edSRichard Henderson     result = float64_mul(b, c, &cpu->env.fp_status);
158*762e22edSRichard Henderson     result = float64_add(result, a, &cpu->env.fp_status);
159*762e22edSRichard Henderson     update_fpcsr(cpu);
160*762e22edSRichard Henderson     return result;
1615b569507SJia Liu }
1625b569507SJia Liu 
163*762e22edSRichard Henderson uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a,
164*762e22edSRichard Henderson                              uint32_t b, uint32_t c)
165*762e22edSRichard Henderson {
166*762e22edSRichard Henderson     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
167*762e22edSRichard Henderson     uint32_t result;
168*762e22edSRichard Henderson     set_float_exception_flags(0, &cpu->env.fp_status);
169*762e22edSRichard Henderson     /* Note that or1ksim doesn't use merged operation.  */
170*762e22edSRichard Henderson     result = float32_mul(b, c, &cpu->env.fp_status);
171*762e22edSRichard Henderson     result = float32_add(result, a, &cpu->env.fp_status);
172*762e22edSRichard Henderson     update_fpcsr(cpu);
173*762e22edSRichard Henderson     return result;
174*762e22edSRichard Henderson }
1755b569507SJia Liu 
1765b569507SJia Liu 
1775b569507SJia Liu #define FLOAT_CMP(name)                                                   \
1785b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
1795b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
1805b569507SJia Liu {                                                                         \
1815b569507SJia Liu     int res;                                                              \
182dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1835b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1845b569507SJia Liu     res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
1855b569507SJia Liu     update_fpcsr(cpu);                                                    \
1865b569507SJia Liu     return res;                                                           \
1875b569507SJia Liu }                                                                         \
1885b569507SJia Liu                                                                           \
1895b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
1905b569507SJia Liu                                              uint32_t fdt0, uint32_t fdt1)\
1915b569507SJia Liu {                                                                         \
1925b569507SJia Liu     int res;                                                              \
193dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
1945b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
1955b569507SJia Liu     res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
1965b569507SJia Liu     update_fpcsr(cpu);                                                    \
1975b569507SJia Liu     return res;                                                           \
1985b569507SJia Liu }
1995b569507SJia Liu 
2005b569507SJia Liu FLOAT_CMP(le)
2015b569507SJia Liu FLOAT_CMP(eq)
2025b569507SJia Liu FLOAT_CMP(lt)
2035b569507SJia Liu #undef FLOAT_CMP
2045b569507SJia Liu 
2055b569507SJia Liu 
2065b569507SJia Liu #define FLOAT_CMPNE(name)                                                 \
2075b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
2085b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
2095b569507SJia Liu {                                                                         \
2105b569507SJia Liu     int res;                                                              \
211dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2125b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2135b569507SJia Liu     res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
2145b569507SJia Liu     update_fpcsr(cpu);                                                    \
2155b569507SJia Liu     return res;                                                           \
2165b569507SJia Liu }                                                                         \
2175b569507SJia Liu                                                                           \
2185b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
2195b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
2205b569507SJia Liu {                                                                         \
2215b569507SJia Liu     int res;                                                              \
222dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2235b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2245b569507SJia Liu     res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
2255b569507SJia Liu     update_fpcsr(cpu);                                                    \
2265b569507SJia Liu     return res;                                                           \
2275b569507SJia Liu }
2285b569507SJia Liu 
2295b569507SJia Liu FLOAT_CMPNE(ne)
2305b569507SJia Liu #undef FLOAT_CMPNE
2315b569507SJia Liu 
2325b569507SJia Liu #define FLOAT_CMPGT(name)                                                 \
2335b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
2345b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
2355b569507SJia Liu {                                                                         \
2365b569507SJia Liu     int res;                                                              \
237dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2385b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2395b569507SJia Liu     res = !float64_le(fdt0, fdt1, &cpu->env.fp_status);                   \
2405b569507SJia Liu     update_fpcsr(cpu);                                                    \
2415b569507SJia Liu     return res;                                                           \
2425b569507SJia Liu }                                                                         \
2435b569507SJia Liu                                                                           \
2445b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
2455b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
2465b569507SJia Liu {                                                                         \
2475b569507SJia Liu     int res;                                                              \
248dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2495b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2505b569507SJia Liu     res = !float32_le(fdt0, fdt1, &cpu->env.fp_status);                   \
2515b569507SJia Liu     update_fpcsr(cpu);                                                    \
2525b569507SJia Liu     return res;                                                           \
2535b569507SJia Liu }
2545b569507SJia Liu FLOAT_CMPGT(gt)
2555b569507SJia Liu #undef FLOAT_CMPGT
2565b569507SJia Liu 
2575b569507SJia Liu #define FLOAT_CMPGE(name)                                                 \
2585b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
2595b569507SJia Liu                                      uint64_t fdt0, uint64_t fdt1)        \
2605b569507SJia Liu {                                                                         \
2615b569507SJia Liu     int res;                                                              \
262dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2635b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2645b569507SJia Liu     res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
2655b569507SJia Liu     update_fpcsr(cpu);                                                    \
2665b569507SJia Liu     return res;                                                           \
2675b569507SJia Liu }                                                                         \
2685b569507SJia Liu                                                                           \
2695b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
2705b569507SJia Liu                                      uint32_t fdt0, uint32_t fdt1)        \
2715b569507SJia Liu {                                                                         \
2725b569507SJia Liu     int res;                                                              \
273dd51dc52SAndreas Färber     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
2745b569507SJia Liu     set_float_exception_flags(0, &cpu->env.fp_status);                    \
2755b569507SJia Liu     res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
2765b569507SJia Liu     update_fpcsr(cpu);                                                    \
2775b569507SJia Liu     return res;                                                           \
2785b569507SJia Liu }
2795b569507SJia Liu 
2805b569507SJia Liu FLOAT_CMPGE(ge)
2815b569507SJia Liu #undef FLOAT_CMPGE
282