target/ppc: Add helpers for fmadds et al
[qemu.git] / target / ppc / translate / fp-impl.c.inc
blob2e3162d3e7c023e3d59df10a7dd3bc036ee4906f
1 /*
2  * translate-fp.c
3  *
4  * Standard FPU translation
5  */
7 static inline void gen_reset_fpstatus(void)
9     gen_helper_reset_fpstatus(cpu_env);
12 static inline void gen_compute_fprf_float64(TCGv_i64 arg)
14     gen_helper_compute_fprf_float64(cpu_env, arg);
15     gen_helper_float_check_status(cpu_env);
18 #if defined(TARGET_PPC64)
19 static void gen_set_cr1_from_fpscr(DisasContext *ctx)
21     TCGv_i32 tmp = tcg_temp_new_i32();
22     tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
23     tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
24     tcg_temp_free_i32(tmp);
26 #else
27 static void gen_set_cr1_from_fpscr(DisasContext *ctx)
29     tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
31 #endif
33 /***                       Floating-Point arithmetic                       ***/
34 #define _GEN_FLOAT_ACB(name, op1, op2, set_fprf, type)                        \
35 static void gen_f##name(DisasContext *ctx)                                    \
36 {                                                                             \
37     TCGv_i64 t0;                                                              \
38     TCGv_i64 t1;                                                              \
39     TCGv_i64 t2;                                                              \
40     TCGv_i64 t3;                                                              \
41     if (unlikely(!ctx->fpu_enabled)) {                                        \
42         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
43         return;                                                               \
44     }                                                                         \
45     t0 = tcg_temp_new_i64();                                                  \
46     t1 = tcg_temp_new_i64();                                                  \
47     t2 = tcg_temp_new_i64();                                                  \
48     t3 = tcg_temp_new_i64();                                                  \
49     gen_reset_fpstatus();                                                     \
50     get_fpr(t0, rA(ctx->opcode));                                             \
51     get_fpr(t1, rC(ctx->opcode));                                             \
52     get_fpr(t2, rB(ctx->opcode));                                             \
53     gen_helper_f##name(t3, cpu_env, t0, t1, t2);                              \
54     set_fpr(rD(ctx->opcode), t3);                                             \
55     if (set_fprf) {                                                           \
56         gen_compute_fprf_float64(t3);                                         \
57     }                                                                         \
58     if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
59         gen_set_cr1_from_fpscr(ctx);                                          \
60     }                                                                         \
61     tcg_temp_free_i64(t0);                                                    \
62     tcg_temp_free_i64(t1);                                                    \
63     tcg_temp_free_i64(t2);                                                    \
64     tcg_temp_free_i64(t3);                                                    \
67 #define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
68 _GEN_FLOAT_ACB(name, 0x3F, op2, set_fprf, type);                              \
69 _GEN_FLOAT_ACB(name##s, 0x3B, op2, set_fprf, type);
71 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
72 static void gen_f##name(DisasContext *ctx)                                    \
73 {                                                                             \
74     TCGv_i64 t0;                                                              \
75     TCGv_i64 t1;                                                              \
76     TCGv_i64 t2;                                                              \
77     if (unlikely(!ctx->fpu_enabled)) {                                        \
78         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
79         return;                                                               \
80     }                                                                         \
81     t0 = tcg_temp_new_i64();                                                  \
82     t1 = tcg_temp_new_i64();                                                  \
83     t2 = tcg_temp_new_i64();                                                  \
84     gen_reset_fpstatus();                                                     \
85     get_fpr(t0, rA(ctx->opcode));                                             \
86     get_fpr(t1, rB(ctx->opcode));                                             \
87     gen_helper_f##op(t2, cpu_env, t0, t1);                                    \
88     if (isfloat) {                                                            \
89         gen_helper_frsp(t2, cpu_env, t2);                                     \
90     }                                                                         \
91     set_fpr(rD(ctx->opcode), t2);                                             \
92     if (set_fprf) {                                                           \
93         gen_compute_fprf_float64(t2);                                         \
94     }                                                                         \
95     if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
96         gen_set_cr1_from_fpscr(ctx);                                          \
97     }                                                                         \
98     tcg_temp_free_i64(t0);                                                    \
99     tcg_temp_free_i64(t1);                                                    \
100     tcg_temp_free_i64(t2);                                                    \
102 #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
103 _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
104 _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
106 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
107 static void gen_f##name(DisasContext *ctx)                                    \
108 {                                                                             \
109     TCGv_i64 t0;                                                              \
110     TCGv_i64 t1;                                                              \
111     TCGv_i64 t2;                                                              \
112     if (unlikely(!ctx->fpu_enabled)) {                                        \
113         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
114         return;                                                               \
115     }                                                                         \
116     t0 = tcg_temp_new_i64();                                                  \
117     t1 = tcg_temp_new_i64();                                                  \
118     t2 = tcg_temp_new_i64();                                                  \
119     gen_reset_fpstatus();                                                     \
120     get_fpr(t0, rA(ctx->opcode));                                             \
121     get_fpr(t1, rC(ctx->opcode));                                             \
122     gen_helper_f##op(t2, cpu_env, t0, t1);                                    \
123     if (isfloat) {                                                            \
124         gen_helper_frsp(t2, cpu_env, t2);                                     \
125     }                                                                         \
126     set_fpr(rD(ctx->opcode), t2);                                             \
127     if (set_fprf) {                                                           \
128         gen_compute_fprf_float64(t2);                                         \
129     }                                                                         \
130     if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
131         gen_set_cr1_from_fpscr(ctx);                                          \
132     }                                                                         \
133     tcg_temp_free_i64(t0);                                                    \
134     tcg_temp_free_i64(t1);                                                    \
135     tcg_temp_free_i64(t2);                                                    \
137 #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
138 _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
139 _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
141 #define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
142 static void gen_f##name(DisasContext *ctx)                                    \
143 {                                                                             \
144     TCGv_i64 t0;                                                              \
145     TCGv_i64 t1;                                                              \
146     if (unlikely(!ctx->fpu_enabled)) {                                        \
147         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
148         return;                                                               \
149     }                                                                         \
150     t0 = tcg_temp_new_i64();                                                  \
151     t1 = tcg_temp_new_i64();                                                  \
152     gen_reset_fpstatus();                                                     \
153     get_fpr(t0, rB(ctx->opcode));                                             \
154     gen_helper_f##name(t1, cpu_env, t0);                                      \
155     set_fpr(rD(ctx->opcode), t1);                                             \
156     if (set_fprf) {                                                           \
157         gen_helper_compute_fprf_float64(cpu_env, t1);                         \
158     }                                                                         \
159     gen_helper_float_check_status(cpu_env);                                   \
160     if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
161         gen_set_cr1_from_fpscr(ctx);                                          \
162     }                                                                         \
163     tcg_temp_free_i64(t0);                                                    \
164     tcg_temp_free_i64(t1);                                                    \
167 #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
168 static void gen_f##name(DisasContext *ctx)                                    \
169 {                                                                             \
170     TCGv_i64 t0;                                                              \
171     TCGv_i64 t1;                                                              \
172     if (unlikely(!ctx->fpu_enabled)) {                                        \
173         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
174         return;                                                               \
175     }                                                                         \
176     t0 = tcg_temp_new_i64();                                                  \
177     t1 = tcg_temp_new_i64();                                                  \
178     gen_reset_fpstatus();                                                     \
179     get_fpr(t0, rB(ctx->opcode));                                             \
180     gen_helper_f##name(t1, cpu_env, t0);                                      \
181     set_fpr(rD(ctx->opcode), t1);                                             \
182     if (set_fprf) {                                                           \
183         gen_compute_fprf_float64(t1);                                         \
184     }                                                                         \
185     if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
186         gen_set_cr1_from_fpscr(ctx);                                          \
187     }                                                                         \
188     tcg_temp_free_i64(t0);                                                    \
189     tcg_temp_free_i64(t1);                                                    \
192 /* fadd - fadds */
193 GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
194 /* fdiv - fdivs */
195 GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
196 /* fmul - fmuls */
197 GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
199 /* fre */
200 GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
202 /* fres */
203 GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
205 /* frsqrte */
206 GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
208 /* frsqrtes */
209 static void gen_frsqrtes(DisasContext *ctx)
211     TCGv_i64 t0;
212     TCGv_i64 t1;
213     if (unlikely(!ctx->fpu_enabled)) {
214         gen_exception(ctx, POWERPC_EXCP_FPU);
215         return;
216     }
217     t0 = tcg_temp_new_i64();
218     t1 = tcg_temp_new_i64();
219     gen_reset_fpstatus();
220     get_fpr(t0, rB(ctx->opcode));
221     gen_helper_frsqrte(t1, cpu_env, t0);
222     gen_helper_frsp(t1, cpu_env, t1);
223     set_fpr(rD(ctx->opcode), t1);
224     gen_compute_fprf_float64(t1);
225     if (unlikely(Rc(ctx->opcode) != 0)) {
226         gen_set_cr1_from_fpscr(ctx);
227     }
228     tcg_temp_free_i64(t0);
229     tcg_temp_free_i64(t1);
232 /* fsel */
233 _GEN_FLOAT_ACB(sel, 0x3F, 0x17, 0, PPC_FLOAT_FSEL);
234 /* fsub - fsubs */
235 GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
236 /* Optional: */
238 /* fsqrt */
239 static void gen_fsqrt(DisasContext *ctx)
241     TCGv_i64 t0;
242     TCGv_i64 t1;
243     if (unlikely(!ctx->fpu_enabled)) {
244         gen_exception(ctx, POWERPC_EXCP_FPU);
245         return;
246     }
247     t0 = tcg_temp_new_i64();
248     t1 = tcg_temp_new_i64();
249     gen_reset_fpstatus();
250     get_fpr(t0, rB(ctx->opcode));
251     gen_helper_fsqrt(t1, cpu_env, t0);
252     set_fpr(rD(ctx->opcode), t1);
253     gen_compute_fprf_float64(t1);
254     if (unlikely(Rc(ctx->opcode) != 0)) {
255         gen_set_cr1_from_fpscr(ctx);
256     }
257     tcg_temp_free_i64(t0);
258     tcg_temp_free_i64(t1);
261 static void gen_fsqrts(DisasContext *ctx)
263     TCGv_i64 t0;
264     TCGv_i64 t1;
265     if (unlikely(!ctx->fpu_enabled)) {
266         gen_exception(ctx, POWERPC_EXCP_FPU);
267         return;
268     }
269     t0 = tcg_temp_new_i64();
270     t1 = tcg_temp_new_i64();
271     gen_reset_fpstatus();
272     get_fpr(t0, rB(ctx->opcode));
273     gen_helper_fsqrt(t1, cpu_env, t0);
274     gen_helper_frsp(t1, cpu_env, t1);
275     set_fpr(rD(ctx->opcode), t1);
276     gen_compute_fprf_float64(t1);
277     if (unlikely(Rc(ctx->opcode) != 0)) {
278         gen_set_cr1_from_fpscr(ctx);
279     }
280     tcg_temp_free_i64(t0);
281     tcg_temp_free_i64(t1);
284 /***                     Floating-Point multiply-and-add                   ***/
285 /* fmadd - fmadds */
286 GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
287 /* fmsub - fmsubs */
288 GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
289 /* fnmadd - fnmadds */
290 GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
291 /* fnmsub - fnmsubs */
292 GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
294 /***                     Floating-Point round & convert                    ***/
295 /* fctiw */
296 GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
297 /* fctiwu */
298 GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206);
299 /* fctiwz */
300 GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
301 /* fctiwuz */
302 GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206);
303 /* frsp */
304 GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
305 /* fcfid */
306 GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64);
307 /* fcfids */
308 GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206);
309 /* fcfidu */
310 GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
311 /* fcfidus */
312 GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
313 /* fctid */
314 GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64);
315 /* fctidu */
316 GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206);
317 /* fctidz */
318 GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64);
319 /* fctidu */
320 GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206);
322 /* frin */
323 GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
324 /* friz */
325 GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
326 /* frip */
327 GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
328 /* frim */
329 GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
331 static void gen_ftdiv(DisasContext *ctx)
333     TCGv_i64 t0;
334     TCGv_i64 t1;
335     if (unlikely(!ctx->fpu_enabled)) {
336         gen_exception(ctx, POWERPC_EXCP_FPU);
337         return;
338     }
339     t0 = tcg_temp_new_i64();
340     t1 = tcg_temp_new_i64();
341     get_fpr(t0, rA(ctx->opcode));
342     get_fpr(t1, rB(ctx->opcode));
343     gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], t0, t1);
344     tcg_temp_free_i64(t0);
345     tcg_temp_free_i64(t1);
348 static void gen_ftsqrt(DisasContext *ctx)
350     TCGv_i64 t0;
351     if (unlikely(!ctx->fpu_enabled)) {
352         gen_exception(ctx, POWERPC_EXCP_FPU);
353         return;
354     }
355     t0 = tcg_temp_new_i64();
356     get_fpr(t0, rB(ctx->opcode));
357     gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], t0);
358     tcg_temp_free_i64(t0);
363 /***                         Floating-Point compare                        ***/
365 /* fcmpo */
366 static void gen_fcmpo(DisasContext *ctx)
368     TCGv_i32 crf;
369     TCGv_i64 t0;
370     TCGv_i64 t1;
371     if (unlikely(!ctx->fpu_enabled)) {
372         gen_exception(ctx, POWERPC_EXCP_FPU);
373         return;
374     }
375     t0 = tcg_temp_new_i64();
376     t1 = tcg_temp_new_i64();
377     gen_reset_fpstatus();
378     crf = tcg_const_i32(crfD(ctx->opcode));
379     get_fpr(t0, rA(ctx->opcode));
380     get_fpr(t1, rB(ctx->opcode));
381     gen_helper_fcmpo(cpu_env, t0, t1, crf);
382     tcg_temp_free_i32(crf);
383     gen_helper_float_check_status(cpu_env);
384     tcg_temp_free_i64(t0);
385     tcg_temp_free_i64(t1);
388 /* fcmpu */
389 static void gen_fcmpu(DisasContext *ctx)
391     TCGv_i32 crf;
392     TCGv_i64 t0;
393     TCGv_i64 t1;
394     if (unlikely(!ctx->fpu_enabled)) {
395         gen_exception(ctx, POWERPC_EXCP_FPU);
396         return;
397     }
398     t0 = tcg_temp_new_i64();
399     t1 = tcg_temp_new_i64();
400     gen_reset_fpstatus();
401     crf = tcg_const_i32(crfD(ctx->opcode));
402     get_fpr(t0, rA(ctx->opcode));
403     get_fpr(t1, rB(ctx->opcode));
404     gen_helper_fcmpu(cpu_env, t0, t1, crf);
405     tcg_temp_free_i32(crf);
406     gen_helper_float_check_status(cpu_env);
407     tcg_temp_free_i64(t0);
408     tcg_temp_free_i64(t1);
411 /***                         Floating-point move                           ***/
412 /* fabs */
413 /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
414 static void gen_fabs(DisasContext *ctx)
416     TCGv_i64 t0;
417     TCGv_i64 t1;
418     if (unlikely(!ctx->fpu_enabled)) {
419         gen_exception(ctx, POWERPC_EXCP_FPU);
420         return;
421     }
422     t0 = tcg_temp_new_i64();
423     t1 = tcg_temp_new_i64();
424     get_fpr(t0, rB(ctx->opcode));
425     tcg_gen_andi_i64(t1, t0, ~(1ULL << 63));
426     set_fpr(rD(ctx->opcode), t1);
427     if (unlikely(Rc(ctx->opcode))) {
428         gen_set_cr1_from_fpscr(ctx);
429     }
430     tcg_temp_free_i64(t0);
431     tcg_temp_free_i64(t1);
434 /* fmr  - fmr. */
435 /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
436 static void gen_fmr(DisasContext *ctx)
438     TCGv_i64 t0;
439     if (unlikely(!ctx->fpu_enabled)) {
440         gen_exception(ctx, POWERPC_EXCP_FPU);
441         return;
442     }
443     t0 = tcg_temp_new_i64();
444     get_fpr(t0, rB(ctx->opcode));
445     set_fpr(rD(ctx->opcode), t0);
446     if (unlikely(Rc(ctx->opcode))) {
447         gen_set_cr1_from_fpscr(ctx);
448     }
449     tcg_temp_free_i64(t0);
452 /* fnabs */
453 /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
454 static void gen_fnabs(DisasContext *ctx)
456     TCGv_i64 t0;
457     TCGv_i64 t1;
458     if (unlikely(!ctx->fpu_enabled)) {
459         gen_exception(ctx, POWERPC_EXCP_FPU);
460         return;
461     }
462     t0 = tcg_temp_new_i64();
463     t1 = tcg_temp_new_i64();
464     get_fpr(t0, rB(ctx->opcode));
465     tcg_gen_ori_i64(t1, t0, 1ULL << 63);
466     set_fpr(rD(ctx->opcode), t1);
467     if (unlikely(Rc(ctx->opcode))) {
468         gen_set_cr1_from_fpscr(ctx);
469     }
470     tcg_temp_free_i64(t0);
471     tcg_temp_free_i64(t1);
474 /* fneg */
475 /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
476 static void gen_fneg(DisasContext *ctx)
478     TCGv_i64 t0;
479     TCGv_i64 t1;
480     if (unlikely(!ctx->fpu_enabled)) {
481         gen_exception(ctx, POWERPC_EXCP_FPU);
482         return;
483     }
484     t0 = tcg_temp_new_i64();
485     t1 = tcg_temp_new_i64();
486     get_fpr(t0, rB(ctx->opcode));
487     tcg_gen_xori_i64(t1, t0, 1ULL << 63);
488     set_fpr(rD(ctx->opcode), t1);
489     if (unlikely(Rc(ctx->opcode))) {
490         gen_set_cr1_from_fpscr(ctx);
491     }
492     tcg_temp_free_i64(t0);
493     tcg_temp_free_i64(t1);
496 /* fcpsgn: PowerPC 2.05 specification */
497 /* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
498 static void gen_fcpsgn(DisasContext *ctx)
500     TCGv_i64 t0;
501     TCGv_i64 t1;
502     TCGv_i64 t2;
503     if (unlikely(!ctx->fpu_enabled)) {
504         gen_exception(ctx, POWERPC_EXCP_FPU);
505         return;
506     }
507     t0 = tcg_temp_new_i64();
508     t1 = tcg_temp_new_i64();
509     t2 = tcg_temp_new_i64();
510     get_fpr(t0, rA(ctx->opcode));
511     get_fpr(t1, rB(ctx->opcode));
512     tcg_gen_deposit_i64(t2, t0, t1, 0, 63);
513     set_fpr(rD(ctx->opcode), t2);
514     if (unlikely(Rc(ctx->opcode))) {
515         gen_set_cr1_from_fpscr(ctx);
516     }
517     tcg_temp_free_i64(t0);
518     tcg_temp_free_i64(t1);
519     tcg_temp_free_i64(t2);
522 static void gen_fmrgew(DisasContext *ctx)
524     TCGv_i64 b0;
525     TCGv_i64 t0;
526     TCGv_i64 t1;
527     if (unlikely(!ctx->fpu_enabled)) {
528         gen_exception(ctx, POWERPC_EXCP_FPU);
529         return;
530     }
531     b0 = tcg_temp_new_i64();
532     t0 = tcg_temp_new_i64();
533     t1 = tcg_temp_new_i64();
534     get_fpr(t0, rB(ctx->opcode));
535     tcg_gen_shri_i64(b0, t0, 32);
536     get_fpr(t0, rA(ctx->opcode));
537     tcg_gen_deposit_i64(t1, t0, b0, 0, 32);
538     set_fpr(rD(ctx->opcode), t1);
539     tcg_temp_free_i64(b0);
540     tcg_temp_free_i64(t0);
541     tcg_temp_free_i64(t1);
544 static void gen_fmrgow(DisasContext *ctx)
546     TCGv_i64 t0;
547     TCGv_i64 t1;
548     TCGv_i64 t2;
549     if (unlikely(!ctx->fpu_enabled)) {
550         gen_exception(ctx, POWERPC_EXCP_FPU);
551         return;
552     }
553     t0 = tcg_temp_new_i64();
554     t1 = tcg_temp_new_i64();
555     t2 = tcg_temp_new_i64();
556     get_fpr(t0, rB(ctx->opcode));
557     get_fpr(t1, rA(ctx->opcode));
558     tcg_gen_deposit_i64(t2, t0, t1, 32, 32);
559     set_fpr(rD(ctx->opcode), t2);
560     tcg_temp_free_i64(t0);
561     tcg_temp_free_i64(t1);
562     tcg_temp_free_i64(t2);
565 /***                  Floating-Point status & ctrl register                ***/
567 /* mcrfs */
568 static void gen_mcrfs(DisasContext *ctx)
570     TCGv tmp = tcg_temp_new();
571     TCGv_i32 tmask;
572     TCGv_i64 tnew_fpscr = tcg_temp_new_i64();
573     int bfa;
574     int nibble;
575     int shift;
577     if (unlikely(!ctx->fpu_enabled)) {
578         gen_exception(ctx, POWERPC_EXCP_FPU);
579         return;
580     }
581     bfa = crfS(ctx->opcode);
582     nibble = 7 - bfa;
583     shift = 4 * nibble;
584     tcg_gen_shri_tl(tmp, cpu_fpscr, shift);
585     tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
586     tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],
587                      0xf);
588     tcg_temp_free(tmp);
589     tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
590     /* Only the exception bits (including FX) should be cleared if read */
591     tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr,
592                      ~((0xF << shift) & FP_EX_CLEAR_BITS));
593     /* FEX and VX need to be updated, so don't set fpscr directly */
594     tmask = tcg_const_i32(1 << nibble);
595     gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask);
596     tcg_temp_free_i32(tmask);
597     tcg_temp_free_i64(tnew_fpscr);
600 /* mffs */
601 static void gen_mffs(DisasContext *ctx)
603     TCGv_i64 t0;
604     if (unlikely(!ctx->fpu_enabled)) {
605         gen_exception(ctx, POWERPC_EXCP_FPU);
606         return;
607     }
608     t0 = tcg_temp_new_i64();
609     gen_reset_fpstatus();
610     tcg_gen_extu_tl_i64(t0, cpu_fpscr);
611     set_fpr(rD(ctx->opcode), t0);
612     if (unlikely(Rc(ctx->opcode))) {
613         gen_set_cr1_from_fpscr(ctx);
614     }
615     tcg_temp_free_i64(t0);
618 /* mffsl */
619 static void gen_mffsl(DisasContext *ctx)
621     TCGv_i64 t0;
623     if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
624         return gen_mffs(ctx);
625     }
627     if (unlikely(!ctx->fpu_enabled)) {
628         gen_exception(ctx, POWERPC_EXCP_FPU);
629         return;
630     }
631     t0 = tcg_temp_new_i64();
632     gen_reset_fpstatus();
633     tcg_gen_extu_tl_i64(t0, cpu_fpscr);
634     /* Mask everything except mode, status, and enables.  */
635     tcg_gen_andi_i64(t0, t0, FP_DRN | FP_STATUS | FP_ENABLES | FP_RN);
636     set_fpr(rD(ctx->opcode), t0);
637     tcg_temp_free_i64(t0);
640 /* mffsce */
641 static void gen_mffsce(DisasContext *ctx)
643     TCGv_i64 t0;
644     TCGv_i32 mask;
646     if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
647         return gen_mffs(ctx);
648     }
650     if (unlikely(!ctx->fpu_enabled)) {
651         gen_exception(ctx, POWERPC_EXCP_FPU);
652         return;
653     }
655     t0 = tcg_temp_new_i64();
657     gen_reset_fpstatus();
658     tcg_gen_extu_tl_i64(t0, cpu_fpscr);
659     set_fpr(rD(ctx->opcode), t0);
661     /* Clear exception enable bits in the FPSCR.  */
662     tcg_gen_andi_i64(t0, t0, ~FP_ENABLES);
663     mask = tcg_const_i32(0x0003);
664     gen_helper_store_fpscr(cpu_env, t0, mask);
666     tcg_temp_free_i32(mask);
667     tcg_temp_free_i64(t0);
670 static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
672     TCGv_i64 t0 = tcg_temp_new_i64();
673     TCGv_i32 mask = tcg_const_i32(0x0001);
675     gen_reset_fpstatus();
676     tcg_gen_extu_tl_i64(t0, cpu_fpscr);
677     tcg_gen_andi_i64(t0, t0, FP_DRN | FP_ENABLES | FP_RN);
678     set_fpr(rD(ctx->opcode), t0);
680     /* Mask FPSCR value to clear RN.  */
681     tcg_gen_andi_i64(t0, t0, ~FP_RN);
683     /* Merge RN into FPSCR value.  */
684     tcg_gen_or_i64(t0, t0, t1);
686     gen_helper_store_fpscr(cpu_env, t0, mask);
688     tcg_temp_free_i32(mask);
689     tcg_temp_free_i64(t0);
692 /* mffscrn */
693 static void gen_mffscrn(DisasContext *ctx)
695     TCGv_i64 t1;
697     if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
698         return gen_mffs(ctx);
699     }
701     if (unlikely(!ctx->fpu_enabled)) {
702         gen_exception(ctx, POWERPC_EXCP_FPU);
703         return;
704     }
706     t1 = tcg_temp_new_i64();
707     get_fpr(t1, rB(ctx->opcode));
708     /* Mask FRB to get just RN.  */
709     tcg_gen_andi_i64(t1, t1, FP_RN);
711     gen_helper_mffscrn(ctx, t1);
713     tcg_temp_free_i64(t1);
716 /* mffscrni */
717 static void gen_mffscrni(DisasContext *ctx)
719     TCGv_i64 t1;
721     if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
722         return gen_mffs(ctx);
723     }
725     if (unlikely(!ctx->fpu_enabled)) {
726         gen_exception(ctx, POWERPC_EXCP_FPU);
727         return;
728     }
730     t1 = tcg_const_i64((uint64_t)RM(ctx->opcode));
732     gen_helper_mffscrn(ctx, t1);
734     tcg_temp_free_i64(t1);
737 /* mtfsb0 */
738 static void gen_mtfsb0(DisasContext *ctx)
740     uint8_t crb;
742     if (unlikely(!ctx->fpu_enabled)) {
743         gen_exception(ctx, POWERPC_EXCP_FPU);
744         return;
745     }
746     crb = 31 - crbD(ctx->opcode);
747     gen_reset_fpstatus();
748     if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
749         TCGv_i32 t0;
750         t0 = tcg_const_i32(crb);
751         gen_helper_fpscr_clrbit(cpu_env, t0);
752         tcg_temp_free_i32(t0);
753     }
754     if (unlikely(Rc(ctx->opcode) != 0)) {
755         tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
756         tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
757     }
760 /* mtfsb1 */
761 static void gen_mtfsb1(DisasContext *ctx)
763     uint8_t crb;
765     if (unlikely(!ctx->fpu_enabled)) {
766         gen_exception(ctx, POWERPC_EXCP_FPU);
767         return;
768     }
769     crb = 31 - crbD(ctx->opcode);
770     /* XXX: we pretend we can only do IEEE floating-point computations */
771     if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
772         TCGv_i32 t0;
773         t0 = tcg_const_i32(crb);
774         gen_helper_fpscr_setbit(cpu_env, t0);
775         tcg_temp_free_i32(t0);
776     }
777     if (unlikely(Rc(ctx->opcode) != 0)) {
778         tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
779         tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
780     }
781     /* We can raise a deferred exception */
782     gen_helper_fpscr_check_status(cpu_env);
785 /* mtfsf */
786 static void gen_mtfsf(DisasContext *ctx)
788     TCGv_i32 t0;
789     TCGv_i64 t1;
790     int flm, l, w;
792     if (unlikely(!ctx->fpu_enabled)) {
793         gen_exception(ctx, POWERPC_EXCP_FPU);
794         return;
795     }
796     flm = FPFLM(ctx->opcode);
797     l = FPL(ctx->opcode);
798     w = FPW(ctx->opcode);
799     if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
800         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
801         return;
802     }
803     if (l) {
804         t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
805     } else {
806         t0 = tcg_const_i32(flm << (w * 8));
807     }
808     t1 = tcg_temp_new_i64();
809     get_fpr(t1, rB(ctx->opcode));
810     gen_helper_store_fpscr(cpu_env, t1, t0);
811     tcg_temp_free_i32(t0);
812     if (unlikely(Rc(ctx->opcode) != 0)) {
813         tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
814         tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
815     }
816     /* We can raise a deferred exception */
817     gen_helper_fpscr_check_status(cpu_env);
818     tcg_temp_free_i64(t1);
821 /* mtfsfi */
822 static void gen_mtfsfi(DisasContext *ctx)
824     int bf, sh, w;
825     TCGv_i64 t0;
826     TCGv_i32 t1;
828     if (unlikely(!ctx->fpu_enabled)) {
829         gen_exception(ctx, POWERPC_EXCP_FPU);
830         return;
831     }
832     w = FPW(ctx->opcode);
833     bf = FPBF(ctx->opcode);
834     if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
835         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
836         return;
837     }
838     sh = (8 * w) + 7 - bf;
839     t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
840     t1 = tcg_const_i32(1 << sh);
841     gen_helper_store_fpscr(cpu_env, t0, t1);
842     tcg_temp_free_i64(t0);
843     tcg_temp_free_i32(t1);
844     if (unlikely(Rc(ctx->opcode) != 0)) {
845         tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
846         tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
847     }
848     /* We can raise a deferred exception */
849     gen_helper_fpscr_check_status(cpu_env);
852 static void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr)
854     TCGv_i32 tmp = tcg_temp_new_i32();
855     tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
856     gen_helper_todouble(dest, tmp);
857     tcg_temp_free_i32(tmp);
860 /* lfdepx (external PID lfdx) */
861 static void gen_lfdepx(DisasContext *ctx)
863     TCGv EA;
864     TCGv_i64 t0;
865     CHK_SV;
866     if (unlikely(!ctx->fpu_enabled)) {
867         gen_exception(ctx, POWERPC_EXCP_FPU);
868         return;
869     }
870     gen_set_access_type(ctx, ACCESS_FLOAT);
871     EA = tcg_temp_new();
872     t0 = tcg_temp_new_i64();
873     gen_addr_reg_index(ctx, EA);
874     tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_Q));
875     set_fpr(rD(ctx->opcode), t0);
876     tcg_temp_free(EA);
877     tcg_temp_free_i64(t0);
880 /* lfdp */
881 static void gen_lfdp(DisasContext *ctx)
883     TCGv EA;
884     TCGv_i64 t0;
885     if (unlikely(!ctx->fpu_enabled)) {
886         gen_exception(ctx, POWERPC_EXCP_FPU);
887         return;
888     }
889     gen_set_access_type(ctx, ACCESS_FLOAT);
890     EA = tcg_temp_new();
891     gen_addr_imm_index(ctx, EA, 0);
892     t0 = tcg_temp_new_i64();
893     /*
894      * We only need to swap high and low halves. gen_qemu_ld64_i64
895      * does necessary 64-bit byteswap already.
896      */
897     if (unlikely(ctx->le_mode)) {
898         gen_qemu_ld64_i64(ctx, t0, EA);
899         set_fpr(rD(ctx->opcode) + 1, t0);
900         tcg_gen_addi_tl(EA, EA, 8);
901         gen_qemu_ld64_i64(ctx, t0, EA);
902         set_fpr(rD(ctx->opcode), t0);
903     } else {
904         gen_qemu_ld64_i64(ctx, t0, EA);
905         set_fpr(rD(ctx->opcode), t0);
906         tcg_gen_addi_tl(EA, EA, 8);
907         gen_qemu_ld64_i64(ctx, t0, EA);
908         set_fpr(rD(ctx->opcode) + 1, t0);
909     }
910     tcg_temp_free(EA);
911     tcg_temp_free_i64(t0);
914 /* lfdpx */
915 static void gen_lfdpx(DisasContext *ctx)
917     TCGv EA;
918     TCGv_i64 t0;
919     if (unlikely(!ctx->fpu_enabled)) {
920         gen_exception(ctx, POWERPC_EXCP_FPU);
921         return;
922     }
923     gen_set_access_type(ctx, ACCESS_FLOAT);
924     EA = tcg_temp_new();
925     gen_addr_reg_index(ctx, EA);
926     t0 = tcg_temp_new_i64();
927     /*
928      * We only need to swap high and low halves. gen_qemu_ld64_i64
929      * does necessary 64-bit byteswap already.
930      */
931     if (unlikely(ctx->le_mode)) {
932         gen_qemu_ld64_i64(ctx, t0, EA);
933         set_fpr(rD(ctx->opcode) + 1, t0);
934         tcg_gen_addi_tl(EA, EA, 8);
935         gen_qemu_ld64_i64(ctx, t0, EA);
936         set_fpr(rD(ctx->opcode), t0);
937     } else {
938         gen_qemu_ld64_i64(ctx, t0, EA);
939         set_fpr(rD(ctx->opcode), t0);
940         tcg_gen_addi_tl(EA, EA, 8);
941         gen_qemu_ld64_i64(ctx, t0, EA);
942         set_fpr(rD(ctx->opcode) + 1, t0);
943     }
944     tcg_temp_free(EA);
945     tcg_temp_free_i64(t0);
948 /* lfiwax */
949 static void gen_lfiwax(DisasContext *ctx)
951     TCGv EA;
952     TCGv t0;
953     TCGv_i64 t1;
954     if (unlikely(!ctx->fpu_enabled)) {
955         gen_exception(ctx, POWERPC_EXCP_FPU);
956         return;
957     }
958     gen_set_access_type(ctx, ACCESS_FLOAT);
959     EA = tcg_temp_new();
960     t0 = tcg_temp_new();
961     t1 = tcg_temp_new_i64();
962     gen_addr_reg_index(ctx, EA);
963     gen_qemu_ld32s(ctx, t0, EA);
964     tcg_gen_ext_tl_i64(t1, t0);
965     set_fpr(rD(ctx->opcode), t1);
966     tcg_temp_free(EA);
967     tcg_temp_free(t0);
968     tcg_temp_free_i64(t1);
971 /* lfiwzx */
972 static void gen_lfiwzx(DisasContext *ctx)
974     TCGv EA;
975     TCGv_i64 t0;
976     if (unlikely(!ctx->fpu_enabled)) {
977         gen_exception(ctx, POWERPC_EXCP_FPU);
978         return;
979     }
980     gen_set_access_type(ctx, ACCESS_FLOAT);
981     EA = tcg_temp_new();
982     t0 = tcg_temp_new_i64();
983     gen_addr_reg_index(ctx, EA);
984     gen_qemu_ld32u_i64(ctx, t0, EA);
985     set_fpr(rD(ctx->opcode), t0);
986     tcg_temp_free(EA);
987     tcg_temp_free_i64(t0);
990 #define GEN_STXF(name, stop, opc2, opc3, type)                                \
991 static void glue(gen_, name##x)(DisasContext *ctx)                            \
992 {                                                                             \
993     TCGv EA;                                                                  \
994     TCGv_i64 t0;                                                              \
995     if (unlikely(!ctx->fpu_enabled)) {                                        \
996         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
997         return;                                                               \
998     }                                                                         \
999     gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
1000     EA = tcg_temp_new();                                                      \
1001     t0 = tcg_temp_new_i64();                                                  \
1002     gen_addr_reg_index(ctx, EA);                                              \
1003     get_fpr(t0, rS(ctx->opcode));                                             \
1004     gen_qemu_##stop(ctx, t0, EA);                                             \
1005     tcg_temp_free(EA);                                                        \
1006     tcg_temp_free_i64(t0);                                                    \
1009 static void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr)
1011     TCGv_i32 tmp = tcg_temp_new_i32();
1012     gen_helper_tosingle(tmp, src);
1013     tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
1014     tcg_temp_free_i32(tmp);
1017 /* stfdepx (external PID lfdx) */
1018 static void gen_stfdepx(DisasContext *ctx)
1020     TCGv EA;
1021     TCGv_i64 t0;
1022     CHK_SV;
1023     if (unlikely(!ctx->fpu_enabled)) {
1024         gen_exception(ctx, POWERPC_EXCP_FPU);
1025         return;
1026     }
1027     gen_set_access_type(ctx, ACCESS_FLOAT);
1028     EA = tcg_temp_new();
1029     t0 = tcg_temp_new_i64();
1030     gen_addr_reg_index(ctx, EA);
1031     get_fpr(t0, rD(ctx->opcode));
1032     tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_Q));
1033     tcg_temp_free(EA);
1034     tcg_temp_free_i64(t0);
1037 /* stfdp */
1038 static void gen_stfdp(DisasContext *ctx)
1040     TCGv EA;
1041     TCGv_i64 t0;
1042     if (unlikely(!ctx->fpu_enabled)) {
1043         gen_exception(ctx, POWERPC_EXCP_FPU);
1044         return;
1045     }
1046     gen_set_access_type(ctx, ACCESS_FLOAT);
1047     EA = tcg_temp_new();
1048     t0 = tcg_temp_new_i64();
1049     gen_addr_imm_index(ctx, EA, 0);
1050     /*
1051      * We only need to swap high and low halves. gen_qemu_st64_i64
1052      * does necessary 64-bit byteswap already.
1053      */
1054     if (unlikely(ctx->le_mode)) {
1055         get_fpr(t0, rD(ctx->opcode) + 1);
1056         gen_qemu_st64_i64(ctx, t0, EA);
1057         tcg_gen_addi_tl(EA, EA, 8);
1058         get_fpr(t0, rD(ctx->opcode));
1059         gen_qemu_st64_i64(ctx, t0, EA);
1060     } else {
1061         get_fpr(t0, rD(ctx->opcode));
1062         gen_qemu_st64_i64(ctx, t0, EA);
1063         tcg_gen_addi_tl(EA, EA, 8);
1064         get_fpr(t0, rD(ctx->opcode) + 1);
1065         gen_qemu_st64_i64(ctx, t0, EA);
1066     }
1067     tcg_temp_free(EA);
1068     tcg_temp_free_i64(t0);
1071 /* stfdpx */
1072 static void gen_stfdpx(DisasContext *ctx)
1074     TCGv EA;
1075     TCGv_i64 t0;
1076     if (unlikely(!ctx->fpu_enabled)) {
1077         gen_exception(ctx, POWERPC_EXCP_FPU);
1078         return;
1079     }
1080     gen_set_access_type(ctx, ACCESS_FLOAT);
1081     EA = tcg_temp_new();
1082     t0 = tcg_temp_new_i64();
1083     gen_addr_reg_index(ctx, EA);
1084     /*
1085      * We only need to swap high and low halves. gen_qemu_st64_i64
1086      * does necessary 64-bit byteswap already.
1087      */
1088     if (unlikely(ctx->le_mode)) {
1089         get_fpr(t0, rD(ctx->opcode) + 1);
1090         gen_qemu_st64_i64(ctx, t0, EA);
1091         tcg_gen_addi_tl(EA, EA, 8);
1092         get_fpr(t0, rD(ctx->opcode));
1093         gen_qemu_st64_i64(ctx, t0, EA);
1094     } else {
1095         get_fpr(t0, rD(ctx->opcode));
1096         gen_qemu_st64_i64(ctx, t0, EA);
1097         tcg_gen_addi_tl(EA, EA, 8);
1098         get_fpr(t0, rD(ctx->opcode) + 1);
1099         gen_qemu_st64_i64(ctx, t0, EA);
1100     }
1101     tcg_temp_free(EA);
1102     tcg_temp_free_i64(t0);
1105 /* Optional: */
1106 static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1108     TCGv t0 = tcg_temp_new();
1109     tcg_gen_trunc_i64_tl(t0, arg1),
1110     gen_qemu_st32(ctx, t0, arg2);
1111     tcg_temp_free(t0);
1113 /* stfiwx */
1114 GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
1116 /* POWER2 specific instructions */
1117 /* Quad manipulation (load/store two floats at a time) */
1119 /* lfq */
1120 static void gen_lfq(DisasContext *ctx)
1122     int rd = rD(ctx->opcode);
1123     TCGv t0;
1124     TCGv_i64 t1;
1125     gen_set_access_type(ctx, ACCESS_FLOAT);
1126     t0 = tcg_temp_new();
1127     t1 = tcg_temp_new_i64();
1128     gen_addr_imm_index(ctx, t0, 0);
1129     gen_qemu_ld64_i64(ctx, t1, t0);
1130     set_fpr(rd, t1);
1131     gen_addr_add(ctx, t0, t0, 8);
1132     gen_qemu_ld64_i64(ctx, t1, t0);
1133     set_fpr((rd + 1) % 32, t1);
1134     tcg_temp_free(t0);
1135     tcg_temp_free_i64(t1);
1138 /* lfqu */
1139 static void gen_lfqu(DisasContext *ctx)
1141     int ra = rA(ctx->opcode);
1142     int rd = rD(ctx->opcode);
1143     TCGv t0, t1;
1144     TCGv_i64 t2;
1145     gen_set_access_type(ctx, ACCESS_FLOAT);
1146     t0 = tcg_temp_new();
1147     t1 = tcg_temp_new();
1148     t2 = tcg_temp_new_i64();
1149     gen_addr_imm_index(ctx, t0, 0);
1150     gen_qemu_ld64_i64(ctx, t2, t0);
1151     set_fpr(rd, t2);
1152     gen_addr_add(ctx, t1, t0, 8);
1153     gen_qemu_ld64_i64(ctx, t2, t1);
1154     set_fpr((rd + 1) % 32, t2);
1155     if (ra != 0) {
1156         tcg_gen_mov_tl(cpu_gpr[ra], t0);
1157     }
1158     tcg_temp_free(t0);
1159     tcg_temp_free(t1);
1160     tcg_temp_free_i64(t2);
1163 /* lfqux */
1164 static void gen_lfqux(DisasContext *ctx)
1166     int ra = rA(ctx->opcode);
1167     int rd = rD(ctx->opcode);
1168     gen_set_access_type(ctx, ACCESS_FLOAT);
1169     TCGv t0, t1;
1170     TCGv_i64 t2;
1171     t2 = tcg_temp_new_i64();
1172     t0 = tcg_temp_new();
1173     gen_addr_reg_index(ctx, t0);
1174     gen_qemu_ld64_i64(ctx, t2, t0);
1175     set_fpr(rd, t2);
1176     t1 = tcg_temp_new();
1177     gen_addr_add(ctx, t1, t0, 8);
1178     gen_qemu_ld64_i64(ctx, t2, t1);
1179     set_fpr((rd + 1) % 32, t2);
1180     tcg_temp_free(t1);
1181     if (ra != 0) {
1182         tcg_gen_mov_tl(cpu_gpr[ra], t0);
1183     }
1184     tcg_temp_free(t0);
1185     tcg_temp_free_i64(t2);
1188 /* lfqx */
1189 static void gen_lfqx(DisasContext *ctx)
1191     int rd = rD(ctx->opcode);
1192     TCGv t0;
1193     TCGv_i64 t1;
1194     gen_set_access_type(ctx, ACCESS_FLOAT);
1195     t0 = tcg_temp_new();
1196     t1 = tcg_temp_new_i64();
1197     gen_addr_reg_index(ctx, t0);
1198     gen_qemu_ld64_i64(ctx, t1, t0);
1199     set_fpr(rd, t1);
1200     gen_addr_add(ctx, t0, t0, 8);
1201     gen_qemu_ld64_i64(ctx, t1, t0);
1202     set_fpr((rd + 1) % 32, t1);
1203     tcg_temp_free(t0);
1204     tcg_temp_free_i64(t1);
1207 /* stfq */
1208 static void gen_stfq(DisasContext *ctx)
1210     int rd = rD(ctx->opcode);
1211     TCGv t0;
1212     TCGv_i64 t1;
1213     gen_set_access_type(ctx, ACCESS_FLOAT);
1214     t0 = tcg_temp_new();
1215     t1 = tcg_temp_new_i64();
1216     gen_addr_imm_index(ctx, t0, 0);
1217     get_fpr(t1, rd);
1218     gen_qemu_st64_i64(ctx, t1, t0);
1219     gen_addr_add(ctx, t0, t0, 8);
1220     get_fpr(t1, (rd + 1) % 32);
1221     gen_qemu_st64_i64(ctx, t1, t0);
1222     tcg_temp_free(t0);
1223     tcg_temp_free_i64(t1);
1226 /* stfqu */
1227 static void gen_stfqu(DisasContext *ctx)
1229     int ra = rA(ctx->opcode);
1230     int rd = rD(ctx->opcode);
1231     TCGv t0, t1;
1232     TCGv_i64 t2;
1233     gen_set_access_type(ctx, ACCESS_FLOAT);
1234     t2 = tcg_temp_new_i64();
1235     t0 = tcg_temp_new();
1236     gen_addr_imm_index(ctx, t0, 0);
1237     get_fpr(t2, rd);
1238     gen_qemu_st64_i64(ctx, t2, t0);
1239     t1 = tcg_temp_new();
1240     gen_addr_add(ctx, t1, t0, 8);
1241     get_fpr(t2, (rd + 1) % 32);
1242     gen_qemu_st64_i64(ctx, t2, t1);
1243     tcg_temp_free(t1);
1244     if (ra != 0) {
1245         tcg_gen_mov_tl(cpu_gpr[ra], t0);
1246     }
1247     tcg_temp_free(t0);
1248     tcg_temp_free_i64(t2);
1251 /* stfqux */
1252 static void gen_stfqux(DisasContext *ctx)
1254     int ra = rA(ctx->opcode);
1255     int rd = rD(ctx->opcode);
1256     TCGv t0, t1;
1257     TCGv_i64 t2;
1258     gen_set_access_type(ctx, ACCESS_FLOAT);
1259     t2 = tcg_temp_new_i64();
1260     t0 = tcg_temp_new();
1261     gen_addr_reg_index(ctx, t0);
1262     get_fpr(t2, rd);
1263     gen_qemu_st64_i64(ctx, t2, t0);
1264     t1 = tcg_temp_new();
1265     gen_addr_add(ctx, t1, t0, 8);
1266     get_fpr(t2, (rd + 1) % 32);
1267     gen_qemu_st64_i64(ctx, t2, t1);
1268     tcg_temp_free(t1);
1269     if (ra != 0) {
1270         tcg_gen_mov_tl(cpu_gpr[ra], t0);
1271     }
1272     tcg_temp_free(t0);
1273     tcg_temp_free_i64(t2);
1276 /* stfqx */
1277 static void gen_stfqx(DisasContext *ctx)
1279     int rd = rD(ctx->opcode);
1280     TCGv t0;
1281     TCGv_i64 t1;
1282     gen_set_access_type(ctx, ACCESS_FLOAT);
1283     t1 = tcg_temp_new_i64();
1284     t0 = tcg_temp_new();
1285     gen_addr_reg_index(ctx, t0);
1286     get_fpr(t1, rd);
1287     gen_qemu_st64_i64(ctx, t1, t0);
1288     gen_addr_add(ctx, t0, t0, 8);
1289     get_fpr(t1, (rd + 1) % 32);
1290     gen_qemu_st64_i64(ctx, t1, t0);
1291     tcg_temp_free(t0);
1292     tcg_temp_free_i64(t1);
1295 /*            Floating-point Load/Store Instructions                         */
1296 static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ,
1297                       bool update, bool store, bool single)
1299     TCGv ea;
1300     TCGv_i64 t0;
1301     REQUIRE_INSNS_FLAGS(ctx, FLOAT);
1302     REQUIRE_FPU(ctx);
1303     if (update && ra == 0) {
1304         gen_invalid(ctx);
1305         return true;
1306     }
1307     gen_set_access_type(ctx, ACCESS_FLOAT);
1308     t0 = tcg_temp_new_i64();
1309     ea = do_ea_calc(ctx, ra, displ);
1310     if (store) {
1311         get_fpr(t0, rt);
1312         if (single) {
1313             gen_qemu_st32fs(ctx, t0, ea);
1314         } else {
1315             gen_qemu_st64_i64(ctx, t0, ea);
1316         }
1317     } else {
1318         if (single) {
1319             gen_qemu_ld32fs(ctx, t0, ea);
1320         } else {
1321             gen_qemu_ld64_i64(ctx, t0, ea);
1322         }
1323         set_fpr(rt, t0);
1324     }
1325     if (update) {
1326         tcg_gen_mov_tl(cpu_gpr[ra], ea);
1327     }
1328     tcg_temp_free_i64(t0);
1329     tcg_temp_free(ea);
1330     return true;
1333 static bool do_lsfp_D(DisasContext *ctx, arg_D *a, bool update, bool store,
1334                       bool single)
1336     return do_lsfpsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store,
1337                      single);
1340 static bool do_lsfp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
1341                           bool store, bool single)
1343     arg_D d;
1344     if (!resolve_PLS_D(ctx, &d, a)) {
1345         return true;
1346     }
1347     return do_lsfp_D(ctx, &d, update, store, single);
1350 static bool do_lsfp_X(DisasContext *ctx, arg_X *a, bool update,
1351                       bool store, bool single)
1353     return do_lsfpsd(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, single);
1356 TRANS(LFS, do_lsfp_D, false, false, true)
1357 TRANS(LFSU, do_lsfp_D, true, false, true)
1358 TRANS(LFSX, do_lsfp_X, false, false, true)
1359 TRANS(LFSUX, do_lsfp_X, true, false, true)
1360 TRANS(PLFS, do_lsfp_PLS_D, false, false, true)
1362 TRANS(LFD, do_lsfp_D, false, false, false)
1363 TRANS(LFDU, do_lsfp_D, true, false, false)
1364 TRANS(LFDX, do_lsfp_X, false, false, false)
1365 TRANS(LFDUX, do_lsfp_X, true, false, false)
1366 TRANS(PLFD, do_lsfp_PLS_D, false, false, false)
1368 TRANS(STFS, do_lsfp_D, false, true, true)
1369 TRANS(STFSU, do_lsfp_D, true, true, true)
1370 TRANS(STFSX, do_lsfp_X, false, true, true)
1371 TRANS(STFSUX, do_lsfp_X, true, true, true)
1372 TRANS(PSTFS, do_lsfp_PLS_D, false, true, true)
1374 TRANS(STFD, do_lsfp_D, false, true, false)
1375 TRANS(STFDU, do_lsfp_D, true, true, false)
1376 TRANS(STFDX, do_lsfp_X, false, true, false)
1377 TRANS(STFDUX, do_lsfp_X, true, true, false)
1378 TRANS(PSTFD, do_lsfp_PLS_D, false, true, false)
1380 #undef _GEN_FLOAT_ACB
1381 #undef GEN_FLOAT_ACB
1382 #undef _GEN_FLOAT_AB
1383 #undef GEN_FLOAT_AB
1384 #undef _GEN_FLOAT_AC
1385 #undef GEN_FLOAT_AC
1386 #undef GEN_FLOAT_B
1387 #undef GEN_FLOAT_BS
1389 #undef GEN_LDF
1390 #undef GEN_LDUF
1391 #undef GEN_LDUXF
1392 #undef GEN_LDXF
1393 #undef GEN_LDFS
1395 #undef GEN_STF
1396 #undef GEN_STUF
1397 #undef GEN_STUXF
1398 #undef GEN_STXF
1399 #undef GEN_STFS