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 10198a2d21SThomas Huth * version 2.1 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" 23*9156ca76SStafford Horne #include "exec/exec-all.h" 242ef6175aSRichard Henderson #include "exec/helper-proto.h" 2524f91e81SAlex Bennée #include "fpu/softfloat.h" 265b569507SJia Liu 274e2d3007SRichard Henderson static int ieee_ex_to_openrisc(int fexcp) 285b569507SJia Liu { 295b569507SJia Liu int ret = 0; 305b569507SJia Liu if (fexcp & float_flag_invalid) { 314e2d3007SRichard Henderson ret |= FPCSR_IVF; 325b569507SJia Liu } 335b569507SJia Liu if (fexcp & float_flag_overflow) { 344e2d3007SRichard Henderson ret |= FPCSR_OVF; 355b569507SJia Liu } 365b569507SJia Liu if (fexcp & float_flag_underflow) { 374e2d3007SRichard Henderson ret |= FPCSR_UNF; 385b569507SJia Liu } 395b569507SJia Liu if (fexcp & float_flag_divbyzero) { 404e2d3007SRichard Henderson ret |= FPCSR_DZF; 415b569507SJia Liu } 425b569507SJia Liu if (fexcp & float_flag_inexact) { 434e2d3007SRichard Henderson ret |= FPCSR_IXF; 445b569507SJia Liu } 455b569507SJia Liu return ret; 465b569507SJia Liu } 475b569507SJia Liu 48*9156ca76SStafford Horne static G_NORETURN 49*9156ca76SStafford Horne void do_fpe(CPUOpenRISCState *env, uintptr_t pc) 50*9156ca76SStafford Horne { 51*9156ca76SStafford Horne CPUState *cs = env_cpu(env); 52*9156ca76SStafford Horne 53*9156ca76SStafford Horne cs->exception_index = EXCP_FPE; 54*9156ca76SStafford Horne cpu_loop_exit_restore(cs, pc); 55*9156ca76SStafford Horne } 56*9156ca76SStafford Horne 574e2d3007SRichard Henderson void HELPER(update_fpcsr)(CPUOpenRISCState *env) 585b569507SJia Liu { 594e2d3007SRichard Henderson int tmp = get_float_exception_flags(&env->fp_status); 605b569507SJia Liu 614e2d3007SRichard Henderson if (tmp) { 624e2d3007SRichard Henderson set_float_exception_flags(0, &env->fp_status); 634e2d3007SRichard Henderson tmp = ieee_ex_to_openrisc(tmp); 644e2d3007SRichard Henderson if (tmp) { 654e2d3007SRichard Henderson env->fpcsr |= tmp; 664e2d3007SRichard Henderson if (env->fpcsr & FPCSR_FPEE) { 67*9156ca76SStafford Horne do_fpe(env, GETPC()); 684e2d3007SRichard Henderson } 694e2d3007SRichard Henderson } 705b569507SJia Liu } 715b569507SJia Liu } 725b569507SJia Liu 73a465772eSRichard Henderson void cpu_set_fpcsr(CPUOpenRISCState *env, uint32_t val) 74a465772eSRichard Henderson { 75a465772eSRichard Henderson static const int rm_to_sf[] = { 76a465772eSRichard Henderson float_round_nearest_even, 77a465772eSRichard Henderson float_round_to_zero, 78a465772eSRichard Henderson float_round_up, 79a465772eSRichard Henderson float_round_down 80a465772eSRichard Henderson }; 81a465772eSRichard Henderson 8297a254b3SStafford Horne env->fpcsr = val & 0xfff; 83a465772eSRichard Henderson set_float_rounding_mode(rm_to_sf[extract32(val, 1, 2)], &env->fp_status); 84a465772eSRichard Henderson } 85a465772eSRichard Henderson 865b569507SJia Liu uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val) 875b569507SJia Liu { 8862f2b038SRichard Henderson return int64_to_float64(val, &env->fp_status); 895b569507SJia Liu } 905b569507SJia Liu 915b569507SJia Liu uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val) 925b569507SJia Liu { 934e2d3007SRichard Henderson return int32_to_float32(val, &env->fp_status); 945b569507SJia Liu } 955b569507SJia Liu 965b569507SJia Liu uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val) 975b569507SJia Liu { 9862f2b038SRichard Henderson return float64_to_int64_round_to_zero(val, &env->fp_status); 995b569507SJia Liu } 1005b569507SJia Liu 1015b569507SJia Liu uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val) 1025b569507SJia Liu { 103091a3516SRichard Henderson return float32_to_int32_round_to_zero(val, &env->fp_status); 1045b569507SJia Liu } 1055b569507SJia Liu 10662f2b038SRichard Henderson uint64_t HELPER(stod)(CPUOpenRISCState *env, uint32_t val) 10762f2b038SRichard Henderson { 10862f2b038SRichard Henderson return float32_to_float64(val, &env->fp_status); 10962f2b038SRichard Henderson } 11062f2b038SRichard Henderson 11162f2b038SRichard Henderson uint32_t HELPER(dtos)(CPUOpenRISCState *env, uint64_t val) 11262f2b038SRichard Henderson { 11362f2b038SRichard Henderson return float64_to_float32(val, &env->fp_status); 11462f2b038SRichard Henderson } 11562f2b038SRichard Henderson 1165b569507SJia Liu #define FLOAT_CALC(name) \ 1175b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 1185b569507SJia Liu uint64_t fdt0, uint64_t fdt1) \ 1194e2d3007SRichard Henderson { return float64_ ## name(fdt0, fdt1, &env->fp_status); } \ 1205b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 1215b569507SJia Liu uint32_t fdt0, uint32_t fdt1) \ 1224e2d3007SRichard Henderson { return float32_ ## name(fdt0, fdt1, &env->fp_status); } 1235b569507SJia Liu 1245b569507SJia Liu FLOAT_CALC(add) 1255b569507SJia Liu FLOAT_CALC(sub) 1265b569507SJia Liu FLOAT_CALC(mul) 1275b569507SJia Liu FLOAT_CALC(div) 1285b569507SJia Liu FLOAT_CALC(rem) 1295b569507SJia Liu #undef FLOAT_CALC 1305b569507SJia Liu 131762e22edSRichard Henderson 132762e22edSRichard Henderson uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a, 133762e22edSRichard Henderson uint64_t b, uint64_t c) 134762e22edSRichard Henderson { 1354e2d3007SRichard Henderson /* Note that or1ksim doesn't use fused operation. */ 1364e2d3007SRichard Henderson b = float64_mul(b, c, &env->fp_status); 1374e2d3007SRichard Henderson return float64_add(a, b, &env->fp_status); 1385b569507SJia Liu } 1395b569507SJia Liu 140762e22edSRichard Henderson uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a, 141762e22edSRichard Henderson uint32_t b, uint32_t c) 142762e22edSRichard Henderson { 1434e2d3007SRichard Henderson /* Note that or1ksim doesn't use fused operation. */ 1444e2d3007SRichard Henderson b = float32_mul(b, c, &env->fp_status); 1454e2d3007SRichard Henderson return float32_add(a, b, &env->fp_status); 146762e22edSRichard Henderson } 1475b569507SJia Liu 1485b569507SJia Liu 1494e2d3007SRichard Henderson #define FLOAT_CMP(name, impl) \ 1504e2d3007SRichard Henderson target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 1515b569507SJia Liu uint64_t fdt0, uint64_t fdt1) \ 1524e2d3007SRichard Henderson { return float64_ ## impl(fdt0, fdt1, &env->fp_status); } \ 1534e2d3007SRichard Henderson target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 1545b569507SJia Liu uint32_t fdt0, uint32_t fdt1) \ 1554e2d3007SRichard Henderson { return float32_ ## impl(fdt0, fdt1, &env->fp_status); } 1565b569507SJia Liu 1574e2d3007SRichard Henderson FLOAT_CMP(le, le) 1584e2d3007SRichard Henderson FLOAT_CMP(lt, lt) 1594e2d3007SRichard Henderson FLOAT_CMP(eq, eq_quiet) 1602b13b4b9SRichard Henderson FLOAT_CMP(un, unordered_quiet) 1615b569507SJia Liu #undef FLOAT_CMP 1622b13b4b9SRichard Henderson 1632b13b4b9SRichard Henderson #define FLOAT_UCMP(name, expr) \ 1642b13b4b9SRichard Henderson target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 1652b13b4b9SRichard Henderson uint64_t fdt0, uint64_t fdt1) \ 1662b13b4b9SRichard Henderson { \ 16771bfd65cSRichard Henderson FloatRelation r = float64_compare_quiet(fdt0, fdt1, &env->fp_status); \ 1682b13b4b9SRichard Henderson return expr; \ 1692b13b4b9SRichard Henderson } \ 1702b13b4b9SRichard Henderson target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 1712b13b4b9SRichard Henderson uint32_t fdt0, uint32_t fdt1) \ 1722b13b4b9SRichard Henderson { \ 17371bfd65cSRichard Henderson FloatRelation r = float32_compare_quiet(fdt0, fdt1, &env->fp_status); \ 1742b13b4b9SRichard Henderson return expr; \ 1752b13b4b9SRichard Henderson } 1762b13b4b9SRichard Henderson 1772b13b4b9SRichard Henderson FLOAT_UCMP(ueq, r == float_relation_equal || r == float_relation_unordered) 1782b13b4b9SRichard Henderson FLOAT_UCMP(ult, r == float_relation_less || r == float_relation_unordered) 1792b13b4b9SRichard Henderson FLOAT_UCMP(ule, r != float_relation_greater) 1802b13b4b9SRichard Henderson #undef FLOAT_UCMP 181