Commit a0d7d5a776ff4f5cbc00d3d9bb43925e1acbefa1

Authored by aurel32
1 parent a7859e89

target-ppc: convert FPU load/store to TCG

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5786 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/helper.h
@@ -35,6 +35,8 @@ DEF_HELPER_0(reset_fpstatus, void) @@ -35,6 +35,8 @@ DEF_HELPER_0(reset_fpstatus, void)
35 DEF_HELPER_2(compute_fprf, i32, i64, i32) 35 DEF_HELPER_2(compute_fprf, i32, i64, i32)
36 DEF_HELPER_2(store_fpscr, void, i64, i32) 36 DEF_HELPER_2(store_fpscr, void, i64, i32)
37 DEF_HELPER_1(fpscr_setbit, void, i32) 37 DEF_HELPER_1(fpscr_setbit, void, i32)
  38 +DEF_HELPER_1(float64_to_float32, i32, i64)
  39 +DEF_HELPER_1(float32_to_float64, i64, i32)
38 40
39 DEF_HELPER_1(fctiw, i64, i64) 41 DEF_HELPER_1(fctiw, i64, i64)
40 DEF_HELPER_1(fctiwz, i64, i64) 42 DEF_HELPER_1(fctiwz, i64, i64)
target-ppc/op_helper.c
@@ -237,6 +237,24 @@ target_ulong helper_popcntb_64 (target_ulong val) @@ -237,6 +237,24 @@ target_ulong helper_popcntb_64 (target_ulong val)
237 237
238 /*****************************************************************************/ 238 /*****************************************************************************/
239 /* Floating point operations helpers */ 239 /* Floating point operations helpers */
  240 +uint64_t helper_float32_to_float64(uint32_t arg)
  241 +{
  242 + CPU_FloatU f;
  243 + CPU_DoubleU d;
  244 + f.l = arg;
  245 + d.d = float32_to_float64(f.f, &env->fp_status);
  246 + return d.ll;
  247 +}
  248 +
  249 +uint32_t helper_float64_to_float32(uint64_t arg)
  250 +{
  251 + CPU_FloatU f;
  252 + CPU_DoubleU d;
  253 + d.ll = arg;
  254 + f.f = float64_to_float32(d.d, &env->fp_status);
  255 + return f.l;
  256 +}
  257 +
