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" 232ef6175aSRichard Henderson #include "exec/helper-proto.h" 245b569507SJia Liu #include "exception.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 484e2d3007SRichard Henderson void HELPER(update_fpcsr)(CPUOpenRISCState *env) 495b569507SJia Liu { 504e2d3007SRichard Henderson int tmp = get_float_exception_flags(&env->fp_status); 515b569507SJia Liu 524e2d3007SRichard Henderson if (tmp) { 534e2d3007SRichard Henderson set_float_exception_flags(0, &env->fp_status); 544e2d3007SRichard Henderson tmp = ieee_ex_to_openrisc(tmp); 554e2d3007SRichard Henderson if (tmp) { 564e2d3007SRichard Henderson env->fpcsr |= tmp; 574e2d3007SRichard Henderson if (env->fpcsr & FPCSR_FPEE) { 584e2d3007SRichard Henderson helper_exception(env, EXCP_FPE); 594e2d3007SRichard Henderson } 604e2d3007SRichard Henderson } 615b569507SJia Liu } 625b569507SJia Liu } 635b569507SJia Liu 64*a465772eSRichard Henderson void cpu_set_fpcsr(CPUOpenRISCState *env, uint32_t val) 65*a465772eSRichard Henderson { 66*a465772eSRichard Henderson static const int rm_to_sf[] = { 67*a465772eSRichard Henderson float_round_nearest_even, 68*a465772eSRichard Henderson float_round_to_zero, 69*a465772eSRichard Henderson float_round_up, 70*a465772eSRichard Henderson float_round_down 71*a465772eSRichard Henderson }; 72*a465772eSRichard Henderson 73*a465772eSRichard Henderson env->fpcsr = val & 0x7ff; 74*a465772eSRichard Henderson set_float_rounding_mode(rm_to_sf[extract32(val, 1, 2)], &env->fp_status); 75*a465772eSRichard Henderson } 76*a465772eSRichard Henderson 775b569507SJia Liu uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val) 785b569507SJia Liu { 7962f2b038SRichard Henderson return int64_to_float64(val, &env->fp_status); 805b569507SJia Liu } 815b569507SJia Liu 825b569507SJia Liu uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val) 835b569507SJia Liu { 844e2d3007SRichard Henderson return int32_to_float32(val, &env->fp_status); 855b569507SJia Liu } 865b569507SJia Liu 875b569507SJia Liu uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val) 885b569507SJia Liu { 8962f2b038SRichard Henderson return float64_to_int64_round_to_zero(val, &env->fp_status); 905b569507SJia Liu } 915b569507SJia Liu 925b569507SJia Liu uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val) 935b569507SJia Liu { 94091a3516SRichard Henderson return float32_to_int32_round_to_zero(val, &env->fp_status); 955b569507SJia Liu } 965b569507SJia Liu 9762f2b038SRichard Henderson uint64_t HELPER(stod)(CPUOpenRISCState *env, uint32_t val) 9862f2b038SRichard Henderson { 9962f2b038SRichard Henderson return float32_to_float64(val, &env->fp_status); 10062f2b038SRichard Henderson } 10162f2b038SRichard Henderson 10262f2b038SRichard Henderson uint32_t HELPER(dtos)(CPUOpenRISCState *env, uint64_t val) 10362f2b038SRichard Henderson { 10462f2b038SRichard Henderson return float64_to_float32(val, &env->fp_status); 10562f2b038SRichard Henderson } 10662f2b038SRichard Henderson 1075b569507SJia Liu #define FLOAT_CALC(name) \ 1085b569507SJia Liu uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 1095b569507SJia Liu uint64_t fdt0, uint64_t fdt1) \ 1104e2d3007SRichard Henderson { return float64_ ## name(fdt0, fdt1, &env->fp_status); } \ 1115b569507SJia Liu uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 1125b569507SJia Liu uint32_t fdt0, uint32_t fdt1) \ 1134e2d3007SRichard Henderson { return float32_ ## name(fdt0, fdt1, &env->fp_status); } 1145b569507SJia Liu 1155b569507SJia Liu FLOAT_CALC(add) 1165b569507SJia Liu FLOAT_CALC(sub) 1175b569507SJia Liu FLOAT_CALC(mul) 1185b569507SJia Liu FLOAT_CALC(div) 1195b569507SJia Liu FLOAT_CALC(rem) 1205b569507SJia Liu #undef FLOAT_CALC 1215b569507SJia Liu 122762e22edSRichard Henderson 123762e22edSRichard Henderson uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a, 124762e22edSRichard Henderson uint64_t b, uint64_t c) 125762e22edSRichard Henderson { 1264e2d3007SRichard Henderson /* Note that or1ksim doesn't use fused operation. */ 1274e2d3007SRichard Henderson b = float64_mul(b, c, &env->fp_status); 1284e2d3007SRichard Henderson return float64_add(a, b, &env->fp_status); 1295b569507SJia Liu } 1305b569507SJia Liu 131762e22edSRichard Henderson uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a, 132762e22edSRichard Henderson uint32_t b, uint32_t c) 133762e22edSRichard Henderson { 1344e2d3007SRichard Henderson /* Note that or1ksim doesn't use fused operation. */ 1354e2d3007SRichard Henderson b = float32_mul(b, c, &env->fp_status); 1364e2d3007SRichard Henderson return float32_add(a, b, &env->fp_status); 137762e22edSRichard Henderson } 1385b569507SJia Liu 1395b569507SJia Liu 1404e2d3007SRichard Henderson #define FLOAT_CMP(name, impl) \ 1414e2d3007SRichard Henderson target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 1425b569507SJia Liu uint64_t fdt0, uint64_t fdt1) \ 1434e2d3007SRichard Henderson { return float64_ ## impl(fdt0, fdt1, &env->fp_status); } \ 1444e2d3007SRichard Henderson target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 1455b569507SJia Liu uint32_t fdt0, uint32_t fdt1) \ 1464e2d3007SRichard Henderson { return float32_ ## impl(fdt0, fdt1, &env->fp_status); } 1475b569507SJia Liu 1484e2d3007SRichard Henderson FLOAT_CMP(le, le) 1494e2d3007SRichard Henderson FLOAT_CMP(lt, lt) 1504e2d3007SRichard Henderson FLOAT_CMP(eq, eq_quiet) 1512b13b4b9SRichard Henderson FLOAT_CMP(un, unordered_quiet) 1525b569507SJia Liu #undef FLOAT_CMP 1532b13b4b9SRichard Henderson 1542b13b4b9SRichard Henderson #define FLOAT_UCMP(name, expr) \ 1552b13b4b9SRichard Henderson target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 1562b13b4b9SRichard Henderson uint64_t fdt0, uint64_t fdt1) \ 1572b13b4b9SRichard Henderson { \ 1582b13b4b9SRichard Henderson int r = float64_compare_quiet(fdt0, fdt1, &env->fp_status); \ 1592b13b4b9SRichard Henderson return expr; \ 1602b13b4b9SRichard Henderson } \ 1612b13b4b9SRichard Henderson target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 1622b13b4b9SRichard Henderson uint32_t fdt0, uint32_t fdt1) \ 1632b13b4b9SRichard Henderson { \ 1642b13b4b9SRichard Henderson int r = float32_compare_quiet(fdt0, fdt1, &env->fp_status); \ 1652b13b4b9SRichard Henderson return expr; \ 1662b13b4b9SRichard Henderson } 1672b13b4b9SRichard Henderson 1682b13b4b9SRichard Henderson FLOAT_UCMP(ueq, r == float_relation_equal || r == float_relation_unordered) 1692b13b4b9SRichard Henderson FLOAT_UCMP(ult, r == float_relation_less || r == float_relation_unordered) 1702b13b4b9SRichard Henderson FLOAT_UCMP(ule, r != float_relation_greater) 1712b13b4b9SRichard Henderson #undef FLOAT_UCMP 172