cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

fpu_helper.c (10527B)


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