1f798f1e2SMichael Clark /* 2f798f1e2SMichael Clark * RISC-V FPU Emulation Helpers for QEMU. 3f798f1e2SMichael Clark * 4f798f1e2SMichael Clark * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu 5f798f1e2SMichael Clark * 6f798f1e2SMichael Clark * This program is free software; you can redistribute it and/or modify it 7f798f1e2SMichael Clark * under the terms and conditions of the GNU General Public License, 8f798f1e2SMichael Clark * version 2 or later, as published by the Free Software Foundation. 9f798f1e2SMichael Clark * 10f798f1e2SMichael Clark * This program is distributed in the hope it will be useful, but WITHOUT 11f798f1e2SMichael Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12f798f1e2SMichael Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13f798f1e2SMichael Clark * more details. 14f798f1e2SMichael Clark * 15f798f1e2SMichael Clark * You should have received a copy of the GNU General Public License along with 16f798f1e2SMichael Clark * this program. If not, see <http://www.gnu.org/licenses/>. 17f798f1e2SMichael Clark */ 18f798f1e2SMichael Clark 19f798f1e2SMichael Clark #include "qemu/osdep.h" 20f798f1e2SMichael Clark #include "cpu.h" 21f798f1e2SMichael Clark #include "qemu/host-utils.h" 22f798f1e2SMichael Clark #include "exec/exec-all.h" 23f798f1e2SMichael Clark #include "exec/helper-proto.h" 24135b03cbSAlex Bennée #include "fpu/softfloat.h" 25121ddbb3SLIU Zhiwei #include "internals.h" 26f798f1e2SMichael Clark 27fb738839SMichael Clark target_ulong riscv_cpu_get_fflags(CPURISCVState *env) 28f798f1e2SMichael Clark { 29f798f1e2SMichael Clark int soft = get_float_exception_flags(&env->fp_status); 30f798f1e2SMichael Clark target_ulong hard = 0; 31f798f1e2SMichael Clark 32f798f1e2SMichael Clark hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0; 33f798f1e2SMichael Clark hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0; 34f798f1e2SMichael Clark hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0; 35f798f1e2SMichael Clark hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0; 36f798f1e2SMichael Clark hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0; 37f798f1e2SMichael Clark 38f798f1e2SMichael Clark return hard; 39f798f1e2SMichael Clark } 40f798f1e2SMichael Clark 41fb738839SMichael Clark void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard) 42f798f1e2SMichael Clark { 43f798f1e2SMichael Clark int soft = 0; 44f798f1e2SMichael Clark 45f798f1e2SMichael Clark soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0; 46f798f1e2SMichael Clark soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0; 47f798f1e2SMichael Clark soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0; 48f798f1e2SMichael Clark soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0; 49f798f1e2SMichael Clark soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0; 50f798f1e2SMichael Clark 51f798f1e2SMichael Clark set_float_exception_flags(soft, &env->fp_status); 52f798f1e2SMichael Clark } 53f798f1e2SMichael Clark 54f798f1e2SMichael Clark void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm) 55f798f1e2SMichael Clark { 56f798f1e2SMichael Clark int softrm; 57f798f1e2SMichael Clark 58f798f1e2SMichael Clark if (rm == 7) { 59f798f1e2SMichael Clark rm = env->frm; 60f798f1e2SMichael Clark } 61f798f1e2SMichael Clark switch (rm) { 62f798f1e2SMichael Clark case 0: 63f798f1e2SMichael Clark softrm = float_round_nearest_even; 64f798f1e2SMichael Clark break; 65f798f1e2SMichael Clark case 1: 66f798f1e2SMichael Clark softrm = float_round_to_zero; 67f798f1e2SMichael Clark break; 68f798f1e2SMichael Clark case 2: 69f798f1e2SMichael Clark softrm = float_round_down; 70f798f1e2SMichael Clark break; 71f798f1e2SMichael Clark case 3: 72f798f1e2SMichael Clark softrm = float_round_up; 73f798f1e2SMichael Clark break; 74f798f1e2SMichael Clark case 4: 75f798f1e2SMichael Clark softrm = float_round_ties_away; 76f798f1e2SMichael Clark break; 77f798f1e2SMichael Clark default: 78fb738839SMichael Clark riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 79f798f1e2SMichael Clark } 80f798f1e2SMichael Clark 81f798f1e2SMichael Clark set_float_rounding_mode(softrm, &env->fp_status); 82f798f1e2SMichael Clark } 83f798f1e2SMichael Clark 84*9921e3d3SRichard Henderson static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 85*9921e3d3SRichard Henderson uint64_t frs3, int flags) 86*9921e3d3SRichard Henderson { 87*9921e3d3SRichard Henderson return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status)); 88*9921e3d3SRichard Henderson } 89*9921e3d3SRichard Henderson 90f798f1e2SMichael Clark uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 91f798f1e2SMichael Clark uint64_t frs3) 92f798f1e2SMichael Clark { 93*9921e3d3SRichard Henderson return do_fmadd_s(env, frs1, frs2, frs3, 0); 94f798f1e2SMichael Clark } 95f798f1e2SMichael Clark 96f798f1e2SMichael Clark uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 97f798f1e2SMichael Clark uint64_t frs3) 98f798f1e2SMichael Clark { 99f798f1e2SMichael Clark return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status); 100f798f1e2SMichael Clark } 101f798f1e2SMichael Clark 102f798f1e2SMichael Clark uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 103f798f1e2SMichael Clark uint64_t frs3) 104f798f1e2SMichael Clark { 105*9921e3d3SRichard Henderson return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c); 106f798f1e2SMichael Clark } 107f798f1e2SMichael Clark 108f798f1e2SMichael Clark uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 109f798f1e2SMichael Clark uint64_t frs3) 110f798f1e2SMichael Clark { 111f798f1e2SMichael Clark return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c, 112f798f1e2SMichael Clark &env->fp_status); 113f798f1e2SMichael Clark } 114f798f1e2SMichael Clark 115f798f1e2SMichael Clark uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 116f798f1e2SMichael Clark uint64_t frs3) 117f798f1e2SMichael Clark { 118*9921e3d3SRichard Henderson return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product); 119f798f1e2SMichael Clark } 120f798f1e2SMichael Clark 121f798f1e2SMichael Clark uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 122f798f1e2SMichael Clark uint64_t frs3) 123f798f1e2SMichael Clark { 124f798f1e2SMichael Clark return float64_muladd(frs1, frs2, frs3, float_muladd_negate_product, 125f798f1e2SMichael Clark &env->fp_status); 126f798f1e2SMichael Clark } 127f798f1e2SMichael Clark 128f798f1e2SMichael Clark uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 129f798f1e2SMichael Clark uint64_t frs3) 130f798f1e2SMichael Clark { 131*9921e3d3SRichard Henderson return do_fmadd_s(env, frs1, frs2, frs3, 132*9921e3d3SRichard Henderson float_muladd_negate_c | float_muladd_negate_product); 133f798f1e2SMichael Clark } 134f798f1e2SMichael Clark 135f798f1e2SMichael Clark uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 136f798f1e2SMichael Clark uint64_t frs3) 137f798f1e2SMichael Clark { 138f798f1e2SMichael Clark return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c | 139f798f1e2SMichael Clark float_muladd_negate_product, &env->fp_status); 140f798f1e2SMichael Clark } 141f798f1e2SMichael Clark 142f798f1e2SMichael Clark uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 143f798f1e2SMichael Clark { 144*9921e3d3SRichard Henderson return nanbox_s(float32_add(frs1, frs2, &env->fp_status)); 145f798f1e2SMichael Clark } 146f798f1e2SMichael Clark 147f798f1e2SMichael Clark uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 148f798f1e2SMichael Clark { 149*9921e3d3SRichard Henderson return nanbox_s(float32_sub(frs1, frs2, &env->fp_status)); 150f798f1e2SMichael Clark } 151f798f1e2SMichael Clark 152f798f1e2SMichael Clark uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 153f798f1e2SMichael Clark { 154*9921e3d3SRichard Henderson return nanbox_s(float32_mul(frs1, frs2, &env->fp_status)); 155f798f1e2SMichael Clark } 156f798f1e2SMichael Clark 157f798f1e2SMichael Clark uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 158f798f1e2SMichael Clark { 159*9921e3d3SRichard Henderson return nanbox_s(float32_div(frs1, frs2, &env->fp_status)); 160f798f1e2SMichael Clark } 161f798f1e2SMichael Clark 162f798f1e2SMichael Clark uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 163f798f1e2SMichael Clark { 164*9921e3d3SRichard Henderson return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status)); 165f798f1e2SMichael Clark } 166f798f1e2SMichael Clark 167f798f1e2SMichael Clark uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 168f798f1e2SMichael Clark { 169*9921e3d3SRichard Henderson return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status)); 170f798f1e2SMichael Clark } 171f798f1e2SMichael Clark 172f798f1e2SMichael Clark uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1) 173f798f1e2SMichael Clark { 174*9921e3d3SRichard Henderson return nanbox_s(float32_sqrt(frs1, &env->fp_status)); 175f798f1e2SMichael Clark } 176f798f1e2SMichael Clark 177f798f1e2SMichael Clark target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 178f798f1e2SMichael Clark { 179f798f1e2SMichael Clark return float32_le(frs1, frs2, &env->fp_status); 180f798f1e2SMichael Clark } 181f798f1e2SMichael Clark 182f798f1e2SMichael Clark target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 183f798f1e2SMichael Clark { 184f798f1e2SMichael Clark return float32_lt(frs1, frs2, &env->fp_status); 185f798f1e2SMichael Clark } 186f798f1e2SMichael Clark 187f798f1e2SMichael Clark target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 188f798f1e2SMichael Clark { 189f798f1e2SMichael Clark return float32_eq_quiet(frs1, frs2, &env->fp_status); 190f798f1e2SMichael Clark } 191f798f1e2SMichael Clark 192f798f1e2SMichael Clark target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1) 193f798f1e2SMichael Clark { 194f798f1e2SMichael Clark return float32_to_int32(frs1, &env->fp_status); 195f798f1e2SMichael Clark } 196f798f1e2SMichael Clark 197f798f1e2SMichael Clark target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1) 198f798f1e2SMichael Clark { 199f798f1e2SMichael Clark return (int32_t)float32_to_uint32(frs1, &env->fp_status); 200f798f1e2SMichael Clark } 201f798f1e2SMichael Clark 202f798f1e2SMichael Clark #if defined(TARGET_RISCV64) 203f798f1e2SMichael Clark uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1) 204f798f1e2SMichael Clark { 205f798f1e2SMichael Clark return float32_to_int64(frs1, &env->fp_status); 206f798f1e2SMichael Clark } 207f798f1e2SMichael Clark 208f798f1e2SMichael Clark uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1) 209f798f1e2SMichael Clark { 210f798f1e2SMichael Clark return float32_to_uint64(frs1, &env->fp_status); 211f798f1e2SMichael Clark } 212f798f1e2SMichael Clark #endif 213f798f1e2SMichael Clark 214f798f1e2SMichael Clark uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1) 215f798f1e2SMichael Clark { 216*9921e3d3SRichard Henderson return nanbox_s(int32_to_float32((int32_t)rs1, &env->fp_status)); 217f798f1e2SMichael Clark } 218f798f1e2SMichael Clark 219f798f1e2SMichael Clark uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1) 220f798f1e2SMichael Clark { 221*9921e3d3SRichard Henderson return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status)); 222f798f1e2SMichael Clark } 223f798f1e2SMichael Clark 224f798f1e2SMichael Clark #if defined(TARGET_RISCV64) 225f798f1e2SMichael Clark uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1) 226f798f1e2SMichael Clark { 227*9921e3d3SRichard Henderson return nanbox_s(int64_to_float32(rs1, &env->fp_status)); 228f798f1e2SMichael Clark } 229f798f1e2SMichael Clark 230f798f1e2SMichael Clark uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1) 231f798f1e2SMichael Clark { 232*9921e3d3SRichard Henderson return nanbox_s(uint64_to_float32(rs1, &env->fp_status)); 233f798f1e2SMichael Clark } 234f798f1e2SMichael Clark #endif 235f798f1e2SMichael Clark 236f798f1e2SMichael Clark target_ulong helper_fclass_s(uint64_t frs1) 237f798f1e2SMichael Clark { 238121ddbb3SLIU Zhiwei return fclass_s(frs1); 239f798f1e2SMichael Clark } 240f798f1e2SMichael Clark 241f798f1e2SMichael Clark uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 242f798f1e2SMichael Clark { 243f798f1e2SMichael Clark return float64_add(frs1, frs2, &env->fp_status); 244f798f1e2SMichael Clark } 245f798f1e2SMichael Clark 246f798f1e2SMichael Clark uint64_t helper_fsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 247f798f1e2SMichael Clark { 248f798f1e2SMichael Clark return float64_sub(frs1, frs2, &env->fp_status); 249f798f1e2SMichael Clark } 250f798f1e2SMichael Clark 251f798f1e2SMichael Clark uint64_t helper_fmul_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 252f798f1e2SMichael Clark { 253f798f1e2SMichael Clark return float64_mul(frs1, frs2, &env->fp_status); 254f798f1e2SMichael Clark } 255f798f1e2SMichael Clark 256f798f1e2SMichael Clark uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 257f798f1e2SMichael Clark { 258f798f1e2SMichael Clark return float64_div(frs1, frs2, &env->fp_status); 259f798f1e2SMichael Clark } 260f798f1e2SMichael Clark 261f798f1e2SMichael Clark uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 262f798f1e2SMichael Clark { 263f798f1e2SMichael Clark return float64_minnum(frs1, frs2, &env->fp_status); 264f798f1e2SMichael Clark } 265f798f1e2SMichael Clark 266f798f1e2SMichael Clark uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 267f798f1e2SMichael Clark { 268f798f1e2SMichael Clark return float64_maxnum(frs1, frs2, &env->fp_status); 269f798f1e2SMichael Clark } 270f798f1e2SMichael Clark 271f798f1e2SMichael Clark uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1) 272f798f1e2SMichael Clark { 273*9921e3d3SRichard Henderson return nanbox_s(float64_to_float32(rs1, &env->fp_status)); 274f798f1e2SMichael Clark } 275f798f1e2SMichael Clark 276f798f1e2SMichael Clark uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1) 277f798f1e2SMichael Clark { 278cab32112SRichard Henderson return float32_to_float64(rs1, &env->fp_status); 279f798f1e2SMichael Clark } 280f798f1e2SMichael Clark 281f798f1e2SMichael Clark uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1) 282f798f1e2SMichael Clark { 283f798f1e2SMichael Clark return float64_sqrt(frs1, &env->fp_status); 284f798f1e2SMichael Clark } 285f798f1e2SMichael Clark 286f798f1e2SMichael Clark target_ulong helper_fle_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 287f798f1e2SMichael Clark { 288f798f1e2SMichael Clark return float64_le(frs1, frs2, &env->fp_status); 289f798f1e2SMichael Clark } 290f798f1e2SMichael Clark 291f798f1e2SMichael Clark target_ulong helper_flt_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 292f798f1e2SMichael Clark { 293f798f1e2SMichael Clark return float64_lt(frs1, frs2, &env->fp_status); 294f798f1e2SMichael Clark } 295f798f1e2SMichael Clark 296f798f1e2SMichael Clark target_ulong helper_feq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 297f798f1e2SMichael Clark { 298f798f1e2SMichael Clark return float64_eq_quiet(frs1, frs2, &env->fp_status); 299f798f1e2SMichael Clark } 300f798f1e2SMichael Clark 301f798f1e2SMichael Clark target_ulong helper_fcvt_w_d(CPURISCVState *env, uint64_t frs1) 302f798f1e2SMichael Clark { 303f798f1e2SMichael Clark return float64_to_int32(frs1, &env->fp_status); 304f798f1e2SMichael Clark } 305f798f1e2SMichael Clark 306f798f1e2SMichael Clark target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1) 307f798f1e2SMichael Clark { 308f798f1e2SMichael Clark return (int32_t)float64_to_uint32(frs1, &env->fp_status); 309f798f1e2SMichael Clark } 310f798f1e2SMichael Clark 311f798f1e2SMichael Clark #if defined(TARGET_RISCV64) 312f798f1e2SMichael Clark uint64_t helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1) 313f798f1e2SMichael Clark { 314f798f1e2SMichael Clark return float64_to_int64(frs1, &env->fp_status); 315f798f1e2SMichael Clark } 316f798f1e2SMichael Clark 317f798f1e2SMichael Clark uint64_t helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1) 318f798f1e2SMichael Clark { 319f798f1e2SMichael Clark return float64_to_uint64(frs1, &env->fp_status); 320f798f1e2SMichael Clark } 321f798f1e2SMichael Clark #endif 322f798f1e2SMichael Clark 323f798f1e2SMichael Clark uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1) 324f798f1e2SMichael Clark { 325f798f1e2SMichael Clark return int32_to_float64((int32_t)rs1, &env->fp_status); 326f798f1e2SMichael Clark } 327f798f1e2SMichael Clark 328f798f1e2SMichael Clark uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1) 329f798f1e2SMichael Clark { 330f798f1e2SMichael Clark return uint32_to_float64((uint32_t)rs1, &env->fp_status); 331f798f1e2SMichael Clark } 332f798f1e2SMichael Clark 333f798f1e2SMichael Clark #if defined(TARGET_RISCV64) 334f798f1e2SMichael Clark uint64_t helper_fcvt_d_l(CPURISCVState *env, uint64_t rs1) 335f798f1e2SMichael Clark { 336f798f1e2SMichael Clark return int64_to_float64(rs1, &env->fp_status); 337f798f1e2SMichael Clark } 338f798f1e2SMichael Clark 339f798f1e2SMichael Clark uint64_t helper_fcvt_d_lu(CPURISCVState *env, uint64_t rs1) 340f798f1e2SMichael Clark { 341f798f1e2SMichael Clark return uint64_to_float64(rs1, &env->fp_status); 342f798f1e2SMichael Clark } 343f798f1e2SMichael Clark #endif 344f798f1e2SMichael Clark 345f798f1e2SMichael Clark target_ulong helper_fclass_d(uint64_t frs1) 346f798f1e2SMichael Clark { 347121ddbb3SLIU Zhiwei return fclass_d(frs1); 348f798f1e2SMichael Clark } 349