240 static always_inline int fpisneg (float64 d) 258 static always_inline int fpisneg (float64 d)
241 { 259 {
242 CPU_DoubleU u; 260 CPU_DoubleU u;
target-ppc/op_mem.h
@@ -145,139 +145,6 @@ void OPPROTO glue(op_stsw_64, MEMSUFFIX) (void) @@ -145,139 +145,6 @@ void OPPROTO glue(op_stsw_64, MEMSUFFIX) (void)
145 } 145 }
146 #endif 146 #endif
147 147
148 -/*** Floating-point store ***/  
149 -#define PPC_STF_OP(name, op) \  
150 -void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void) \  
151 -{ \  
152 - glue(op, MEMSUFFIX)((uint32_t)T0, FT0); \  
153 - RETURN(); \  
154 -}  
155 -  
156 -#if defined(TARGET_PPC64)  
157 -#define PPC_STF_OP_64(name, op) \  
158 -void OPPROTO glue(glue(glue(op_st, name), _64), MEMSUFFIX) (void) \  
159 -{ \  
160 - glue(op, MEMSUFFIX)((uint64_t)T0, FT0); \  
161 - RETURN(); \  
162 -}  
163 -#endif  
164 -  
165 -static always_inline void glue(stfs, MEMSUFFIX) (target_ulong EA, float64 d)  
166 -{  
167 - glue(stfl, MEMSUFFIX)(EA, float64_to_float32(d, &env->fp_status));  
168 -}  
169 -  
170 -static always_inline void glue(stfiw, MEMSUFFIX) (target_ulong EA, float64 d)  
171 -{  
172 - CPU_DoubleU u;  
173 -  
174 - /* Store the low order 32 bits without any conversion */  
175 - u.d = d;  
176 - glue(st32, MEMSUFFIX)(EA, u.l.lower);  
177 -}  
178 -  
179 -PPC_STF_OP(fd, stfq);  
180 -PPC_STF_OP(fs, stfs);  
181 -PPC_STF_OP(fiw, stfiw);  
182 -#if defined(TARGET_PPC64)  
183 -PPC_STF_OP_64(fd, stfq);  
184 -PPC_STF_OP_64(fs, stfs);  
185 -PPC_STF_OP_64(fiw, stfiw);  
186 -#endif  
187 -  
188 -static always_inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, float64 d)  
189 -{  
190 - CPU_DoubleU u;  
191 -  
192 - u.d = d;  
193 - u.ll = bswap64(u.ll);  
194 - glue(stfq, MEMSUFFIX)(EA, u.d);  
195 -}  
196 -  
197 -static always_inline void glue(stfsr, MEMSUFFIX) (target_ulong EA, float64 d)  
198 -{  
199 - CPU_FloatU u;  
200 -  
201 - u.f = float64_to_float32(d, &env->fp_status);  
202 - u.l = bswap32(u.l);  
203 - glue(stfl, MEMSUFFIX)(EA, u.f);  
204 -}  
205 -  
206 -static always_inline void glue(stfiwr, MEMSUFFIX) (target_ulong EA, float64 d)  
207 -{  
208 - CPU_DoubleU u;  
209 -  
210 - /* Store the low order 32 bits without any conversion */  
211 - u.d = d;  
212 - u.l.lower = bswap32(u.l.lower);  
213 - glue(st32, MEMSUFFIX)(EA, u.l.lower);  
214 -}  
215 -  
216 -PPC_STF_OP(fd_le, stfqr);  
217 -PPC_STF_OP(fs_le, stfsr);  
218 -PPC_STF_OP(fiw_le, stfiwr);  
219 -#if defined(TARGET_PPC64)  
220 -PPC_STF_OP_64(fd_le, stfqr);  
221 -PPC_STF_OP_64(fs_le, stfsr);  
222 -PPC_STF_OP_64(fiw_le, stfiwr);  
223 -#endif  
224 -  
225 -/*** Floating-point load ***/  
226 -#define PPC_LDF_OP(name, op) \  
227 -void OPPROTO glue(glue(op_l, name), MEMSUFFIX) (void) \  
228 -{ \  
229 - FT0 = glue(op, MEMSUFFIX)((uint32_t)T0); \  
230 - RETURN(); \  
231 -}  
232 -  
233 -#if defined(TARGET_PPC64)  
234 -#define PPC_LDF_OP_64(name, op) \  
235 -void OPPROTO glue(glue(glue(op_l, name), _64), MEMSUFFIX) (void) \  
236 -{ \  
237 - FT0 = glue(op, MEMSUFFIX)((uint64_t)T0); \  
238 - RETURN(); \  
239 -}  
240 -#endif  
241 -  
242 -static always_inline float64 glue(ldfs, MEMSUFFIX) (target_ulong EA)  
243 -{  
244 - return float32_to_float64(glue(ldfl, MEMSUFFIX)(EA), &env->fp_status);  
245 -}  
246 -  
247 -PPC_LDF_OP(fd, ldfq);  
248 -PPC_LDF_OP(fs, ldfs);  
249 -#if defined(TARGET_PPC64)  
250 -PPC_LDF_OP_64(fd, ldfq);  
251 -PPC_LDF_OP_64(fs, ldfs);  
252 -#endif  
253 -  
254 -static always_inline float64 glue(ldfqr, MEMSUFFIX) (target_ulong EA)  
255 -{  
256 - CPU_DoubleU u;  
257 -  
258 - u.d = glue(ldfq, MEMSUFFIX)(EA);  
259 - u.ll = bswap64(u.ll);  
260 -  
261 - return u.d;  
262 -}  
263 -  
264 -static always_inline float64 glue(ldfsr, MEMSUFFIX) (target_ulong EA)  
265 -{  
266 - CPU_FloatU u;  
267 -  
268 - u.f = glue(ldfl, MEMSUFFIX)(EA);  
269 - u.l = bswap32(u.l);  
270 -  
271 - return float32_to_float64(u.f, &env->fp_status);  
272 -}  
273 -  
274 -PPC_LDF_OP(fd_le, ldfqr);  
275 -PPC_LDF_OP(fs_le, ldfsr);  
276 -#if defined(TARGET_PPC64)  
277 -PPC_LDF_OP_64(fd_le, ldfqr);  
278 -PPC_LDF_OP_64(fs_le, ldfsr);  
279 -#endif  
280 -  
281 /* Load and set reservation */ 148 /* Load and set reservation */
282 void OPPROTO glue(op_lwarx, MEMSUFFIX) (void) 149 void OPPROTO glue(op_lwarx, MEMSUFFIX) (void)
283 { 150 {
target-ppc/translate.c
@@ -2524,17 +2524,6 @@ static always_inline void gen_addr_register (TCGv EA, @@ -2524,17 +2524,6 @@ static always_inline void gen_addr_register (TCGv EA,
2524 #endif 2524 #endif
2525 2525
2526 /*** Integer load ***/ 2526 /*** Integer load ***/
2527 -#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()  
2528 -#define OP_LD_TABLE(width) \  
2529 -static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = { \  
2530 - GEN_MEM_FUNCS(l##width), \  
2531 -};  
2532 -#define OP_ST_TABLE(width) \  
2533 -static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = { \  
2534 - GEN_MEM_FUNCS(st##width), \  
2535 -};  
2536 -  
2537 -  
2538 #if defined(TARGET_PPC64) 2527 #if defined(TARGET_PPC64)
2539 #define GEN_QEMU_LD_PPC64(width) \ 2528 #define GEN_QEMU_LD_PPC64(width) \
2540 static always_inline void gen_qemu_ld##width##_ppc64(TCGv t0, TCGv t1, int flags)\ 2529 static always_inline void gen_qemu_ld##width##_ppc64(TCGv t0, TCGv t1, int flags)\
@@ -2700,10 +2689,10 @@ static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags) @@ -2700,10 +2689,10 @@ static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags)
2700 2689
2701 2690
2702 #else /* defined(TARGET_PPC64) */ 2691 #else /* defined(TARGET_PPC64) */
2703 -#define GEN_QEMU_LD_PPC32(width) \  
2704 -static always_inline void gen_qemu_ld##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\  
2705 -{ \  
2706 - tcg_gen_qemu_ld##width(arg0, arg1, flags >> 1); \ 2692 +#define GEN_QEMU_LD_PPC32(width) \
  2693 +static always_inline void gen_qemu_ld##width##_ppc32(TCGv arg0, TCGv arg1, int flags) \
  2694 +{ \
  2695 + tcg_gen_qemu_ld##width(arg0, arg1, flags >> 1); \
2707 } 2696 }
2708 GEN_QEMU_LD_PPC32(8u) 2697 GEN_QEMU_LD_PPC32(8u)
2709 GEN_QEMU_LD_PPC32(8s) 2698 GEN_QEMU_LD_PPC32(8s)
@@ -2711,15 +2700,23 @@ GEN_QEMU_LD_PPC32(16u) @@ -2711,15 +2700,23 @@ GEN_QEMU_LD_PPC32(16u)
2711 GEN_QEMU_LD_PPC32(16s) 2700 GEN_QEMU_LD_PPC32(16s)
2712 GEN_QEMU_LD_PPC32(32u) 2701 GEN_QEMU_LD_PPC32(32u)
2713 GEN_QEMU_LD_PPC32(32s) 2702 GEN_QEMU_LD_PPC32(32s)
  2703 +static always_inline void gen_qemu_ld64_ppc32(TCGv_i64 arg0, TCGv arg1, int flags)
  2704 +{
  2705 + tcg_gen_qemu_ld64(arg0, arg1, flags >> 1);
  2706 +}
2714 2707
2715 -#define GEN_QEMU_ST_PPC32(width) \  
2716 -static always_inline void gen_qemu_st##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\  
2717 -{ \  
2718 - tcg_gen_qemu_st##width(arg0, arg1, flags >> 1); \ 2708 +#define GEN_QEMU_ST_PPC32(width) \
  2709 +static always_inline void gen_qemu_st##width##_ppc32(TCGv arg0, TCGv arg1, int flags) \
  2710 +{ \
  2711 + tcg_gen_qemu_st##width(arg0, arg1, flags >> 1); \
2719 } 2712 }
2720 GEN_QEMU_ST_PPC32(8) 2713 GEN_QEMU_ST_PPC32(8)
2721 GEN_QEMU_ST_PPC32(16) 2714 GEN_QEMU_ST_PPC32(16)
2722 GEN_QEMU_ST_PPC32(32) 2715 GEN_QEMU_ST_PPC32(32)
  2716 +static always_inline void gen_qemu_st64_ppc32(TCGv_i64 arg0, TCGv arg1, int flags)
  2717 +{
  2718 + tcg_gen_qemu_st64(arg0, arg1, flags >> 1);
  2719 +}
2723 2720
2724 static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags) 2721 static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
2725 { 2722 {
@@ -2755,6 +2752,13 @@ static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags) @@ -2755,6 +2752,13 @@ static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
2755 tcg_gen_bswap_i32(arg0, arg0); 2752 tcg_gen_bswap_i32(arg0, arg0);
2756 } 2753 }
2757 2754
  2755 +static always_inline void gen_qemu_ld64(TCGv_i64 arg0, TCGv arg1, int flags)
  2756 +{
  2757 + gen_qemu_ld64_ppc32(arg0, arg1, flags);
  2758 + if (unlikely(flags & 1))
  2759 + tcg_gen_bswap_i64(arg0, arg0);
  2760 +}
  2761 +
2758 static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags) 2762 static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
2759 { 2763 {
2760 gen_qemu_st8_ppc32(arg0, arg1, flags); 2764 gen_qemu_st8_ppc32(arg0, arg1, flags);
@@ -2783,6 +2787,16 @@ static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags) @@ -2783,6 +2787,16 @@ static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
2783 gen_qemu_st32_ppc32(arg0, arg1, flags); 2787 gen_qemu_st32_ppc32(arg0, arg1, flags);
2784 } 2788 }
2785 2789
  2790 +static always_inline void gen_qemu_st64(TCGv_i64 arg0, TCGv arg1, int flags)
  2791 +{
  2792 + if (unlikely(flags & 1)) {
  2793 + TCGv_i64 temp = tcg_temp_new_i64();
  2794 + tcg_gen_bswap_i64(temp, arg0);
  2795 + gen_qemu_st64_ppc32(temp, arg1, flags);
  2796 + tcg_temp_free_i64(temp);
  2797 + } else
  2798 + gen_qemu_st64_ppc32(arg0, arg1, flags);
  2799 +}
