1*5c23704eSSong Gao/* SPDX-License-Identifier: GPL-2.0-or-later */ 2*5c23704eSSong Gao/* 3*5c23704eSSong Gao * Copyright (c) 2021 Loongson Technology Corporation Limited 4*5c23704eSSong Gao */ 5*5c23704eSSong Gao 6*5c23704eSSong Gao#ifndef CONFIG_USER_ONLY 7*5c23704eSSong Gao#define CHECK_FPE do { \ 8*5c23704eSSong Gao if ((ctx->base.tb->flags & HW_FLAGS_EUEN_FPE) == 0) { \ 9*5c23704eSSong Gao generate_exception(ctx, EXCCODE_FPD); \ 10*5c23704eSSong Gao return true; \ 11*5c23704eSSong Gao } \ 12*5c23704eSSong Gao} while (0) 13*5c23704eSSong Gao#else 14*5c23704eSSong Gao#define CHECK_FPE 15*5c23704eSSong Gao#endif 16*5c23704eSSong Gao 17*5c23704eSSong Gaostatic bool gen_fff(DisasContext *ctx, arg_fff *a, 18*5c23704eSSong Gao void (*func)(TCGv, TCGv_env, TCGv, TCGv)) 19*5c23704eSSong Gao{ 20*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 21*5c23704eSSong Gao TCGv src1 = get_fpr(ctx, a->fj); 22*5c23704eSSong Gao TCGv src2 = get_fpr(ctx, a->fk); 23*5c23704eSSong Gao 24*5c23704eSSong Gao CHECK_FPE; 25*5c23704eSSong Gao 26*5c23704eSSong Gao func(dest, tcg_env, src1, src2); 27*5c23704eSSong Gao set_fpr(a->fd, dest); 28*5c23704eSSong Gao 29*5c23704eSSong Gao return true; 30*5c23704eSSong Gao} 31*5c23704eSSong Gao 32*5c23704eSSong Gaostatic bool gen_ff(DisasContext *ctx, arg_ff *a, 33*5c23704eSSong Gao void (*func)(TCGv, TCGv_env, TCGv)) 34*5c23704eSSong Gao{ 35*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 36*5c23704eSSong Gao TCGv src = get_fpr(ctx, a->fj); 37*5c23704eSSong Gao 38*5c23704eSSong Gao CHECK_FPE; 39*5c23704eSSong Gao 40*5c23704eSSong Gao func(dest, tcg_env, src); 41*5c23704eSSong Gao set_fpr(a->fd, dest); 42*5c23704eSSong Gao 43*5c23704eSSong Gao return true; 44*5c23704eSSong Gao} 45*5c23704eSSong Gao 46*5c23704eSSong Gaostatic bool gen_muladd(DisasContext *ctx, arg_ffff *a, 47*5c23704eSSong Gao void (*func)(TCGv, TCGv_env, TCGv, TCGv, TCGv, TCGv_i32), 48*5c23704eSSong Gao int flag) 49*5c23704eSSong Gao{ 50*5c23704eSSong Gao TCGv_i32 tflag = tcg_constant_i32(flag); 51*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 52*5c23704eSSong Gao TCGv src1 = get_fpr(ctx, a->fj); 53*5c23704eSSong Gao TCGv src2 = get_fpr(ctx, a->fk); 54*5c23704eSSong Gao TCGv src3 = get_fpr(ctx, a->fa); 55*5c23704eSSong Gao 56*5c23704eSSong Gao CHECK_FPE; 57*5c23704eSSong Gao 58*5c23704eSSong Gao func(dest, tcg_env, src1, src2, src3, tflag); 59*5c23704eSSong Gao set_fpr(a->fd, dest); 60*5c23704eSSong Gao 61*5c23704eSSong Gao return true; 62*5c23704eSSong Gao} 63*5c23704eSSong Gao 64*5c23704eSSong Gaostatic bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a) 65*5c23704eSSong Gao{ 66*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 67*5c23704eSSong Gao TCGv src1 = get_fpr(ctx, a->fk); 68*5c23704eSSong Gao TCGv src2 = get_fpr(ctx, a->fj); 69*5c23704eSSong Gao 70*5c23704eSSong Gao if (!avail_FP_SP(ctx)) { 71*5c23704eSSong Gao return false; 72*5c23704eSSong Gao } 73*5c23704eSSong Gao 74*5c23704eSSong Gao CHECK_FPE; 75*5c23704eSSong Gao 76*5c23704eSSong Gao tcg_gen_deposit_i64(dest, src1, src2, 0, 31); 77*5c23704eSSong Gao set_fpr(a->fd, dest); 78*5c23704eSSong Gao 79*5c23704eSSong Gao return true; 80*5c23704eSSong Gao} 81*5c23704eSSong Gao 82*5c23704eSSong Gaostatic bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a) 83*5c23704eSSong Gao{ 84*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 85*5c23704eSSong Gao TCGv src1 = get_fpr(ctx, a->fk); 86*5c23704eSSong Gao TCGv src2 = get_fpr(ctx, a->fj); 87*5c23704eSSong Gao 88*5c23704eSSong Gao if (!avail_FP_DP(ctx)) { 89*5c23704eSSong Gao return false; 90*5c23704eSSong Gao } 91*5c23704eSSong Gao 92*5c23704eSSong Gao CHECK_FPE; 93*5c23704eSSong Gao 94*5c23704eSSong Gao tcg_gen_deposit_i64(dest, src1, src2, 0, 63); 95*5c23704eSSong Gao set_fpr(a->fd, dest); 96*5c23704eSSong Gao 97*5c23704eSSong Gao return true; 98*5c23704eSSong Gao} 99*5c23704eSSong Gao 100*5c23704eSSong Gaostatic bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a) 101*5c23704eSSong Gao{ 102*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 103*5c23704eSSong Gao TCGv src = get_fpr(ctx, a->fj); 104*5c23704eSSong Gao 105*5c23704eSSong Gao if (!avail_FP_SP(ctx)) { 106*5c23704eSSong Gao return false; 107*5c23704eSSong Gao } 108*5c23704eSSong Gao 109*5c23704eSSong Gao CHECK_FPE; 110*5c23704eSSong Gao 111*5c23704eSSong Gao tcg_gen_andi_i64(dest, src, MAKE_64BIT_MASK(0, 31)); 112*5c23704eSSong Gao gen_nanbox_s(dest, dest); 113*5c23704eSSong Gao set_fpr(a->fd, dest); 114*5c23704eSSong Gao 115*5c23704eSSong Gao return true; 116*5c23704eSSong Gao} 117*5c23704eSSong Gao 118*5c23704eSSong Gaostatic bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a) 119*5c23704eSSong Gao{ 120*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 121*5c23704eSSong Gao TCGv src = get_fpr(ctx, a->fj); 122*5c23704eSSong Gao 123*5c23704eSSong Gao if (!avail_FP_DP(ctx)) { 124*5c23704eSSong Gao return false; 125*5c23704eSSong Gao } 126*5c23704eSSong Gao 127*5c23704eSSong Gao CHECK_FPE; 128*5c23704eSSong Gao 129*5c23704eSSong Gao tcg_gen_andi_i64(dest, src, MAKE_64BIT_MASK(0, 63)); 130*5c23704eSSong Gao set_fpr(a->fd, dest); 131*5c23704eSSong Gao 132*5c23704eSSong Gao return true; 133*5c23704eSSong Gao} 134*5c23704eSSong Gao 135*5c23704eSSong Gaostatic bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a) 136*5c23704eSSong Gao{ 137*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 138*5c23704eSSong Gao TCGv src = get_fpr(ctx, a->fj); 139*5c23704eSSong Gao 140*5c23704eSSong Gao if (!avail_FP_SP(ctx)) { 141*5c23704eSSong Gao return false; 142*5c23704eSSong Gao } 143*5c23704eSSong Gao 144*5c23704eSSong Gao CHECK_FPE; 145*5c23704eSSong Gao 146*5c23704eSSong Gao tcg_gen_xori_i64(dest, src, 0x80000000); 147*5c23704eSSong Gao gen_nanbox_s(dest, dest); 148*5c23704eSSong Gao set_fpr(a->fd, dest); 149*5c23704eSSong Gao 150*5c23704eSSong Gao return true; 151*5c23704eSSong Gao} 152*5c23704eSSong Gao 153*5c23704eSSong Gaostatic bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a) 154*5c23704eSSong Gao{ 155*5c23704eSSong Gao TCGv dest = get_fpr(ctx, a->fd); 156*5c23704eSSong Gao TCGv src = get_fpr(ctx, a->fj); 157*5c23704eSSong Gao 158*5c23704eSSong Gao if (!avail_FP_DP(ctx)) { 159*5c23704eSSong Gao return false; 160*5c23704eSSong Gao } 161*5c23704eSSong Gao 162*5c23704eSSong Gao CHECK_FPE; 163*5c23704eSSong Gao 164*5c23704eSSong Gao tcg_gen_xori_i64(dest, src, 0x8000000000000000LL); 165*5c23704eSSong Gao set_fpr(a->fd, dest); 166*5c23704eSSong Gao 167*5c23704eSSong Gao return true; 168*5c23704eSSong Gao} 169*5c23704eSSong Gao 170*5c23704eSSong GaoTRANS(fadd_s, FP_SP, gen_fff, gen_helper_fadd_s) 171*5c23704eSSong GaoTRANS(fadd_d, FP_DP, gen_fff, gen_helper_fadd_d) 172*5c23704eSSong GaoTRANS(fsub_s, FP_SP, gen_fff, gen_helper_fsub_s) 173*5c23704eSSong GaoTRANS(fsub_d, FP_DP, gen_fff, gen_helper_fsub_d) 174*5c23704eSSong GaoTRANS(fmul_s, FP_SP, gen_fff, gen_helper_fmul_s) 175*5c23704eSSong GaoTRANS(fmul_d, FP_DP, gen_fff, gen_helper_fmul_d) 176*5c23704eSSong GaoTRANS(fdiv_s, FP_SP, gen_fff, gen_helper_fdiv_s) 177*5c23704eSSong GaoTRANS(fdiv_d, FP_DP, gen_fff, gen_helper_fdiv_d) 178*5c23704eSSong GaoTRANS(fmax_s, FP_SP, gen_fff, gen_helper_fmax_s) 179*5c23704eSSong GaoTRANS(fmax_d, FP_DP, gen_fff, gen_helper_fmax_d) 180*5c23704eSSong GaoTRANS(fmin_s, FP_SP, gen_fff, gen_helper_fmin_s) 181*5c23704eSSong GaoTRANS(fmin_d, FP_DP, gen_fff, gen_helper_fmin_d) 182*5c23704eSSong GaoTRANS(fmaxa_s, FP_SP, gen_fff, gen_helper_fmaxa_s) 183*5c23704eSSong GaoTRANS(fmaxa_d, FP_DP, gen_fff, gen_helper_fmaxa_d) 184*5c23704eSSong GaoTRANS(fmina_s, FP_SP, gen_fff, gen_helper_fmina_s) 185*5c23704eSSong GaoTRANS(fmina_d, FP_DP, gen_fff, gen_helper_fmina_d) 186*5c23704eSSong GaoTRANS(fscaleb_s, FP_SP, gen_fff, gen_helper_fscaleb_s) 187*5c23704eSSong GaoTRANS(fscaleb_d, FP_DP, gen_fff, gen_helper_fscaleb_d) 188*5c23704eSSong GaoTRANS(fsqrt_s, FP_SP, gen_ff, gen_helper_fsqrt_s) 189*5c23704eSSong GaoTRANS(fsqrt_d, FP_DP, gen_ff, gen_helper_fsqrt_d) 190*5c23704eSSong GaoTRANS(frecip_s, FP_SP, gen_ff, gen_helper_frecip_s) 191*5c23704eSSong GaoTRANS(frecip_d, FP_DP, gen_ff, gen_helper_frecip_d) 192*5c23704eSSong GaoTRANS(frsqrt_s, FP_SP, gen_ff, gen_helper_frsqrt_s) 193*5c23704eSSong GaoTRANS(frsqrt_d, FP_DP, gen_ff, gen_helper_frsqrt_d) 194*5c23704eSSong GaoTRANS(flogb_s, FP_SP, gen_ff, gen_helper_flogb_s) 195*5c23704eSSong GaoTRANS(flogb_d, FP_DP, gen_ff, gen_helper_flogb_d) 196*5c23704eSSong GaoTRANS(fclass_s, FP_SP, gen_ff, gen_helper_fclass_s) 197*5c23704eSSong GaoTRANS(fclass_d, FP_DP, gen_ff, gen_helper_fclass_d) 198*5c23704eSSong GaoTRANS(fmadd_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, 0) 199*5c23704eSSong GaoTRANS(fmadd_d, FP_DP, gen_muladd, gen_helper_fmuladd_d, 0) 200*5c23704eSSong GaoTRANS(fmsub_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_c) 201*5c23704eSSong GaoTRANS(fmsub_d, FP_DP, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_c) 202*5c23704eSSong GaoTRANS(fnmadd_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_result) 203*5c23704eSSong GaoTRANS(fnmadd_d, FP_DP, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_result) 204*5c23704eSSong GaoTRANS(fnmsub_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, 205*5c23704eSSong Gao float_muladd_negate_c | float_muladd_negate_result) 206*5c23704eSSong GaoTRANS(fnmsub_d, FP_DP, gen_muladd, gen_helper_fmuladd_d, 207*5c23704eSSong Gao float_muladd_negate_c | float_muladd_negate_result) 208