xref: /qemu/target/ppc/translate/fp-impl.c.inc (revision 177fcc06)
1139c1837SPaolo Bonzini/*
2139c1837SPaolo Bonzini * translate-fp.c
3139c1837SPaolo Bonzini *
4139c1837SPaolo Bonzini * Standard FPU translation
5139c1837SPaolo Bonzini */
6139c1837SPaolo Bonzini
7139c1837SPaolo Bonzinistatic inline void gen_reset_fpstatus(void)
8139c1837SPaolo Bonzini{
9ad75a51eSRichard Henderson    gen_helper_reset_fpstatus(tcg_env);
10139c1837SPaolo Bonzini}
11139c1837SPaolo Bonzini
12139c1837SPaolo Bonzinistatic inline void gen_compute_fprf_float64(TCGv_i64 arg)
13139c1837SPaolo Bonzini{
14ad75a51eSRichard Henderson    gen_helper_compute_fprf_float64(tcg_env, arg);
15ad75a51eSRichard Henderson    gen_helper_float_check_status(tcg_env);
16139c1837SPaolo Bonzini}
17139c1837SPaolo Bonzini
18139c1837SPaolo Bonzini#if defined(TARGET_PPC64)
19139c1837SPaolo Bonzinistatic void gen_set_cr1_from_fpscr(DisasContext *ctx)
20139c1837SPaolo Bonzini{
21139c1837SPaolo Bonzini    TCGv_i32 tmp = tcg_temp_new_i32();
22139c1837SPaolo Bonzini    tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
23139c1837SPaolo Bonzini    tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
24139c1837SPaolo Bonzini}
25139c1837SPaolo Bonzini#else
26139c1837SPaolo Bonzinistatic void gen_set_cr1_from_fpscr(DisasContext *ctx)
27139c1837SPaolo Bonzini{
28139c1837SPaolo Bonzini    tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
29139c1837SPaolo Bonzini}
30139c1837SPaolo Bonzini#endif
31139c1837SPaolo Bonzini
32139c1837SPaolo Bonzini/***                       Floating-Point arithmetic                       ***/
33*177fcc06SChinmay Rathstatic bool do_helper_acb(DisasContext *ctx, arg_A *a,
34*177fcc06SChinmay Rath                          void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64,
35*177fcc06SChinmay Rath                                         TCGv_i64, TCGv_i64))
36*177fcc06SChinmay Rath{
37*177fcc06SChinmay Rath    TCGv_i64 t0, t1, t2, t3;
38*177fcc06SChinmay Rath    REQUIRE_INSNS_FLAGS(ctx, FLOAT);
39*177fcc06SChinmay Rath    REQUIRE_FPU(ctx);
40*177fcc06SChinmay Rath    t0 = tcg_temp_new_i64();
41*177fcc06SChinmay Rath    t1 = tcg_temp_new_i64();
42*177fcc06SChinmay Rath    t2 = tcg_temp_new_i64();
43*177fcc06SChinmay Rath    t3 = tcg_temp_new_i64();
44*177fcc06SChinmay Rath    gen_reset_fpstatus();
45*177fcc06SChinmay Rath    get_fpr(t0, a->fra);
46*177fcc06SChinmay Rath    get_fpr(t1, a->frc);
47*177fcc06SChinmay Rath    get_fpr(t2, a->frb);
48*177fcc06SChinmay Rath    helper(t3, tcg_env, t0, t1, t2);
49*177fcc06SChinmay Rath    set_fpr(a->frt, t3);
50*177fcc06SChinmay Rath    gen_compute_fprf_float64(t3);
51*177fcc06SChinmay Rath    if (unlikely(a->rc)) {
52*177fcc06SChinmay Rath        gen_set_cr1_from_fpscr(ctx);
53*177fcc06SChinmay Rath    }
54*177fcc06SChinmay Rath    return true;
55139c1837SPaolo Bonzini}
56139c1837SPaolo Bonzini
57*177fcc06SChinmay Rathstatic bool do_helper_ab(DisasContext *ctx, arg_A_tab *a,
58*177fcc06SChinmay Rath                         void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64,
59*177fcc06SChinmay Rath                                        TCGv_i64))
60*177fcc06SChinmay Rath{
61*177fcc06SChinmay Rath    TCGv_i64 t0, t1, t2;
62*177fcc06SChinmay Rath    REQUIRE_INSNS_FLAGS(ctx, FLOAT);
63*177fcc06SChinmay Rath    REQUIRE_FPU(ctx);
64*177fcc06SChinmay Rath    t0 = tcg_temp_new_i64();
65*177fcc06SChinmay Rath    t1 = tcg_temp_new_i64();
66*177fcc06SChinmay Rath    t2 = tcg_temp_new_i64();
67*177fcc06SChinmay Rath    gen_reset_fpstatus();
68*177fcc06SChinmay Rath    get_fpr(t0, a->fra);
69*177fcc06SChinmay Rath    get_fpr(t1, a->frb);
70*177fcc06SChinmay Rath    helper(t2, tcg_env, t0, t1);
71*177fcc06SChinmay Rath    set_fpr(a->frt, t2);
72*177fcc06SChinmay Rath    gen_compute_fprf_float64(t2);
73*177fcc06SChinmay Rath    if (unlikely(a->rc)) {
74*177fcc06SChinmay Rath        gen_set_cr1_from_fpscr(ctx);
75139c1837SPaolo Bonzini    }
76*177fcc06SChinmay Rath    return true;
77139c1837SPaolo Bonzini}
78*177fcc06SChinmay Rath
79*177fcc06SChinmay Rathstatic bool do_helper_ac(DisasContext *ctx, arg_A_tac *a,
80*177fcc06SChinmay Rath                         void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64,
81*177fcc06SChinmay Rath                                        TCGv_i64))
82*177fcc06SChinmay Rath{
83*177fcc06SChinmay Rath    TCGv_i64 t0, t1, t2;
84*177fcc06SChinmay Rath    REQUIRE_INSNS_FLAGS(ctx, FLOAT);
85*177fcc06SChinmay Rath    REQUIRE_FPU(ctx);
86*177fcc06SChinmay Rath    t0 = tcg_temp_new_i64();
87*177fcc06SChinmay Rath    t1 = tcg_temp_new_i64();
88*177fcc06SChinmay Rath    t2 = tcg_temp_new_i64();
89*177fcc06SChinmay Rath    gen_reset_fpstatus();
90*177fcc06SChinmay Rath    get_fpr(t0, a->fra);
91*177fcc06SChinmay Rath    get_fpr(t1, a->frc);
92*177fcc06SChinmay Rath    helper(t2, tcg_env, t0, t1);
93*177fcc06SChinmay Rath    set_fpr(a->frt, t2);
94*177fcc06SChinmay Rath    gen_compute_fprf_float64(t2);
95*177fcc06SChinmay Rath    if (unlikely(a->rc)) {
96*177fcc06SChinmay Rath        gen_set_cr1_from_fpscr(ctx);
97*177fcc06SChinmay Rath    }
98*177fcc06SChinmay Rath    return true;
99*177fcc06SChinmay Rath}
100139c1837SPaolo Bonzini
101139c1837SPaolo Bonzini#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
102139c1837SPaolo Bonzinistatic void gen_f##name(DisasContext *ctx)                                    \
103139c1837SPaolo Bonzini{                                                                             \
104139c1837SPaolo Bonzini    TCGv_i64 t0;                                                              \
105139c1837SPaolo Bonzini    TCGv_i64 t1;                                                              \
106139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {                                        \
107139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
108139c1837SPaolo Bonzini        return;                                                               \
109139c1837SPaolo Bonzini    }                                                                         \
110139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();                                                  \
111139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();                                                  \
112139c1837SPaolo Bonzini    gen_reset_fpstatus();                                                     \
113139c1837SPaolo Bonzini    get_fpr(t0, rB(ctx->opcode));                                             \
114ad75a51eSRichard Henderson    gen_helper_f##name(t1, tcg_env, t0);                                      \
115139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t1);                                             \
116139c1837SPaolo Bonzini    if (set_fprf) {                                                           \
117ad75a51eSRichard Henderson        gen_helper_compute_fprf_float64(tcg_env, t1);                         \
118139c1837SPaolo Bonzini    }                                                                         \
119ad75a51eSRichard Henderson    gen_helper_float_check_status(tcg_env);                                   \
120139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
121139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);                                          \
122139c1837SPaolo Bonzini    }                                                                         \
123139c1837SPaolo Bonzini}
124139c1837SPaolo Bonzini
125*177fcc06SChinmay Rathstatic bool do_helper_bs(DisasContext *ctx, arg_A_tb *a,
126*177fcc06SChinmay Rath                         void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64))
127139c1837SPaolo Bonzini{
128*177fcc06SChinmay Rath    TCGv_i64 t0, t1;
129*177fcc06SChinmay Rath    REQUIRE_FPU(ctx);
130139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
131139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
132139c1837SPaolo Bonzini    gen_reset_fpstatus();
133*177fcc06SChinmay Rath    get_fpr(t0, a->frb);
134*177fcc06SChinmay Rath    helper(t1, tcg_env, t0);
135*177fcc06SChinmay Rath    set_fpr(a->frt, t1);
136139c1837SPaolo Bonzini    gen_compute_fprf_float64(t1);
137*177fcc06SChinmay Rath    if (unlikely(a->rc)) {
138139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);
139139c1837SPaolo Bonzini    }
140*177fcc06SChinmay Rath    return true;
141139c1837SPaolo Bonzini}
142139c1837SPaolo Bonzini
143eb69a84bSMatheus Ferststatic bool trans_FSEL(DisasContext *ctx, arg_A *a)
144eb69a84bSMatheus Ferst{
145eb69a84bSMatheus Ferst    TCGv_i64 t0, t1, t2;
146eb69a84bSMatheus Ferst
147eb69a84bSMatheus Ferst    REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSEL);
148eb69a84bSMatheus Ferst    REQUIRE_FPU(ctx);
149eb69a84bSMatheus Ferst
150eb69a84bSMatheus Ferst    t0 = tcg_temp_new_i64();
151eb69a84bSMatheus Ferst    t1 = tcg_temp_new_i64();
152eb69a84bSMatheus Ferst    t2 = tcg_temp_new_i64();
153eb69a84bSMatheus Ferst
154eb69a84bSMatheus Ferst    get_fpr(t0, a->fra);
155eb69a84bSMatheus Ferst    get_fpr(t1, a->frb);
156eb69a84bSMatheus Ferst    get_fpr(t2, a->frc);
157eb69a84bSMatheus Ferst
158eb69a84bSMatheus Ferst    gen_helper_FSEL(t0, t0, t1, t2);
159eb69a84bSMatheus Ferst    set_fpr(a->frt, t0);
160eb69a84bSMatheus Ferst    if (a->rc) {
161eb69a84bSMatheus Ferst        gen_set_cr1_from_fpscr(ctx);
162eb69a84bSMatheus Ferst    }
163eb69a84bSMatheus Ferst    return true;
164eb69a84bSMatheus Ferst}
165eb69a84bSMatheus Ferst
1666a8654d6SVíctor Colombostatic bool do_helper_fsqrt(DisasContext *ctx, arg_A_tb *a,
1676a8654d6SVíctor Colombo                            void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64))
168139c1837SPaolo Bonzini{
1696a8654d6SVíctor Colombo    TCGv_i64 t0, t1;
1706a8654d6SVíctor Colombo
1716a8654d6SVíctor Colombo    REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSQRT);
1726a8654d6SVíctor Colombo    REQUIRE_FPU(ctx);
1736a8654d6SVíctor Colombo
174139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
175139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
1766a8654d6SVíctor Colombo
177139c1837SPaolo Bonzini    gen_reset_fpstatus();
1786a8654d6SVíctor Colombo    get_fpr(t0, a->frb);
179ad75a51eSRichard Henderson    helper(t1, tcg_env, t0);
1806a8654d6SVíctor Colombo    set_fpr(a->frt, t1);
181139c1837SPaolo Bonzini    gen_compute_fprf_float64(t1);
1826a8654d6SVíctor Colombo    if (unlikely(a->rc != 0)) {
183139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);
184139c1837SPaolo Bonzini    }
1856a8654d6SVíctor Colombo    return true;
186139c1837SPaolo Bonzini}
187139c1837SPaolo Bonzini
188*177fcc06SChinmay RathTRANS(FADD, do_helper_ab, gen_helper_FADD);
189*177fcc06SChinmay RathTRANS(FADDS, do_helper_ab, gen_helper_FADDS);
190*177fcc06SChinmay RathTRANS(FSUB, do_helper_ab, gen_helper_FSUB);
191*177fcc06SChinmay RathTRANS(FSUBS, do_helper_ab, gen_helper_FSUBS);
192*177fcc06SChinmay RathTRANS(FDIV, do_helper_ab, gen_helper_FDIV);
193*177fcc06SChinmay RathTRANS(FDIVS, do_helper_ab, gen_helper_FDIVS);
194*177fcc06SChinmay RathTRANS(FMUL, do_helper_ac, gen_helper_FMUL);
195*177fcc06SChinmay RathTRANS(FMULS, do_helper_ac, gen_helper_FMULS);
196*177fcc06SChinmay Rath
197*177fcc06SChinmay RathTRANS(FMADD, do_helper_acb, gen_helper_FMADD);
198*177fcc06SChinmay RathTRANS(FMADDS, do_helper_acb, gen_helper_FMADDS);
199*177fcc06SChinmay RathTRANS(FMSUB, do_helper_acb, gen_helper_FMSUB);
200*177fcc06SChinmay RathTRANS(FMSUBS, do_helper_acb, gen_helper_FMSUBS);
201*177fcc06SChinmay Rath
202*177fcc06SChinmay RathTRANS(FNMADD, do_helper_acb, gen_helper_FNMADD);
203*177fcc06SChinmay RathTRANS(FNMADDS, do_helper_acb, gen_helper_FNMADDS);
204*177fcc06SChinmay RathTRANS(FNMSUB, do_helper_acb, gen_helper_FNMSUB);
205*177fcc06SChinmay RathTRANS(FNMSUBS, do_helper_acb, gen_helper_FNMSUBS);
206*177fcc06SChinmay Rath
207*177fcc06SChinmay RathTRANS_FLAGS(FLOAT_EXT, FRE, do_helper_bs, gen_helper_FRE);
208*177fcc06SChinmay RathTRANS_FLAGS(FLOAT_FRES, FRES, do_helper_bs, gen_helper_FRES);
209*177fcc06SChinmay RathTRANS_FLAGS(FLOAT_FRSQRTE, FRSQRTE, do_helper_bs, gen_helper_FRSQRTE);
210*177fcc06SChinmay RathTRANS_FLAGS(FLOAT_FRSQRTES, FRSQRTES, do_helper_bs, gen_helper_FRSQRTES);
211*177fcc06SChinmay Rath
21274177ec6SVíctor ColomboTRANS(FSQRT, do_helper_fsqrt, gen_helper_FSQRT);
21374177ec6SVíctor ColomboTRANS(FSQRTS, do_helper_fsqrt, gen_helper_FSQRTS);
214139c1837SPaolo Bonzini
215139c1837SPaolo Bonzini/***                     Floating-Point round & convert                    ***/
216139c1837SPaolo Bonzini/* fctiw */
217139c1837SPaolo BonziniGEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
218139c1837SPaolo Bonzini/* fctiwu */
219139c1837SPaolo BonziniGEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206);
220139c1837SPaolo Bonzini/* fctiwz */
221139c1837SPaolo BonziniGEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
222139c1837SPaolo Bonzini/* fctiwuz */
223139c1837SPaolo BonziniGEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206);
224139c1837SPaolo Bonzini/* frsp */
225139c1837SPaolo BonziniGEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
226139c1837SPaolo Bonzini/* fcfid */
227139c1837SPaolo BonziniGEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64);
228139c1837SPaolo Bonzini/* fcfids */
229139c1837SPaolo BonziniGEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206);
230139c1837SPaolo Bonzini/* fcfidu */
231139c1837SPaolo BonziniGEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
232139c1837SPaolo Bonzini/* fcfidus */
233139c1837SPaolo BonziniGEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
234139c1837SPaolo Bonzini/* fctid */
235139c1837SPaolo BonziniGEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64);
236139c1837SPaolo Bonzini/* fctidu */
237139c1837SPaolo BonziniGEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206);
238139c1837SPaolo Bonzini/* fctidz */
239139c1837SPaolo BonziniGEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64);
240139c1837SPaolo Bonzini/* fctidu */
241139c1837SPaolo BonziniGEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206);
242139c1837SPaolo Bonzini
243139c1837SPaolo Bonzini/* frin */
244139c1837SPaolo BonziniGEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
245139c1837SPaolo Bonzini/* friz */
246139c1837SPaolo BonziniGEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
247139c1837SPaolo Bonzini/* frip */
248139c1837SPaolo BonziniGEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
249139c1837SPaolo Bonzini/* frim */
250139c1837SPaolo BonziniGEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
251139c1837SPaolo Bonzini
252*177fcc06SChinmay Rathstatic bool trans_FTDIV(DisasContext *ctx, arg_X_bf *a)
253139c1837SPaolo Bonzini{
254*177fcc06SChinmay Rath    TCGv_i64 t0, t1;
255*177fcc06SChinmay Rath    REQUIRE_INSNS_FLAGS2(ctx, FP_TST_ISA206);
256*177fcc06SChinmay Rath    REQUIRE_FPU(ctx);
257139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
258139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
259*177fcc06SChinmay Rath    get_fpr(t0, a->ra);
260*177fcc06SChinmay Rath    get_fpr(t1, a->rb);
261*177fcc06SChinmay Rath    gen_helper_FTDIV(cpu_crf[a->bf], t0, t1);
262*177fcc06SChinmay Rath    return true;
263139c1837SPaolo Bonzini}
264139c1837SPaolo Bonzini
265*177fcc06SChinmay Rathstatic bool trans_FTSQRT(DisasContext *ctx, arg_X_bf_b *a)
266139c1837SPaolo Bonzini{
267139c1837SPaolo Bonzini    TCGv_i64 t0;
268*177fcc06SChinmay Rath    REQUIRE_INSNS_FLAGS2(ctx, FP_TST_ISA206);
269*177fcc06SChinmay Rath    REQUIRE_FPU(ctx);
270139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
271*177fcc06SChinmay Rath    get_fpr(t0, a->rb);
272*177fcc06SChinmay Rath    gen_helper_FTSQRT(cpu_crf[a->bf], t0);
273*177fcc06SChinmay Rath    return true;
274139c1837SPaolo Bonzini}
275139c1837SPaolo Bonzini
276139c1837SPaolo Bonzini/***                         Floating-Point compare                        ***/
277139c1837SPaolo Bonzini
278139c1837SPaolo Bonzini/* fcmpo */
279139c1837SPaolo Bonzinistatic void gen_fcmpo(DisasContext *ctx)
280139c1837SPaolo Bonzini{
281139c1837SPaolo Bonzini    TCGv_i32 crf;
282139c1837SPaolo Bonzini    TCGv_i64 t0;
283139c1837SPaolo Bonzini    TCGv_i64 t1;
284139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
285139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
286139c1837SPaolo Bonzini        return;
287139c1837SPaolo Bonzini    }
288139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
289139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
290139c1837SPaolo Bonzini    gen_reset_fpstatus();
29161d4bf33SRichard Henderson    crf = tcg_constant_i32(crfD(ctx->opcode));
292139c1837SPaolo Bonzini    get_fpr(t0, rA(ctx->opcode));
293139c1837SPaolo Bonzini    get_fpr(t1, rB(ctx->opcode));
294ad75a51eSRichard Henderson    gen_helper_fcmpo(tcg_env, t0, t1, crf);
295ad75a51eSRichard Henderson    gen_helper_float_check_status(tcg_env);
296139c1837SPaolo Bonzini}
297139c1837SPaolo Bonzini
298139c1837SPaolo Bonzini/* fcmpu */
299139c1837SPaolo Bonzinistatic void gen_fcmpu(DisasContext *ctx)
300139c1837SPaolo Bonzini{
301139c1837SPaolo Bonzini    TCGv_i32 crf;
302139c1837SPaolo Bonzini    TCGv_i64 t0;
303139c1837SPaolo Bonzini    TCGv_i64 t1;
304139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
305139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
306139c1837SPaolo Bonzini        return;
307139c1837SPaolo Bonzini    }
308139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
309139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
310139c1837SPaolo Bonzini    gen_reset_fpstatus();
31161d4bf33SRichard Henderson    crf = tcg_constant_i32(crfD(ctx->opcode));
312139c1837SPaolo Bonzini    get_fpr(t0, rA(ctx->opcode));
313139c1837SPaolo Bonzini    get_fpr(t1, rB(ctx->opcode));
314ad75a51eSRichard Henderson    gen_helper_fcmpu(tcg_env, t0, t1, crf);
315ad75a51eSRichard Henderson    gen_helper_float_check_status(tcg_env);
316139c1837SPaolo Bonzini}
317139c1837SPaolo Bonzini
318139c1837SPaolo Bonzini/***                         Floating-point move                           ***/
319139c1837SPaolo Bonzini/* fabs */
320139c1837SPaolo Bonzini/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
321139c1837SPaolo Bonzinistatic void gen_fabs(DisasContext *ctx)
322139c1837SPaolo Bonzini{
323139c1837SPaolo Bonzini    TCGv_i64 t0;
324139c1837SPaolo Bonzini    TCGv_i64 t1;
325139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
326139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
327139c1837SPaolo Bonzini        return;
328139c1837SPaolo Bonzini    }
329139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
330139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
331139c1837SPaolo Bonzini    get_fpr(t0, rB(ctx->opcode));
332139c1837SPaolo Bonzini    tcg_gen_andi_i64(t1, t0, ~(1ULL << 63));
333139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t1);
334139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode))) {
335139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);
336139c1837SPaolo Bonzini    }
337139c1837SPaolo Bonzini}
338139c1837SPaolo Bonzini
339139c1837SPaolo Bonzini/* fmr  - fmr. */
340139c1837SPaolo Bonzini/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
341139c1837SPaolo Bonzinistatic void gen_fmr(DisasContext *ctx)
342139c1837SPaolo Bonzini{
343139c1837SPaolo Bonzini    TCGv_i64 t0;
344139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
345139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
346139c1837SPaolo Bonzini        return;
347139c1837SPaolo Bonzini    }
348139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
349139c1837SPaolo Bonzini    get_fpr(t0, rB(ctx->opcode));
350139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t0);
351139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode))) {
352139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);
353139c1837SPaolo Bonzini    }
354139c1837SPaolo Bonzini}
355139c1837SPaolo Bonzini
356139c1837SPaolo Bonzini/* fnabs */
357139c1837SPaolo Bonzini/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
358139c1837SPaolo Bonzinistatic void gen_fnabs(DisasContext *ctx)
359139c1837SPaolo Bonzini{
360139c1837SPaolo Bonzini    TCGv_i64 t0;
361139c1837SPaolo Bonzini    TCGv_i64 t1;
362139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
363139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
364139c1837SPaolo Bonzini        return;
365139c1837SPaolo Bonzini    }
366139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
367139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
368139c1837SPaolo Bonzini    get_fpr(t0, rB(ctx->opcode));
369139c1837SPaolo Bonzini    tcg_gen_ori_i64(t1, t0, 1ULL << 63);
370139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t1);
371139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode))) {
372139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);
373139c1837SPaolo Bonzini    }
374139c1837SPaolo Bonzini}
375139c1837SPaolo Bonzini
376139c1837SPaolo Bonzini/* fneg */
377139c1837SPaolo Bonzini/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
378139c1837SPaolo Bonzinistatic void gen_fneg(DisasContext *ctx)
379139c1837SPaolo Bonzini{
380139c1837SPaolo Bonzini    TCGv_i64 t0;
381139c1837SPaolo Bonzini    TCGv_i64 t1;
382139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
383139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
384139c1837SPaolo Bonzini        return;
385139c1837SPaolo Bonzini    }
386139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
387139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
388139c1837SPaolo Bonzini    get_fpr(t0, rB(ctx->opcode));
389139c1837SPaolo Bonzini    tcg_gen_xori_i64(t1, t0, 1ULL << 63);
390139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t1);
391139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode))) {
392139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);
393139c1837SPaolo Bonzini    }
394139c1837SPaolo Bonzini}
395139c1837SPaolo Bonzini
396139c1837SPaolo Bonzini/* fcpsgn: PowerPC 2.05 specification */
397139c1837SPaolo Bonzini/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
398139c1837SPaolo Bonzinistatic void gen_fcpsgn(DisasContext *ctx)
399139c1837SPaolo Bonzini{
400139c1837SPaolo Bonzini    TCGv_i64 t0;
401139c1837SPaolo Bonzini    TCGv_i64 t1;
402139c1837SPaolo Bonzini    TCGv_i64 t2;
403139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
404139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
405139c1837SPaolo Bonzini        return;
406139c1837SPaolo Bonzini    }
407139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
408139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
409139c1837SPaolo Bonzini    t2 = tcg_temp_new_i64();
410139c1837SPaolo Bonzini    get_fpr(t0, rA(ctx->opcode));
411139c1837SPaolo Bonzini    get_fpr(t1, rB(ctx->opcode));
412139c1837SPaolo Bonzini    tcg_gen_deposit_i64(t2, t0, t1, 0, 63);
413139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t2);
414139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode))) {
415139c1837SPaolo Bonzini        gen_set_cr1_from_fpscr(ctx);
416139c1837SPaolo Bonzini    }
417139c1837SPaolo Bonzini}
418139c1837SPaolo Bonzini
419139c1837SPaolo Bonzinistatic void gen_fmrgew(DisasContext *ctx)
420139c1837SPaolo Bonzini{
421139c1837SPaolo Bonzini    TCGv_i64 b0;
422139c1837SPaolo Bonzini    TCGv_i64 t0;
423139c1837SPaolo Bonzini    TCGv_i64 t1;
424139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
425139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
426139c1837SPaolo Bonzini        return;
427139c1837SPaolo Bonzini    }
428139c1837SPaolo Bonzini    b0 = tcg_temp_new_i64();
429139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
430139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
431139c1837SPaolo Bonzini    get_fpr(t0, rB(ctx->opcode));
432139c1837SPaolo Bonzini    tcg_gen_shri_i64(b0, t0, 32);
433139c1837SPaolo Bonzini    get_fpr(t0, rA(ctx->opcode));
434139c1837SPaolo Bonzini    tcg_gen_deposit_i64(t1, t0, b0, 0, 32);
435139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t1);
436139c1837SPaolo Bonzini}
437139c1837SPaolo Bonzini
438139c1837SPaolo Bonzinistatic void gen_fmrgow(DisasContext *ctx)
439139c1837SPaolo Bonzini{
440139c1837SPaolo Bonzini    TCGv_i64 t0;
441139c1837SPaolo Bonzini    TCGv_i64 t1;
442139c1837SPaolo Bonzini    TCGv_i64 t2;
443139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
444139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
445139c1837SPaolo Bonzini        return;
446139c1837SPaolo Bonzini    }
447139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
448139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
449139c1837SPaolo Bonzini    t2 = tcg_temp_new_i64();
450139c1837SPaolo Bonzini    get_fpr(t0, rB(ctx->opcode));
451139c1837SPaolo Bonzini    get_fpr(t1, rA(ctx->opcode));
452139c1837SPaolo Bonzini    tcg_gen_deposit_i64(t2, t0, t1, 32, 32);
453139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t2);
454139c1837SPaolo Bonzini}
455139c1837SPaolo Bonzini
456139c1837SPaolo Bonzini/***                  Floating-Point status & ctrl register                ***/
457139c1837SPaolo Bonzini
458139c1837SPaolo Bonzini/* mcrfs */
459139c1837SPaolo Bonzinistatic void gen_mcrfs(DisasContext *ctx)
460139c1837SPaolo Bonzini{
461139c1837SPaolo Bonzini    TCGv tmp = tcg_temp_new();
462139c1837SPaolo Bonzini    TCGv_i32 tmask;
463139c1837SPaolo Bonzini    TCGv_i64 tnew_fpscr = tcg_temp_new_i64();
464139c1837SPaolo Bonzini    int bfa;
465139c1837SPaolo Bonzini    int nibble;
466139c1837SPaolo Bonzini    int shift;
467139c1837SPaolo Bonzini
468139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
469139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
470139c1837SPaolo Bonzini        return;
471139c1837SPaolo Bonzini    }
472139c1837SPaolo Bonzini    bfa = crfS(ctx->opcode);
473139c1837SPaolo Bonzini    nibble = 7 - bfa;
474139c1837SPaolo Bonzini    shift = 4 * nibble;
475139c1837SPaolo Bonzini    tcg_gen_shri_tl(tmp, cpu_fpscr, shift);
476139c1837SPaolo Bonzini    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
477139c1837SPaolo Bonzini    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],
478139c1837SPaolo Bonzini                     0xf);
479139c1837SPaolo Bonzini    tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
480139c1837SPaolo Bonzini    /* Only the exception bits (including FX) should be cleared if read */
481139c1837SPaolo Bonzini    tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr,
482139c1837SPaolo Bonzini                     ~((0xF << shift) & FP_EX_CLEAR_BITS));
483139c1837SPaolo Bonzini    /* FEX and VX need to be updated, so don't set fpscr directly */
48461d4bf33SRichard Henderson    tmask = tcg_constant_i32(1 << nibble);
485ad75a51eSRichard Henderson    gen_helper_store_fpscr(tcg_env, tnew_fpscr, tmask);
486139c1837SPaolo Bonzini}
487139c1837SPaolo Bonzini
488bf8adfd8SVíctor Colombostatic TCGv_i64 place_from_fpscr(int rt, uint64_t mask)
489139c1837SPaolo Bonzini{
490bf8adfd8SVíctor Colombo    TCGv_i64 fpscr = tcg_temp_new_i64();
491bf8adfd8SVíctor Colombo    TCGv_i64 fpscr_masked = tcg_temp_new_i64();
492139c1837SPaolo Bonzini
493bf8adfd8SVíctor Colombo    tcg_gen_extu_tl_i64(fpscr, cpu_fpscr);
494bf8adfd8SVíctor Colombo    tcg_gen_andi_i64(fpscr_masked, fpscr, mask);
495bf8adfd8SVíctor Colombo    set_fpr(rt, fpscr_masked);
496139c1837SPaolo Bonzini
497bf8adfd8SVíctor Colombo    return fpscr;
498139c1837SPaolo Bonzini}
499139c1837SPaolo Bonzini
500bf8adfd8SVíctor Colombostatic void store_fpscr_masked(TCGv_i64 fpscr, uint64_t clear_mask,
501bf8adfd8SVíctor Colombo                               TCGv_i64 set_mask, uint32_t store_mask)
502139c1837SPaolo Bonzini{
503bf8adfd8SVíctor Colombo    TCGv_i64 fpscr_masked = tcg_temp_new_i64();
504bf8adfd8SVíctor Colombo    TCGv_i32 st_mask = tcg_constant_i32(store_mask);
505139c1837SPaolo Bonzini
506bf8adfd8SVíctor Colombo    tcg_gen_andi_i64(fpscr_masked, fpscr, ~clear_mask);
507bf8adfd8SVíctor Colombo    tcg_gen_or_i64(fpscr_masked, fpscr_masked, set_mask);
508ad75a51eSRichard Henderson    gen_helper_store_fpscr(tcg_env, fpscr_masked, st_mask);
509139c1837SPaolo Bonzini}
510139c1837SPaolo Bonzini
5115260ecffSRichard Purdiestatic bool trans_MFFS_ISA207(DisasContext *ctx, arg_X_t_rc *a)
5125260ecffSRichard Purdie{
5135260ecffSRichard Purdie    if (!(ctx->insns_flags2 & PPC2_ISA300)) {
5145260ecffSRichard Purdie        /*
5155260ecffSRichard Purdie         * Before Power ISA v3.0, MFFS bits 11~15 were reserved, any instruction
5165260ecffSRichard Purdie         * with OPCD=63 and XO=583 should be decoded as MFFS.
5175260ecffSRichard Purdie         */
5185260ecffSRichard Purdie        return trans_MFFS(ctx, a);
5195260ecffSRichard Purdie    }
5205260ecffSRichard Purdie    /*
5215260ecffSRichard Purdie     * For Power ISA v3.0+, return false and let the pattern group
5225260ecffSRichard Purdie     * select the correct instruction.
5235260ecffSRichard Purdie     */
5245260ecffSRichard Purdie    return false;
5255260ecffSRichard Purdie}
5265260ecffSRichard Purdie
527f80d04d5SVíctor Colombostatic bool trans_MFFS(DisasContext *ctx, arg_X_t_rc *a)
528f80d04d5SVíctor Colombo{
529f80d04d5SVíctor Colombo    REQUIRE_FPU(ctx);
530f80d04d5SVíctor Colombo
531f80d04d5SVíctor Colombo    gen_reset_fpstatus();
532571f8507SRichard Henderson    place_from_fpscr(a->rt, UINT64_MAX);
533f80d04d5SVíctor Colombo    if (a->rc) {
534f80d04d5SVíctor Colombo        gen_set_cr1_from_fpscr(ctx);
535f80d04d5SVíctor Colombo    }
536f80d04d5SVíctor Colombo    return true;
537f80d04d5SVíctor Colombo}
538f80d04d5SVíctor Colombo
539394c2e2fSVíctor Colombostatic bool trans_MFFSCE(DisasContext *ctx, arg_X_t *a)
540394c2e2fSVíctor Colombo{
541394c2e2fSVíctor Colombo    TCGv_i64 fpscr;
542394c2e2fSVíctor Colombo
543394c2e2fSVíctor Colombo    REQUIRE_FPU(ctx);
544394c2e2fSVíctor Colombo
545394c2e2fSVíctor Colombo    gen_reset_fpstatus();
546394c2e2fSVíctor Colombo    fpscr = place_from_fpscr(a->rt, UINT64_MAX);
547394c2e2fSVíctor Colombo    store_fpscr_masked(fpscr, FP_ENABLES, tcg_constant_i64(0), 0x0003);
548394c2e2fSVíctor Colombo    return true;
549394c2e2fSVíctor Colombo}
550394c2e2fSVíctor Colombo
551bf8adfd8SVíctor Colombostatic bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a)
552bf8adfd8SVíctor Colombo{
553bf8adfd8SVíctor Colombo    TCGv_i64 t1, fpscr;
554bf8adfd8SVíctor Colombo
555bf8adfd8SVíctor Colombo    REQUIRE_FPU(ctx);
556139c1837SPaolo Bonzini
557139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
558bf8adfd8SVíctor Colombo    get_fpr(t1, a->rb);
559139c1837SPaolo Bonzini    tcg_gen_andi_i64(t1, t1, FP_RN);
560139c1837SPaolo Bonzini
561bf8adfd8SVíctor Colombo    gen_reset_fpstatus();
562bf8adfd8SVíctor Colombo    fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
563bf8adfd8SVíctor Colombo    store_fpscr_masked(fpscr, FP_RN, t1, 0x0001);
564bf8adfd8SVíctor Colombo    return true;
565139c1837SPaolo Bonzini}
566139c1837SPaolo Bonzini
5676cef305fSVíctor Colombostatic bool trans_MFFSCDRN(DisasContext *ctx, arg_X_tb *a)
5686cef305fSVíctor Colombo{
5696cef305fSVíctor Colombo    TCGv_i64 t1, fpscr;
5706cef305fSVíctor Colombo
5716cef305fSVíctor Colombo    REQUIRE_FPU(ctx);
5726cef305fSVíctor Colombo
5736cef305fSVíctor Colombo    t1 = tcg_temp_new_i64();
5746cef305fSVíctor Colombo    get_fpr(t1, a->rb);
5756cef305fSVíctor Colombo    tcg_gen_andi_i64(t1, t1, FP_DRN);
5766cef305fSVíctor Colombo
5776cef305fSVíctor Colombo    gen_reset_fpstatus();
5786cef305fSVíctor Colombo    fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
5796cef305fSVíctor Colombo    store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100);
5806cef305fSVíctor Colombo    return true;
5816cef305fSVíctor Colombo}
5826cef305fSVíctor Colombo
583bf8adfd8SVíctor Colombostatic bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 *a)
584139c1837SPaolo Bonzini{
585bf8adfd8SVíctor Colombo    TCGv_i64 t1, fpscr;
586139c1837SPaolo Bonzini
587bf8adfd8SVíctor Colombo    REQUIRE_FPU(ctx);
588139c1837SPaolo Bonzini
589bf8adfd8SVíctor Colombo    t1 = tcg_temp_new_i64();
590bf8adfd8SVíctor Colombo    tcg_gen_movi_i64(t1, a->imm);
591139c1837SPaolo Bonzini
592bf8adfd8SVíctor Colombo    gen_reset_fpstatus();
593bf8adfd8SVíctor Colombo    fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
594bf8adfd8SVíctor Colombo    store_fpscr_masked(fpscr, FP_RN, t1, 0x0001);
595bf8adfd8SVíctor Colombo    return true;
596139c1837SPaolo Bonzini}
597139c1837SPaolo Bonzini
5986cef305fSVíctor Colombostatic bool trans_MFFSCDRNI(DisasContext *ctx, arg_X_imm3 *a)
5996cef305fSVíctor Colombo{
6006cef305fSVíctor Colombo    TCGv_i64 t1, fpscr;
6016cef305fSVíctor Colombo
6026cef305fSVíctor Colombo    REQUIRE_FPU(ctx);
6036cef305fSVíctor Colombo
6046cef305fSVíctor Colombo    t1 = tcg_temp_new_i64();
6056cef305fSVíctor Colombo    tcg_gen_movi_i64(t1, (uint64_t)a->imm << FPSCR_DRN0);
6066cef305fSVíctor Colombo
6076cef305fSVíctor Colombo    gen_reset_fpstatus();
6086cef305fSVíctor Colombo    fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
6096cef305fSVíctor Colombo    store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100);
6106cef305fSVíctor Colombo    return true;
6116cef305fSVíctor Colombo}
6126cef305fSVíctor Colombo
6133e5bce70SVíctor Colombostatic bool trans_MFFSL(DisasContext *ctx, arg_X_t *a)
6143e5bce70SVíctor Colombo{
6153e5bce70SVíctor Colombo    REQUIRE_FPU(ctx);
6163e5bce70SVíctor Colombo
6173e5bce70SVíctor Colombo    gen_reset_fpstatus();
618571f8507SRichard Henderson    place_from_fpscr(a->rt, FP_DRN | FP_STATUS | FP_ENABLES | FP_NI | FP_RN);
6193e5bce70SVíctor Colombo    return true;
6203e5bce70SVíctor Colombo}
6213e5bce70SVíctor Colombo
622139c1837SPaolo Bonzini/* mtfsb0 */
623139c1837SPaolo Bonzinistatic void gen_mtfsb0(DisasContext *ctx)
624139c1837SPaolo Bonzini{
625139c1837SPaolo Bonzini    uint8_t crb;
626139c1837SPaolo Bonzini
627139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
628139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
629139c1837SPaolo Bonzini        return;
630139c1837SPaolo Bonzini    }
631139c1837SPaolo Bonzini    crb = 31 - crbD(ctx->opcode);
632139c1837SPaolo Bonzini    gen_reset_fpstatus();
633139c1837SPaolo Bonzini    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
634ad75a51eSRichard Henderson        gen_helper_fpscr_clrbit(tcg_env, tcg_constant_i32(crb));
635139c1837SPaolo Bonzini    }
636139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode) != 0)) {
637139c1837SPaolo Bonzini        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
638139c1837SPaolo Bonzini        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
639139c1837SPaolo Bonzini    }
640139c1837SPaolo Bonzini}
641139c1837SPaolo Bonzini
642139c1837SPaolo Bonzini/* mtfsb1 */
643139c1837SPaolo Bonzinistatic void gen_mtfsb1(DisasContext *ctx)
644139c1837SPaolo Bonzini{
645139c1837SPaolo Bonzini    uint8_t crb;
646139c1837SPaolo Bonzini
647139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
648139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
649139c1837SPaolo Bonzini        return;
650139c1837SPaolo Bonzini    }
651139c1837SPaolo Bonzini    crb = 31 - crbD(ctx->opcode);
652139c1837SPaolo Bonzini    /* XXX: we pretend we can only do IEEE floating-point computations */
653139c1837SPaolo Bonzini    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
654ad75a51eSRichard Henderson        gen_helper_fpscr_setbit(tcg_env, tcg_constant_i32(crb));
655139c1837SPaolo Bonzini    }
656139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode) != 0)) {
657139c1837SPaolo Bonzini        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
658139c1837SPaolo Bonzini        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
659139c1837SPaolo Bonzini    }
660139c1837SPaolo Bonzini    /* We can raise a deferred exception */
661ad75a51eSRichard Henderson    gen_helper_fpscr_check_status(tcg_env);
662139c1837SPaolo Bonzini}
663139c1837SPaolo Bonzini
664139c1837SPaolo Bonzini/* mtfsf */
665139c1837SPaolo Bonzinistatic void gen_mtfsf(DisasContext *ctx)
666139c1837SPaolo Bonzini{
667139c1837SPaolo Bonzini    TCGv_i32 t0;
668139c1837SPaolo Bonzini    TCGv_i64 t1;
669139c1837SPaolo Bonzini    int flm, l, w;
670139c1837SPaolo Bonzini
671139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
672139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
673139c1837SPaolo Bonzini        return;
674139c1837SPaolo Bonzini    }
675139c1837SPaolo Bonzini    flm = FPFLM(ctx->opcode);
676139c1837SPaolo Bonzini    l = FPL(ctx->opcode);
677139c1837SPaolo Bonzini    w = FPW(ctx->opcode);
678139c1837SPaolo Bonzini    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
679139c1837SPaolo Bonzini        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
680139c1837SPaolo Bonzini        return;
681139c1837SPaolo Bonzini    }
68261d4bf33SRichard Henderson    if (!l) {
68361d4bf33SRichard Henderson        t0 = tcg_constant_i32(flm << (w * 8));
68461d4bf33SRichard Henderson    } else if (ctx->insns_flags2 & PPC2_ISA205) {
68561d4bf33SRichard Henderson        t0 = tcg_constant_i32(0xffff);
686139c1837SPaolo Bonzini    } else {
68761d4bf33SRichard Henderson        t0 = tcg_constant_i32(0xff);
688139c1837SPaolo Bonzini    }
689139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
690139c1837SPaolo Bonzini    get_fpr(t1, rB(ctx->opcode));
691ad75a51eSRichard Henderson    gen_helper_store_fpscr(tcg_env, t1, t0);
692139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode) != 0)) {
693139c1837SPaolo Bonzini        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
694139c1837SPaolo Bonzini        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
695139c1837SPaolo Bonzini    }
696139c1837SPaolo Bonzini    /* We can raise a deferred exception */
697ad75a51eSRichard Henderson    gen_helper_fpscr_check_status(tcg_env);
698139c1837SPaolo Bonzini}
699139c1837SPaolo Bonzini
700139c1837SPaolo Bonzini/* mtfsfi */
701139c1837SPaolo Bonzinistatic void gen_mtfsfi(DisasContext *ctx)
702139c1837SPaolo Bonzini{
703139c1837SPaolo Bonzini    int bf, sh, w;
704139c1837SPaolo Bonzini    TCGv_i64 t0;
705139c1837SPaolo Bonzini    TCGv_i32 t1;
706139c1837SPaolo Bonzini
707139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
708139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
709139c1837SPaolo Bonzini        return;
710139c1837SPaolo Bonzini    }
711139c1837SPaolo Bonzini    w = FPW(ctx->opcode);
712139c1837SPaolo Bonzini    bf = FPBF(ctx->opcode);
713139c1837SPaolo Bonzini    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
714139c1837SPaolo Bonzini        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
715139c1837SPaolo Bonzini        return;
716139c1837SPaolo Bonzini    }
717139c1837SPaolo Bonzini    sh = (8 * w) + 7 - bf;
71861d4bf33SRichard Henderson    t0 = tcg_constant_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
71961d4bf33SRichard Henderson    t1 = tcg_constant_i32(1 << sh);
720ad75a51eSRichard Henderson    gen_helper_store_fpscr(tcg_env, t0, t1);
721139c1837SPaolo Bonzini    if (unlikely(Rc(ctx->opcode) != 0)) {
722139c1837SPaolo Bonzini        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
723139c1837SPaolo Bonzini        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
724139c1837SPaolo Bonzini    }
725139c1837SPaolo Bonzini    /* We can raise a deferred exception */
726ad75a51eSRichard Henderson    gen_helper_fpscr_check_status(tcg_env);
727139c1837SPaolo Bonzini}
728139c1837SPaolo Bonzini
729139c1837SPaolo Bonzinistatic void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr)
730139c1837SPaolo Bonzini{
731139c1837SPaolo Bonzini    TCGv_i32 tmp = tcg_temp_new_i32();
732139c1837SPaolo Bonzini    tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
733139c1837SPaolo Bonzini    gen_helper_todouble(dest, tmp);
734139c1837SPaolo Bonzini}
735139c1837SPaolo Bonzini
736139c1837SPaolo Bonzini/* lfdepx (external PID lfdx) */
737139c1837SPaolo Bonzinistatic void gen_lfdepx(DisasContext *ctx)
738139c1837SPaolo Bonzini{
739139c1837SPaolo Bonzini    TCGv EA;
740139c1837SPaolo Bonzini    TCGv_i64 t0;
7419f0cf041SMatheus Ferst    CHK_SV(ctx);
742139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
743139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
744139c1837SPaolo Bonzini        return;
745139c1837SPaolo Bonzini    }
746139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
747139c1837SPaolo Bonzini    EA = tcg_temp_new();
748139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
749139c1837SPaolo Bonzini    gen_addr_reg_index(ctx, EA);
750fc313c64SFrédéric Pétrot    tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UQ));
751139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t0);
752139c1837SPaolo Bonzini}
753139c1837SPaolo Bonzini
754139c1837SPaolo Bonzini/* lfdp */
755139c1837SPaolo Bonzinistatic void gen_lfdp(DisasContext *ctx)
756139c1837SPaolo Bonzini{
757139c1837SPaolo Bonzini    TCGv EA;
758139c1837SPaolo Bonzini    TCGv_i64 t0;
759139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
760139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
761139c1837SPaolo Bonzini        return;
762139c1837SPaolo Bonzini    }
763139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
764139c1837SPaolo Bonzini    EA = tcg_temp_new();
765139c1837SPaolo Bonzini    gen_addr_imm_index(ctx, EA, 0);
766139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
767139c1837SPaolo Bonzini    /*
768139c1837SPaolo Bonzini     * We only need to swap high and low halves. gen_qemu_ld64_i64
769139c1837SPaolo Bonzini     * does necessary 64-bit byteswap already.
770139c1837SPaolo Bonzini     */
771139c1837SPaolo Bonzini    if (unlikely(ctx->le_mode)) {
772139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
773139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode) + 1, t0);
774139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
775139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
776139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode), t0);
777139c1837SPaolo Bonzini    } else {
778139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
779139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode), t0);
780139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
781139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
782139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode) + 1, t0);
783139c1837SPaolo Bonzini    }
784139c1837SPaolo Bonzini}
785139c1837SPaolo Bonzini
786139c1837SPaolo Bonzini/* lfdpx */
787139c1837SPaolo Bonzinistatic void gen_lfdpx(DisasContext *ctx)
788139c1837SPaolo Bonzini{
789139c1837SPaolo Bonzini    TCGv EA;
790139c1837SPaolo Bonzini    TCGv_i64 t0;
791139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
792139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
793139c1837SPaolo Bonzini        return;
794139c1837SPaolo Bonzini    }
795139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
796139c1837SPaolo Bonzini    EA = tcg_temp_new();
797139c1837SPaolo Bonzini    gen_addr_reg_index(ctx, EA);
798139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
799139c1837SPaolo Bonzini    /*
800139c1837SPaolo Bonzini     * We only need to swap high and low halves. gen_qemu_ld64_i64
801139c1837SPaolo Bonzini     * does necessary 64-bit byteswap already.
802139c1837SPaolo Bonzini     */
803139c1837SPaolo Bonzini    if (unlikely(ctx->le_mode)) {
804139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
805139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode) + 1, t0);
806139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
807139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
808139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode), t0);
809139c1837SPaolo Bonzini    } else {
810139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
811139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode), t0);
812139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
813139c1837SPaolo Bonzini        gen_qemu_ld64_i64(ctx, t0, EA);
814139c1837SPaolo Bonzini        set_fpr(rD(ctx->opcode) + 1, t0);
815139c1837SPaolo Bonzini    }
816139c1837SPaolo Bonzini}
817139c1837SPaolo Bonzini
818139c1837SPaolo Bonzini/* lfiwax */
819139c1837SPaolo Bonzinistatic void gen_lfiwax(DisasContext *ctx)
820139c1837SPaolo Bonzini{
821139c1837SPaolo Bonzini    TCGv EA;
822139c1837SPaolo Bonzini    TCGv t0;
823139c1837SPaolo Bonzini    TCGv_i64 t1;
824139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
825139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
826139c1837SPaolo Bonzini        return;
827139c1837SPaolo Bonzini    }
828139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
829139c1837SPaolo Bonzini    EA = tcg_temp_new();
830139c1837SPaolo Bonzini    t0 = tcg_temp_new();
831139c1837SPaolo Bonzini    t1 = tcg_temp_new_i64();
832139c1837SPaolo Bonzini    gen_addr_reg_index(ctx, EA);
833139c1837SPaolo Bonzini    gen_qemu_ld32s(ctx, t0, EA);
834139c1837SPaolo Bonzini    tcg_gen_ext_tl_i64(t1, t0);
835139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t1);
836139c1837SPaolo Bonzini}
837139c1837SPaolo Bonzini
838139c1837SPaolo Bonzini/* lfiwzx */
839139c1837SPaolo Bonzinistatic void gen_lfiwzx(DisasContext *ctx)
840139c1837SPaolo Bonzini{
841139c1837SPaolo Bonzini    TCGv EA;
842139c1837SPaolo Bonzini    TCGv_i64 t0;
843139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
844139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
845139c1837SPaolo Bonzini        return;
846139c1837SPaolo Bonzini    }
847139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
848139c1837SPaolo Bonzini    EA = tcg_temp_new();
849139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
850139c1837SPaolo Bonzini    gen_addr_reg_index(ctx, EA);
851139c1837SPaolo Bonzini    gen_qemu_ld32u_i64(ctx, t0, EA);
852139c1837SPaolo Bonzini    set_fpr(rD(ctx->opcode), t0);
853139c1837SPaolo Bonzini}
854139c1837SPaolo Bonzini
855139c1837SPaolo Bonzini#define GEN_STXF(name, stop, opc2, opc3, type)                                \
856139c1837SPaolo Bonzinistatic void glue(gen_, name##x)(DisasContext *ctx)                            \
857139c1837SPaolo Bonzini{                                                                             \
858139c1837SPaolo Bonzini    TCGv EA;                                                                  \
859139c1837SPaolo Bonzini    TCGv_i64 t0;                                                              \
860139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {                                        \
861139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
862139c1837SPaolo Bonzini        return;                                                               \
863139c1837SPaolo Bonzini    }                                                                         \
864139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
865139c1837SPaolo Bonzini    EA = tcg_temp_new();                                                      \
866139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();                                                  \
867139c1837SPaolo Bonzini    gen_addr_reg_index(ctx, EA);                                              \
868139c1837SPaolo Bonzini    get_fpr(t0, rS(ctx->opcode));                                             \
869139c1837SPaolo Bonzini    gen_qemu_##stop(ctx, t0, EA);                                             \
870139c1837SPaolo Bonzini}
871139c1837SPaolo Bonzini
872139c1837SPaolo Bonzinistatic void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr)
873139c1837SPaolo Bonzini{
874139c1837SPaolo Bonzini    TCGv_i32 tmp = tcg_temp_new_i32();
875139c1837SPaolo Bonzini    gen_helper_tosingle(tmp, src);
876139c1837SPaolo Bonzini    tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
877139c1837SPaolo Bonzini}
878139c1837SPaolo Bonzini
879139c1837SPaolo Bonzini/* stfdepx (external PID lfdx) */
880139c1837SPaolo Bonzinistatic void gen_stfdepx(DisasContext *ctx)
881139c1837SPaolo Bonzini{
882139c1837SPaolo Bonzini    TCGv EA;
883139c1837SPaolo Bonzini    TCGv_i64 t0;
8849f0cf041SMatheus Ferst    CHK_SV(ctx);
885139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
886139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
887139c1837SPaolo Bonzini        return;
888139c1837SPaolo Bonzini    }
889139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
890139c1837SPaolo Bonzini    EA = tcg_temp_new();
891139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
892139c1837SPaolo Bonzini    gen_addr_reg_index(ctx, EA);
893139c1837SPaolo Bonzini    get_fpr(t0, rD(ctx->opcode));
894fc313c64SFrédéric Pétrot    tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_UQ));
895139c1837SPaolo Bonzini}
896139c1837SPaolo Bonzini
897139c1837SPaolo Bonzini/* stfdp */
898139c1837SPaolo Bonzinistatic void gen_stfdp(DisasContext *ctx)
899139c1837SPaolo Bonzini{
900139c1837SPaolo Bonzini    TCGv EA;
901139c1837SPaolo Bonzini    TCGv_i64 t0;
902139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
903139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
904139c1837SPaolo Bonzini        return;
905139c1837SPaolo Bonzini    }
906139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
907139c1837SPaolo Bonzini    EA = tcg_temp_new();
908139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
909139c1837SPaolo Bonzini    gen_addr_imm_index(ctx, EA, 0);
910139c1837SPaolo Bonzini    /*
911139c1837SPaolo Bonzini     * We only need to swap high and low halves. gen_qemu_st64_i64
912139c1837SPaolo Bonzini     * does necessary 64-bit byteswap already.
913139c1837SPaolo Bonzini     */
914139c1837SPaolo Bonzini    if (unlikely(ctx->le_mode)) {
915139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode) + 1);
916139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
917139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
918139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode));
919139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
920139c1837SPaolo Bonzini    } else {
921139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode));
922139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
923139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
924139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode) + 1);
925139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
926139c1837SPaolo Bonzini    }
927139c1837SPaolo Bonzini}
928139c1837SPaolo Bonzini
929139c1837SPaolo Bonzini/* stfdpx */
930139c1837SPaolo Bonzinistatic void gen_stfdpx(DisasContext *ctx)
931139c1837SPaolo Bonzini{
932139c1837SPaolo Bonzini    TCGv EA;
933139c1837SPaolo Bonzini    TCGv_i64 t0;
934139c1837SPaolo Bonzini    if (unlikely(!ctx->fpu_enabled)) {
935139c1837SPaolo Bonzini        gen_exception(ctx, POWERPC_EXCP_FPU);
936139c1837SPaolo Bonzini        return;
937139c1837SPaolo Bonzini    }
938139c1837SPaolo Bonzini    gen_set_access_type(ctx, ACCESS_FLOAT);
939139c1837SPaolo Bonzini    EA = tcg_temp_new();
940139c1837SPaolo Bonzini    t0 = tcg_temp_new_i64();
941139c1837SPaolo Bonzini    gen_addr_reg_index(ctx, EA);
942139c1837SPaolo Bonzini    /*
943139c1837SPaolo Bonzini     * We only need to swap high and low halves. gen_qemu_st64_i64
944139c1837SPaolo Bonzini     * does necessary 64-bit byteswap already.
945139c1837SPaolo Bonzini     */
946139c1837SPaolo Bonzini    if (unlikely(ctx->le_mode)) {
947139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode) + 1);
948139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
949139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
950139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode));
951139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
952139c1837SPaolo Bonzini    } else {
953139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode));
954139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
955139c1837SPaolo Bonzini        tcg_gen_addi_tl(EA, EA, 8);
956139c1837SPaolo Bonzini        get_fpr(t0, rD(ctx->opcode) + 1);
957139c1837SPaolo Bonzini        gen_qemu_st64_i64(ctx, t0, EA);
958139c1837SPaolo Bonzini    }
959139c1837SPaolo Bonzini}
960139c1837SPaolo Bonzini
961139c1837SPaolo Bonzini/* Optional: */
962139c1837SPaolo Bonzinistatic inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
963139c1837SPaolo Bonzini{
964139c1837SPaolo Bonzini    TCGv t0 = tcg_temp_new();
965139c1837SPaolo Bonzini    tcg_gen_trunc_i64_tl(t0, arg1),
966139c1837SPaolo Bonzini    gen_qemu_st32(ctx, t0, arg2);
967139c1837SPaolo Bonzini}
968139c1837SPaolo Bonzini/* stfiwx */
969139c1837SPaolo BonziniGEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
970139c1837SPaolo Bonzini
971fbd2e60eSFernando Eckhardt Valle/*            Floating-point Load/Store Instructions                         */
972fbd2e60eSFernando Eckhardt Vallestatic bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ,
973fbd2e60eSFernando Eckhardt Valle                      bool update, bool store, bool single)
974fbd2e60eSFernando Eckhardt Valle{
975fbd2e60eSFernando Eckhardt Valle    TCGv ea;
976fbd2e60eSFernando Eckhardt Valle    TCGv_i64 t0;
977fbd2e60eSFernando Eckhardt Valle    REQUIRE_INSNS_FLAGS(ctx, FLOAT);
978fbd2e60eSFernando Eckhardt Valle    REQUIRE_FPU(ctx);
979fbd2e60eSFernando Eckhardt Valle    if (update && ra == 0) {
980fbd2e60eSFernando Eckhardt Valle        gen_invalid(ctx);
981fbd2e60eSFernando Eckhardt Valle        return true;
982fbd2e60eSFernando Eckhardt Valle    }
983fbd2e60eSFernando Eckhardt Valle    gen_set_access_type(ctx, ACCESS_FLOAT);
984fbd2e60eSFernando Eckhardt Valle    t0 = tcg_temp_new_i64();
985fbd2e60eSFernando Eckhardt Valle    ea = do_ea_calc(ctx, ra, displ);
986fbd2e60eSFernando Eckhardt Valle    if (store) {
987fbd2e60eSFernando Eckhardt Valle        get_fpr(t0, rt);
988fbd2e60eSFernando Eckhardt Valle        if (single) {
989fbd2e60eSFernando Eckhardt Valle            gen_qemu_st32fs(ctx, t0, ea);
990fbd2e60eSFernando Eckhardt Valle        } else {
991fbd2e60eSFernando Eckhardt Valle            gen_qemu_st64_i64(ctx, t0, ea);
992fbd2e60eSFernando Eckhardt Valle        }
993fbd2e60eSFernando Eckhardt Valle    } else {
994fbd2e60eSFernando Eckhardt Valle        if (single) {
995fbd2e60eSFernando Eckhardt Valle            gen_qemu_ld32fs(ctx, t0, ea);
996fbd2e60eSFernando Eckhardt Valle        } else {
997fbd2e60eSFernando Eckhardt Valle            gen_qemu_ld64_i64(ctx, t0, ea);
998fbd2e60eSFernando Eckhardt Valle        }
999fbd2e60eSFernando Eckhardt Valle        set_fpr(rt, t0);
1000fbd2e60eSFernando Eckhardt Valle    }
1001fbd2e60eSFernando Eckhardt Valle    if (update) {
10023620328fSMatheus Ferst        tcg_gen_mov_tl(cpu_gpr[ra], ea);
1003fbd2e60eSFernando Eckhardt Valle    }
1004fbd2e60eSFernando Eckhardt Valle    return true;
1005fbd2e60eSFernando Eckhardt Valle}
1006fbd2e60eSFernando Eckhardt Valle
1007fbd2e60eSFernando Eckhardt Vallestatic bool do_lsfp_D(DisasContext *ctx, arg_D *a, bool update, bool store,
1008fbd2e60eSFernando Eckhardt Valle                      bool single)
1009fbd2e60eSFernando Eckhardt Valle{
1010fbd2e60eSFernando Eckhardt Valle    return do_lsfpsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store,
1011fbd2e60eSFernando Eckhardt Valle                     single);
1012fbd2e60eSFernando Eckhardt Valle}
1013fbd2e60eSFernando Eckhardt Valle
1014dcb4e5b7SFernando Eckhardt Vallestatic bool do_lsfp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
1015dcb4e5b7SFernando Eckhardt Valle                          bool store, bool single)
1016dcb4e5b7SFernando Eckhardt Valle{
1017dcb4e5b7SFernando Eckhardt Valle    arg_D d;
1018dcb4e5b7SFernando Eckhardt Valle    if (!resolve_PLS_D(ctx, &d, a)) {
1019dcb4e5b7SFernando Eckhardt Valle        return true;
1020dcb4e5b7SFernando Eckhardt Valle    }
1021dcb4e5b7SFernando Eckhardt Valle    return do_lsfp_D(ctx, &d, update, store, single);
1022dcb4e5b7SFernando Eckhardt Valle}
1023dcb4e5b7SFernando Eckhardt Valle
1024fbd2e60eSFernando Eckhardt Vallestatic bool do_lsfp_X(DisasContext *ctx, arg_X *a, bool update,
1025fbd2e60eSFernando Eckhardt Valle                      bool store, bool single)
1026fbd2e60eSFernando Eckhardt Valle{
1027fbd2e60eSFernando Eckhardt Valle    return do_lsfpsd(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, single);
1028fbd2e60eSFernando Eckhardt Valle}
1029fbd2e60eSFernando Eckhardt Valle
1030fbd2e60eSFernando Eckhardt ValleTRANS(LFS, do_lsfp_D, false, false, true)
1031fbd2e60eSFernando Eckhardt ValleTRANS(LFSU, do_lsfp_D, true, false, true)
1032fbd2e60eSFernando Eckhardt ValleTRANS(LFSX, do_lsfp_X, false, false, true)
1033fbd2e60eSFernando Eckhardt ValleTRANS(LFSUX, do_lsfp_X, true, false, true)
1034dcb4e5b7SFernando Eckhardt ValleTRANS(PLFS, do_lsfp_PLS_D, false, false, true)
1035fbd2e60eSFernando Eckhardt Valle
1036fbd2e60eSFernando Eckhardt ValleTRANS(LFD, do_lsfp_D, false, false, false)
1037fbd2e60eSFernando Eckhardt ValleTRANS(LFDU, do_lsfp_D, true, false, false)
1038fbd2e60eSFernando Eckhardt ValleTRANS(LFDX, do_lsfp_X, false, false, false)
1039fbd2e60eSFernando Eckhardt ValleTRANS(LFDUX, do_lsfp_X, true, false, false)
1040dcb4e5b7SFernando Eckhardt ValleTRANS(PLFD, do_lsfp_PLS_D, false, false, false)
1041fbd2e60eSFernando Eckhardt Valle
1042fbd2e60eSFernando Eckhardt ValleTRANS(STFS, do_lsfp_D, false, true, true)
1043fbd2e60eSFernando Eckhardt ValleTRANS(STFSU, do_lsfp_D, true, true, true)
1044fbd2e60eSFernando Eckhardt ValleTRANS(STFSX, do_lsfp_X, false, true, true)
1045fbd2e60eSFernando Eckhardt ValleTRANS(STFSUX, do_lsfp_X, true, true, true)
1046dcb4e5b7SFernando Eckhardt ValleTRANS(PSTFS, do_lsfp_PLS_D, false, true, true)
1047fbd2e60eSFernando Eckhardt Valle
1048fbd2e60eSFernando Eckhardt ValleTRANS(STFD, do_lsfp_D, false, true, false)
1049fbd2e60eSFernando Eckhardt ValleTRANS(STFDU, do_lsfp_D, true, true, false)
1050fbd2e60eSFernando Eckhardt ValleTRANS(STFDX, do_lsfp_X, false, true, false)
1051fbd2e60eSFernando Eckhardt ValleTRANS(STFDUX, do_lsfp_X, true, true, false)
1052dcb4e5b7SFernando Eckhardt ValleTRANS(PSTFD, do_lsfp_PLS_D, false, true, false)
1053fbd2e60eSFernando Eckhardt Valle
1054139c1837SPaolo Bonzini#undef GEN_FLOAT_B
1055139c1837SPaolo Bonzini
1056139c1837SPaolo Bonzini#undef GEN_LDF
1057139c1837SPaolo Bonzini#undef GEN_LDUF
1058139c1837SPaolo Bonzini#undef GEN_LDUXF
1059139c1837SPaolo Bonzini#undef GEN_LDXF
1060139c1837SPaolo Bonzini#undef GEN_LDFS
1061139c1837SPaolo Bonzini
1062139c1837SPaolo Bonzini#undef GEN_STF
1063139c1837SPaolo Bonzini#undef GEN_STUF
1064139c1837SPaolo Bonzini#undef GEN_STUXF
1065139c1837SPaolo Bonzini#undef GEN_STXF
1066139c1837SPaolo Bonzini#undef GEN_STFS
1067