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