xref: /openbmc/qemu/target/loongarch/tcg/insn_trans/trans_farith.c.inc (revision 8188c3cda586dc445cac875b7d21c0c960dbe97e)
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