1 /* 2 * OpenRISC float helper routines 3 * 4 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> 5 * Feng Gao <gf91597@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "cpu.h" 23 #include "exec/helper-proto.h" 24 #include "exception.h" 25 #include "fpu/softfloat.h" 26 27 static int ieee_ex_to_openrisc(int fexcp) 28 { 29 int ret = 0; 30 if (fexcp & float_flag_invalid) { 31 ret |= FPCSR_IVF; 32 } 33 if (fexcp & float_flag_overflow) { 34 ret |= FPCSR_OVF; 35 } 36 if (fexcp & float_flag_underflow) { 37 ret |= FPCSR_UNF; 38 } 39 if (fexcp & float_flag_divbyzero) { 40 ret |= FPCSR_DZF; 41 } 42 if (fexcp & float_flag_inexact) { 43 ret |= FPCSR_IXF; 44 } 45 return ret; 46 } 47 48 void HELPER(update_fpcsr)(CPUOpenRISCState *env) 49 { 50 int tmp = get_float_exception_flags(&env->fp_status); 51 52 if (tmp) { 53 set_float_exception_flags(0, &env->fp_status); 54 tmp = ieee_ex_to_openrisc(tmp); 55 if (tmp) { 56 env->fpcsr |= tmp; 57 if (env->fpcsr & FPCSR_FPEE) { 58 helper_exception(env, EXCP_FPE); 59 } 60 } 61 } 62 } 63 64 uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val) 65 { 66 return int32_to_float64(val, &env->fp_status); 67 } 68 69 uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val) 70 { 71 return int32_to_float32(val, &env->fp_status); 72 } 73 74 uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val) 75 { 76 return float32_to_int64(val, &env->fp_status); 77 } 78 79 uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val) 80 { 81 return float32_to_int32(val, &env->fp_status); 82 } 83 84 #define FLOAT_CALC(name) \ 85 uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 86 uint64_t fdt0, uint64_t fdt1) \ 87 { return float64_ ## name(fdt0, fdt1, &env->fp_status); } \ 88 uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 89 uint32_t fdt0, uint32_t fdt1) \ 90 { return float32_ ## name(fdt0, fdt1, &env->fp_status); } 91 92 FLOAT_CALC(add) 93 FLOAT_CALC(sub) 94 FLOAT_CALC(mul) 95 FLOAT_CALC(div) 96 FLOAT_CALC(rem) 97 #undef FLOAT_CALC 98 99 100 uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a, 101 uint64_t b, uint64_t c) 102 { 103 /* Note that or1ksim doesn't use fused operation. */ 104 b = float64_mul(b, c, &env->fp_status); 105 return float64_add(a, b, &env->fp_status); 106 } 107 108 uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a, 109 uint32_t b, uint32_t c) 110 { 111 /* Note that or1ksim doesn't use fused operation. */ 112 b = float32_mul(b, c, &env->fp_status); 113 return float32_add(a, b, &env->fp_status); 114 } 115 116 117 #define FLOAT_CMP(name, impl) \ 118 target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \ 119 uint64_t fdt0, uint64_t fdt1) \ 120 { return float64_ ## impl(fdt0, fdt1, &env->fp_status); } \ 121 target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \ 122 uint32_t fdt0, uint32_t fdt1) \ 123 { return float32_ ## impl(fdt0, fdt1, &env->fp_status); } 124 125 FLOAT_CMP(le, le) 126 FLOAT_CMP(lt, lt) 127 FLOAT_CMP(eq, eq_quiet) 128 #undef FLOAT_CMP 129