2786 #endif 2800 #endif
2787 2801
2788 #define GEN_LD(name, ldop, opc, type) \ 2802 #define GEN_LD(name, ldop, opc, type) \
@@ -3325,22 +3339,25 @@ GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT) @@ -3325,22 +3339,25 @@ GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
3325 } 3339 }
3326 3340
3327 /*** Floating-point load ***/ 3341 /*** Floating-point load ***/
3328 -#define GEN_LDF(width, opc, type) \  
3329 -GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \ 3342 +#define GEN_LDF(name, ldop, opc, type) \
  3343 +GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
3330 { \ 3344 { \
  3345 + TCGv EA; \
3331 if (unlikely(!ctx->fpu_enabled)) { \ 3346 if (unlikely(!ctx->fpu_enabled)) { \
3332 GEN_EXCP_NO_FP(ctx); \ 3347 GEN_EXCP_NO_FP(ctx); \
3333 return; \ 3348 return; \
3334 } \ 3349 } \
3335 gen_set_access_type(ACCESS_FLOAT); \ 3350 gen_set_access_type(ACCESS_FLOAT); \
3336 - gen_addr_imm_index(cpu_T[0], ctx, 0); \  
3337 - op_ldst(l##width); \  
3338 - tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \ 3351 + EA = tcg_temp_new(); \
  3352 + gen_addr_imm_index(EA, ctx, 0); \
  3353 + gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
  3354 + tcg_temp_free(EA); \
3339 } 3355 }
3340 3356
3341 -#define GEN_LDUF(width, opc, type) \  
3342 -GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ 3357 +#define GEN_LDUF(name, ldop, opc, type) \
  3358 +GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \
3343 { \ 3359 { \
  3360 + TCGv EA; \
3344 if (unlikely(!ctx->fpu_enabled)) { \ 3361 if (unlikely(!ctx->fpu_enabled)) { \
3345 GEN_EXCP_NO_FP(ctx); \ 3362 GEN_EXCP_NO_FP(ctx); \
3346 return; \ 3363 return; \
@@ -3350,15 +3367,17 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ @@ -3350,15 +3367,17 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
3350 return; \ 3367 return; \
3351 } \ 3368 } \
3352 gen_set_access_type(ACCESS_FLOAT); \ 3369 gen_set_access_type(ACCESS_FLOAT); \
3353 - gen_addr_imm_index(cpu_T[0], ctx, 0); \  
3354 - op_ldst(l##width); \  
3355 - tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \  
3356 - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \ 3370 + EA = tcg_temp_new(); \
  3371 + gen_addr_imm_index(EA, ctx, 0); \
  3372 + gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
  3373 + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
  3374 + tcg_temp_free(EA); \
3357 } 3375 }
3358 3376
3359 -#define GEN_LDUXF(width, opc, type) \  
3360 -GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \ 3377 +#define GEN_LDUXF(name, ldop, opc, type) \
  3378 +GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \
3361 { \ 3379 { \
  3380 + TCGv EA; \
3362 if (unlikely(!ctx->fpu_enabled)) { \ 3381 if (unlikely(!ctx->fpu_enabled)) { \
3363 GEN_EXCP_NO_FP(ctx); \ 3382 GEN_EXCP_NO_FP(ctx); \
3364 return; \ 3383 return; \
@@ -3368,54 +3387,70 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \ @@ -3368,54 +3387,70 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
3368 return; \ 3387 return; \
3369 } \ 3388 } \
3370 gen_set_access_type(ACCESS_FLOAT); \ 3389 gen_set_access_type(ACCESS_FLOAT); \
3371 - gen_addr_reg_index(cpu_T[0], ctx); \  
3372 - op_ldst(l##width); \  
3373 - tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \  
3374 - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \ 3390 + EA = tcg_temp_new(); \
  3391 + gen_addr_reg_index(EA, ctx); \
  3392 + gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
  3393 + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
  3394 + tcg_temp_free(EA); \
3375 } 3395 }
3376 3396
3377 -#define GEN_LDXF(width, opc2, opc3, type) \  
3378 -GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \ 3397 +#define GEN_LDXF(name, ldop, opc2, opc3, type) \
  3398 +GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
3379 { \ 3399 { \
  3400 + TCGv EA; \
3380 if (unlikely(!ctx->fpu_enabled)) { \ 3401 if (unlikely(!ctx->fpu_enabled)) { \
3381 GEN_EXCP_NO_FP(ctx); \ 3402 GEN_EXCP_NO_FP(ctx); \
3382 return; \ 3403 return; \
3383 } \ 3404 } \
3384 gen_set_access_type(ACCESS_FLOAT); \ 3405 gen_set_access_type(ACCESS_FLOAT); \
3385 - gen_addr_reg_index(cpu_T[0], ctx); \  
3386 - op_ldst(l##width); \  
3387 - tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \ 3406 + EA = tcg_temp_new(); \
  3407 + gen_addr_reg_index(EA, ctx); \
  3408 + gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
  3409 + tcg_temp_free(EA); \
3388 } 3410 }
3389 3411
3390 -#define GEN_LDFS(width, op, type) \  
3391 -OP_LD_TABLE(width); \  
3392 -GEN_LDF(width, op | 0x20, type); \  
3393 -GEN_LDUF(width, op | 0x21, type); \  
3394 -GEN_LDUXF(width, op | 0x01, type); \  
3395 -GEN_LDXF(width, 0x17, op | 0x00, type) 3412 +#define GEN_LDFS(name, ldop, op, type) \
  3413 +GEN_LDF(name, ldop, op | 0x20, type); \
  3414 +GEN_LDUF(name, ldop, op | 0x21, type); \
  3415 +GEN_LDUXF(name, ldop, op | 0x01, type); \
  3416 +GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3396 3417
3397 -/* lfd lfdu lfdux lfdx */  
3398 -GEN_LDFS(fd, 0x12, PPC_FLOAT);  
3399 -/* lfs lfsu lfsux lfsx */  
3400 -GEN_LDFS(fs, 0x10, PPC_FLOAT); 3418 +static always_inline void gen_qemu_ld32fs(TCGv_i64 arg1, TCGv arg2, int flags)
  3419 +{
  3420 + TCGv t0 = tcg_temp_new();
  3421 + TCGv_i32 t1 = tcg_temp_new_i32();
  3422 + gen_qemu_ld32u(t0, arg2, flags);
  3423 + tcg_gen_trunc_tl_i32(t1, t0);
  3424 + tcg_temp_free(t0);
  3425 + gen_helper_float32_to_float64(arg1, t1);
  3426 + tcg_temp_free_i32(t1);
  3427 +}
  3428 +
  3429 + /* lfd lfdu lfdux lfdx */
  3430 +GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
  3431 + /* lfs lfsu lfsux lfsx */
  3432 +GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
3401 3433
3402 /*** Floating-point store ***/ 3434 /*** Floating-point store ***/
3403 -#define GEN_STF(width, opc, type) \  
3404 -GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \ 3435 +#define GEN_STF(name, stop, opc, type) \
  3436 +GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
3405 { \ 3437 { \
  3438 + TCGv EA; \
3406 if (unlikely(!ctx->fpu_enabled)) { \ 3439 if (unlikely(!ctx->fpu_enabled)) { \
3407 GEN_EXCP_NO_FP(ctx); \ 3440 GEN_EXCP_NO_FP(ctx); \
3408 return; \ 3441 return; \
3409 } \ 3442 } \
3410 gen_set_access_type(ACCESS_FLOAT); \ 3443 gen_set_access_type(ACCESS_FLOAT); \
3411 - gen_addr_imm_index(cpu_T[0], ctx, 0); \  
3412 - tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \  
3413 - op_ldst(st##width); \ 3444 + EA = tcg_temp_new(); \
  3445 + gen_addr_imm_index(EA, ctx, 0); \
  3446 + gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
  3447 + tcg_temp_free(EA); \
3414 } 3448 }
3415 3449
3416 -#define GEN_STUF(width, opc, type) \  
3417 -GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ 3450 +#define GEN_STUF(name, stop, opc, type) \
  3451 +GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \
3418 { \ 3452 { \
  3453 + TCGv EA; \
3419 if (unlikely(!ctx->fpu_enabled)) { \ 3454 if (unlikely(!ctx->fpu_enabled)) { \
3420 GEN_EXCP_NO_FP(ctx); \ 3455 GEN_EXCP_NO_FP(ctx); \
3421 return; \ 3456 return; \
@@ -3425,15 +3460,17 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ @@ -3425,15 +3460,17 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
3425 return; \ 3460 return; \
3426 } \ 3461 } \
3427 gen_set_access_type(ACCESS_FLOAT); \ 3462 gen_set_access_type(ACCESS_FLOAT); \
3428 - gen_addr_imm_index(cpu_T[0], ctx, 0); \  
3429 - tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \  
3430 - op_ldst(st##width); \  
3431 - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \ 3463 + EA = tcg_temp_new(); \
  3464 + gen_addr_imm_index(EA, ctx, 0); \
  3465 + gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
  3466 + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
  3467 + tcg_temp_free(EA); \
3432 } 3468 }
3433 3469
3434 -#define GEN_STUXF(width, opc, type) \  
3435 -GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \ 3470 +#define GEN_STUXF(name, stop, opc, type) \
  3471 +GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \
3436 { \ 3472 { \
  3473 + TCGv EA; \
3437 if (unlikely(!ctx->fpu_enabled)) { \ 3474 if (unlikely(!ctx->fpu_enabled)) { \
3438 GEN_EXCP_NO_FP(ctx); \ 3475 GEN_EXCP_NO_FP(ctx); \
3439 return; \ 3476 return; \
@@ -3443,41 +3480,60 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \ @@ -3443,41 +3480,60 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
3443 return; \ 3480 return; \
3444 } \ 3481 } \
3445 gen_set_access_type(ACCESS_FLOAT); \ 3482 gen_set_access_type(ACCESS_FLOAT); \
3446 - gen_addr_reg_index(cpu_T[0], ctx); \  
3447 - tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \  
3448 - op_ldst(st##width); \  
3449 - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \ 3483 + EA = tcg_temp_new(); \
  3484 + gen_addr_reg_index(EA, ctx); \
  3485 + gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
  3486 + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
  3487 + tcg_temp_free(EA); \
3450 } 3488 }
3451 3489
3452 -#define GEN_STXF(width, opc2, opc3, type) \  
3453 -GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \ 3490 +#define GEN_STXF(name, stop, opc2, opc3, type) \
  3491 +GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
3454 { \ 3492 { \
  3493 + TCGv EA; \
3455 if (unlikely(!ctx->fpu_enabled)) { \ 3494 if (unlikely(!ctx->fpu_enabled)) { \
3456 GEN_EXCP_NO_FP(ctx); \ 3495 GEN_EXCP_NO_FP(ctx); \
3457 return; \ 3496 return; \
3458 } \ 3497 } \
3459 gen_set_access_type(ACCESS_FLOAT); \ 3498 gen_set_access_type(ACCESS_FLOAT); \
3460 - gen_addr_reg_index(cpu_T[0], ctx); \  
3461 - tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \  
3462 - op_ldst(st##width); \ 3499 + EA = tcg_temp_new(); \
  3500 + gen_addr_reg_index(EA, ctx); \
  3501 + gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
  3502 + tcg_temp_free(EA); \
3463 } 3503 }
3464 3504
3465 -#define GEN_STFS(width, op, type) \  
3466 -OP_ST_TABLE(width); \  
3467 -GEN_STF(width, op | 0x20, type); \  
3468 -GEN_STUF(width, op | 0x21, type); \  
3469 -GEN_STUXF(width, op | 0x01, type); \  
3470 -GEN_STXF(width, 0x17, op | 0x00, type) 3505 +#define GEN_STFS(name, stop, op, type) \
  3506 +GEN_STF(name, stop, op | 0x20, type); \
  3507 +GEN_STUF(name, stop, op | 0x21, type); \
  3508 +GEN_STUXF(name, stop, op | 0x01, type); \
  3509 +GEN_STXF(name, stop, 0x17, op | 0x00, type)
  3510 +
  3511 +static always_inline void gen_qemu_st32fs(TCGv_i64 arg1, TCGv arg2, int flags)
  3512 +{
  3513 + TCGv_i32 t0 = tcg_temp_new_i32();
  3514 + TCGv t1 = tcg_temp_new();
  3515 + gen_helper_float64_to_float32(t0, arg1);
  3516 + tcg_gen_extu_i32_tl(t1, t0);
  3517 + tcg_temp_free_i32(t0);
  3518 + gen_qemu_st32(t1, arg2, flags);
  3519 + tcg_temp_free(t1);
  3520 +}
3471 3521
3472 /* stfd stfdu stfdux stfdx */ 3522 /* stfd stfdu stfdux stfdx */
3473 -GEN_STFS(fd, 0x16, PPC_FLOAT); 3523 +GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
3474 /* stfs stfsu stfsux stfsx */ 3524 /* stfs stfsu stfsux stfsx */
3475 -GEN_STFS(fs, 0x14, PPC_FLOAT); 3525 +GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
3476 3526
3477 /* Optional: */ 3527 /* Optional: */
  3528 +static always_inline void gen_qemu_st32fiw(TCGv_i64 arg1, TCGv arg2, int flags)
  3529 +{
  3530 + TCGv t0 = tcg_temp_new();
  3531 + tcg_gen_trunc_i64_tl(t0, arg1),
  3532 + gen_qemu_st32(t0, arg2, flags);
  3533 + tcg_temp_free(t0);
  3534 +}
3478 /* stfiwx */ 3535 /* stfiwx */
3479 -OP_ST_TABLE(fiw);  
3480 -GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX); 3536 +GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3481 3537
3482 /*** Branch ***/ 3538 /*** Branch ***/
3483 static always_inline void gen_goto_tb (DisasContext *ctx, int n, 3539 static always_inline void gen_goto_tb (DisasContext *ctx, int n,