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