1
2
3
4
5
6
7
8
9
10static inline void gen_evmra(DisasContext *ctx)
11{
12
13 if (unlikely(!ctx->spe_enabled)) {
14 gen_exception(ctx, POWERPC_EXCP_SPEU);
15 return;
16 }
17
18 TCGv_i64 tmp = tcg_temp_new_i64();
19
20
21 tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
22
23
24 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
25 tcg_temp_free_i64(tmp);
26
27
28 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
29 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
30}
31
32static inline void gen_load_gpr64(TCGv_i64 t, int reg)
33{
34 tcg_gen_concat_tl_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
35}
36
37static inline void gen_store_gpr64(int reg, TCGv_i64 t)
38{
39 tcg_gen_extr_i64_tl(cpu_gpr[reg], cpu_gprh[reg], t);
40}
41
42#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
43static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
44{ \
45 if (Rc(ctx->opcode)) \
46 gen_##name1(ctx); \
47 else \
48 gen_##name0(ctx); \
49}
50
51
52static inline void gen_speundef(DisasContext *ctx)
53{
54 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
55}
56
57
58#define GEN_SPEOP_LOGIC2(name, tcg_op) \
59static inline void gen_##name(DisasContext *ctx) \
60{ \
61 if (unlikely(!ctx->spe_enabled)) { \
62 gen_exception(ctx, POWERPC_EXCP_SPEU); \
63 return; \
64 } \
65 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
66 cpu_gpr[rB(ctx->opcode)]); \
67 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
68 cpu_gprh[rB(ctx->opcode)]); \
69}
70
71GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
72GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
73GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
74GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
75GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
76GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
77GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
78GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
79
80
81#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
82static inline void gen_##name(DisasContext *ctx) \
83{ \
84 TCGv_i32 t0; \
85 if (unlikely(!ctx->spe_enabled)) { \
86 gen_exception(ctx, POWERPC_EXCP_SPEU); \
87 return; \
88 } \
89 t0 = tcg_temp_new_i32(); \
90 \
91 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
92 tcg_opi(t0, t0, rB(ctx->opcode)); \
93 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
94 \
95 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
96 tcg_opi(t0, t0, rB(ctx->opcode)); \
97 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
98 \
99 tcg_temp_free_i32(t0); \
100}
101GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
102GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
103GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
104GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
105
106
107#define GEN_SPEOP_ARITH1(name, tcg_op) \
108static inline void gen_##name(DisasContext *ctx) \
109{ \
110 TCGv_i32 t0; \
111 if (unlikely(!ctx->spe_enabled)) { \
112 gen_exception(ctx, POWERPC_EXCP_SPEU); \
113 return; \
114 } \
115 t0 = tcg_temp_new_i32(); \
116 \
117 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
118 tcg_op(t0, t0); \
119 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
120 \
121 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
122 tcg_op(t0, t0); \
123 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
124 \
125 tcg_temp_free_i32(t0); \
126}
127
128static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
129{
130 TCGLabel *l1 = gen_new_label();
131 TCGLabel *l2 = gen_new_label();
132
133 tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
134 tcg_gen_neg_i32(ret, arg1);
135 tcg_gen_br(l2);
136 gen_set_label(l1);
137 tcg_gen_mov_i32(ret, arg1);
138 gen_set_label(l2);
139}
140GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
141GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
142GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
143GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
144static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
145{
146 tcg_gen_addi_i32(ret, arg1, 0x8000);
147 tcg_gen_ext16u_i32(ret, ret);
148}
149GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
150GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
151GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
152
153#define GEN_SPEOP_ARITH2(name, tcg_op) \
154static inline void gen_##name(DisasContext *ctx) \
155{ \
156 TCGv_i32 t0, t1; \
157 if (unlikely(!ctx->spe_enabled)) { \
158 gen_exception(ctx, POWERPC_EXCP_SPEU); \
159 return; \
160 } \
161 t0 = tcg_temp_new_i32(); \
162 t1 = tcg_temp_new_i32(); \
163 \
164 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
165 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
166 tcg_op(t0, t0, t1); \
167 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
168 \
169 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
170 tcg_gen_trunc_tl_i32(t1, cpu_gprh[rB(ctx->opcode)]); \
171 tcg_op(t0, t0, t1); \
172 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
173 \
174 tcg_temp_free_i32(t0); \
175 tcg_temp_free_i32(t1); \
176}
177
178static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
179{
180 TCGLabel *l1 = gen_new_label();
181 TCGLabel *l2 = gen_new_label();
182 TCGv_i32 t0 = tcg_temp_local_new_i32();
183
184
185 tcg_gen_andi_i32(t0, arg2, 0x3F);
186 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
187 tcg_gen_shr_i32(ret, arg1, t0);
188 tcg_gen_br(l2);
189 gen_set_label(l1);
190 tcg_gen_movi_i32(ret, 0);
191 gen_set_label(l2);
192 tcg_temp_free_i32(t0);
193}
194GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
195static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
196{
197 TCGLabel *l1 = gen_new_label();
198 TCGLabel *l2 = gen_new_label();
199 TCGv_i32 t0 = tcg_temp_local_new_i32();
200
201
202 tcg_gen_andi_i32(t0, arg2, 0x3F);
203 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
204 tcg_gen_sar_i32(ret, arg1, t0);
205 tcg_gen_br(l2);
206 gen_set_label(l1);
207 tcg_gen_movi_i32(ret, 0);
208 gen_set_label(l2);
209 tcg_temp_free_i32(t0);
210}
211GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
212static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
213{
214 TCGLabel *l1 = gen_new_label();
215 TCGLabel *l2 = gen_new_label();
216 TCGv_i32 t0 = tcg_temp_local_new_i32();
217
218
219 tcg_gen_andi_i32(t0, arg2, 0x3F);
220 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
221 tcg_gen_shl_i32(ret, arg1, t0);
222 tcg_gen_br(l2);
223 gen_set_label(l1);
224 tcg_gen_movi_i32(ret, 0);
225 gen_set_label(l2);
226 tcg_temp_free_i32(t0);
227}
228GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
229static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
230{
231 TCGv_i32 t0 = tcg_temp_new_i32();
232 tcg_gen_andi_i32(t0, arg2, 0x1F);
233 tcg_gen_rotl_i32(ret, arg1, t0);
234 tcg_temp_free_i32(t0);
235}
236GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
237static inline void gen_evmergehi(DisasContext *ctx)
238{
239 if (unlikely(!ctx->spe_enabled)) {
240 gen_exception(ctx, POWERPC_EXCP_SPEU);
241 return;
242 }
243 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
244 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
245}
246GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
247static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
248{
249 tcg_gen_sub_i32(ret, arg2, arg1);
250}
251GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
252
253
254#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
255static inline void gen_##name(DisasContext *ctx) \
256{ \
257 TCGv_i32 t0; \
258 if (unlikely(!ctx->spe_enabled)) { \
259 gen_exception(ctx, POWERPC_EXCP_SPEU); \
260 return; \
261 } \
262 t0 = tcg_temp_new_i32(); \
263 \
264 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
265 tcg_op(t0, t0, rA(ctx->opcode)); \
266 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
267 \
268 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rB(ctx->opcode)]); \
269 tcg_op(t0, t0, rA(ctx->opcode)); \
270 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
271 \
272 tcg_temp_free_i32(t0); \
273}
274GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
275GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
276
277
278#define GEN_SPEOP_COMP(name, tcg_cond) \
279static inline void gen_##name(DisasContext *ctx) \
280{ \
281 if (unlikely(!ctx->spe_enabled)) { \
282 gen_exception(ctx, POWERPC_EXCP_SPEU); \
283 return; \
284 } \
285 TCGLabel *l1 = gen_new_label(); \
286 TCGLabel *l2 = gen_new_label(); \
287 TCGLabel *l3 = gen_new_label(); \
288 TCGLabel *l4 = gen_new_label(); \
289 \
290 tcg_gen_ext32s_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
291 tcg_gen_ext32s_tl(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
292 tcg_gen_ext32s_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
293 tcg_gen_ext32s_tl(cpu_gprh[rB(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); \
294 \
295 tcg_gen_brcond_tl(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
296 cpu_gpr[rB(ctx->opcode)], l1); \
297 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
298 tcg_gen_br(l2); \
299 gen_set_label(l1); \
300 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
301 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
302 gen_set_label(l2); \
303 tcg_gen_brcond_tl(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
304 cpu_gprh[rB(ctx->opcode)], l3); \
305 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
306 ~(CRF_CH | CRF_CH_AND_CL)); \
307 tcg_gen_br(l4); \
308 gen_set_label(l3); \
309 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
310 CRF_CH | CRF_CH_OR_CL); \
311 gen_set_label(l4); \
312}
313GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
314GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
315GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
316GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
317GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
318
319
320static inline void gen_brinc(DisasContext *ctx)
321{
322
323 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
324 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
325}
326static inline void gen_evmergelo(DisasContext *ctx)
327{
328 if (unlikely(!ctx->spe_enabled)) {
329 gen_exception(ctx, POWERPC_EXCP_SPEU);
330 return;
331 }
332 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
333 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
334}
335static inline void gen_evmergehilo(DisasContext *ctx)
336{
337 if (unlikely(!ctx->spe_enabled)) {
338 gen_exception(ctx, POWERPC_EXCP_SPEU);
339 return;
340 }
341 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
342 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
343}
344static inline void gen_evmergelohi(DisasContext *ctx)
345{
346 if (unlikely(!ctx->spe_enabled)) {
347 gen_exception(ctx, POWERPC_EXCP_SPEU);
348 return;
349 }
350 if (rD(ctx->opcode) == rA(ctx->opcode)) {
351 TCGv tmp = tcg_temp_new();
352 tcg_gen_mov_tl(tmp, cpu_gpr[rA(ctx->opcode)]);
353 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
354 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], tmp);
355 tcg_temp_free(tmp);
356 } else {
357 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
358 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
359 }
360}
361static inline void gen_evsplati(DisasContext *ctx)
362{
363 uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
364
365 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
366 tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
367}
368static inline void gen_evsplatfi(DisasContext *ctx)
369{
370 uint64_t imm = rA(ctx->opcode) << 27;
371
372 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
373 tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
374}
375
376static inline void gen_evsel(DisasContext *ctx)
377{
378 TCGLabel *l1 = gen_new_label();
379 TCGLabel *l2 = gen_new_label();
380 TCGLabel *l3 = gen_new_label();
381 TCGLabel *l4 = gen_new_label();
382 TCGv_i32 t0 = tcg_temp_local_new_i32();
383
384 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
385 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
386 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
387 tcg_gen_br(l2);
388 gen_set_label(l1);
389 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
390 gen_set_label(l2);
391 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
392 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
393 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
394 tcg_gen_br(l4);
395 gen_set_label(l3);
396 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
397 gen_set_label(l4);
398 tcg_temp_free_i32(t0);
399}
400
401static void gen_evsel0(DisasContext *ctx)
402{
403 gen_evsel(ctx);
404}
405
406static void gen_evsel1(DisasContext *ctx)
407{
408 gen_evsel(ctx);
409}
410
411static void gen_evsel2(DisasContext *ctx)
412{
413 gen_evsel(ctx);
414}
415
416static void gen_evsel3(DisasContext *ctx)
417{
418 gen_evsel(ctx);
419}
420
421
422
423static inline void gen_evmwumi(DisasContext *ctx)
424{
425 TCGv_i64 t0, t1;
426
427 if (unlikely(!ctx->spe_enabled)) {
428 gen_exception(ctx, POWERPC_EXCP_SPEU);
429 return;
430 }
431
432 t0 = tcg_temp_new_i64();
433 t1 = tcg_temp_new_i64();
434
435
436 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
437 tcg_gen_ext32u_i64(t0, t0);
438 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
439 tcg_gen_ext32u_i64(t1, t1);
440
441 tcg_gen_mul_i64(t0, t0, t1);
442
443 gen_store_gpr64(rD(ctx->opcode), t0);
444
445 tcg_temp_free_i64(t0);
446 tcg_temp_free_i64(t1);
447}
448
449static inline void gen_evmwumia(DisasContext *ctx)
450{
451 TCGv_i64 tmp;
452
453 if (unlikely(!ctx->spe_enabled)) {
454 gen_exception(ctx, POWERPC_EXCP_SPEU);
455 return;
456 }
457
458 gen_evmwumi(ctx);
459
460 tmp = tcg_temp_new_i64();
461
462
463 gen_load_gpr64(tmp, rD(ctx->opcode));
464 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
465 tcg_temp_free_i64(tmp);
466}
467
468static inline void gen_evmwumiaa(DisasContext *ctx)
469{
470 TCGv_i64 acc;
471 TCGv_i64 tmp;
472
473 if (unlikely(!ctx->spe_enabled)) {
474 gen_exception(ctx, POWERPC_EXCP_SPEU);
475 return;
476 }
477
478 gen_evmwumi(ctx);
479
480 acc = tcg_temp_new_i64();
481 tmp = tcg_temp_new_i64();
482
483
484 gen_load_gpr64(tmp, rD(ctx->opcode));
485
486
487 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
488
489
490 tcg_gen_add_i64(acc, acc, tmp);
491
492
493 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
494
495
496 gen_store_gpr64(rD(ctx->opcode), acc);
497
498 tcg_temp_free_i64(acc);
499 tcg_temp_free_i64(tmp);
500}
501
502static inline void gen_evmwsmi(DisasContext *ctx)
503{
504 TCGv_i64 t0, t1;
505
506 if (unlikely(!ctx->spe_enabled)) {
507 gen_exception(ctx, POWERPC_EXCP_SPEU);
508 return;
509 }
510
511 t0 = tcg_temp_new_i64();
512 t1 = tcg_temp_new_i64();
513
514
515 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
516 tcg_gen_ext32s_i64(t0, t0);
517 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
518 tcg_gen_ext32s_i64(t1, t1);
519
520 tcg_gen_mul_i64(t0, t0, t1);
521
522 gen_store_gpr64(rD(ctx->opcode), t0);
523
524 tcg_temp_free_i64(t0);
525 tcg_temp_free_i64(t1);
526}
527
528static inline void gen_evmwsmia(DisasContext *ctx)
529{
530 TCGv_i64 tmp;
531
532 gen_evmwsmi(ctx);
533
534 tmp = tcg_temp_new_i64();
535
536
537 gen_load_gpr64(tmp, rD(ctx->opcode));
538 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
539
540 tcg_temp_free_i64(tmp);
541}
542
543static inline void gen_evmwsmiaa(DisasContext *ctx)
544{
545 TCGv_i64 acc = tcg_temp_new_i64();
546 TCGv_i64 tmp = tcg_temp_new_i64();
547
548 gen_evmwsmi(ctx);
549
550 acc = tcg_temp_new_i64();
551 tmp = tcg_temp_new_i64();
552
553
554 gen_load_gpr64(tmp, rD(ctx->opcode));
555
556
557 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
558
559
560 tcg_gen_add_i64(acc, acc, tmp);
561
562
563 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
564
565
566 gen_store_gpr64(rD(ctx->opcode), acc);
567
568 tcg_temp_free_i64(acc);
569 tcg_temp_free_i64(tmp);
570}
571
572GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
573GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
574GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
575GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
576GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE);
577GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE);
578GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE);
579GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE);
580GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
581GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE);
582GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
583GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE);
584GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE);
585GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
586GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
587GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
588GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE);
589GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
590GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE);
591GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
592GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
593GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
594GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
595GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
596GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE);
597GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE);
598GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE);
599GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE);
600GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE);
601
602
603static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
604{
605 target_ulong uimm = rB(ctx->opcode);
606
607 if (rA(ctx->opcode) == 0) {
608 tcg_gen_movi_tl(EA, uimm << sh);
609 } else {
610 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
611 if (NARROW_MODE(ctx)) {
612 tcg_gen_ext32u_tl(EA, EA);
613 }
614 }
615}
616
617static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
618{
619 TCGv_i64 t0 = tcg_temp_new_i64();
620 gen_qemu_ld64_i64(ctx, t0, addr);
621 gen_store_gpr64(rD(ctx->opcode), t0);
622 tcg_temp_free_i64(t0);
623}
624
625static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
626{
627 gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
628 gen_addr_add(ctx, addr, addr, 4);
629 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
630}
631
632static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
633{
634 TCGv t0 = tcg_temp_new();
635 gen_qemu_ld16u(ctx, t0, addr);
636 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
637 gen_addr_add(ctx, addr, addr, 2);
638 gen_qemu_ld16u(ctx, t0, addr);
639 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
640 gen_addr_add(ctx, addr, addr, 2);
641 gen_qemu_ld16u(ctx, t0, addr);
642 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
643 gen_addr_add(ctx, addr, addr, 2);
644 gen_qemu_ld16u(ctx, t0, addr);
645 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
646 tcg_temp_free(t0);
647}
648
649static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
650{
651 TCGv t0 = tcg_temp_new();
652 gen_qemu_ld16u(ctx, t0, addr);
653 tcg_gen_shli_tl(t0, t0, 16);
654 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
655 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
656 tcg_temp_free(t0);
657}
658
659static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
660{
661 TCGv t0 = tcg_temp_new();
662 gen_qemu_ld16u(ctx, t0, addr);
663 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
664 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
665 tcg_temp_free(t0);
666}
667
668static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
669{
670 TCGv t0 = tcg_temp_new();
671 gen_qemu_ld16s(ctx, t0, addr);
672 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
673 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
674 tcg_temp_free(t0);
675}
676
677static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
678{
679 TCGv t0 = tcg_temp_new();
680 gen_qemu_ld16u(ctx, t0, addr);
681 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
682 gen_addr_add(ctx, addr, addr, 2);
683 gen_qemu_ld16u(ctx, t0, addr);
684 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
685 tcg_temp_free(t0);
686}
687
688static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
689{
690 gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
691 gen_addr_add(ctx, addr, addr, 2);
692 gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
693}
694
695static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
696{
697 gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
698 gen_addr_add(ctx, addr, addr, 2);
699 gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
700}
701
702static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
703{
704 TCGv t0 = tcg_temp_new();
705 gen_qemu_ld32u(ctx, t0, addr);
706 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
707 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
708 tcg_temp_free(t0);
709}
710
711static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
712{
713 TCGv t0 = tcg_temp_new();
714 gen_qemu_ld16u(ctx, t0, addr);
715 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
716 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
717 gen_addr_add(ctx, addr, addr, 2);
718 gen_qemu_ld16u(ctx, t0, addr);
719 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
720 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
721 tcg_temp_free(t0);
722}
723
724static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
725{
726 TCGv_i64 t0 = tcg_temp_new_i64();
727 gen_load_gpr64(t0, rS(ctx->opcode));
728 gen_qemu_st64_i64(ctx, t0, addr);
729 tcg_temp_free_i64(t0);
730}
731
732static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
733{
734 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
735 gen_addr_add(ctx, addr, addr, 4);
736 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
737}
738
739static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
740{
741 TCGv t0 = tcg_temp_new();
742 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
743 gen_qemu_st16(ctx, t0, addr);
744 gen_addr_add(ctx, addr, addr, 2);
745 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
746 gen_addr_add(ctx, addr, addr, 2);
747 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
748 gen_qemu_st16(ctx, t0, addr);
749 tcg_temp_free(t0);
750 gen_addr_add(ctx, addr, addr, 2);
751 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
752}
753
754static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
755{
756 TCGv t0 = tcg_temp_new();
757 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
758 gen_qemu_st16(ctx, t0, addr);
759 gen_addr_add(ctx, addr, addr, 2);
760 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
761 gen_qemu_st16(ctx, t0, addr);
762 tcg_temp_free(t0);
763}
764
765static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
766{
767 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
768 gen_addr_add(ctx, addr, addr, 2);
769 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
770}
771
772static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
773{
774 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
775}
776
777static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
778{
779 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
780}
781
782#define GEN_SPEOP_LDST(name, opc2, sh) \
783static void glue(gen_, name)(DisasContext *ctx) \
784{ \
785 TCGv t0; \
786 if (unlikely(!ctx->spe_enabled)) { \
787 gen_exception(ctx, POWERPC_EXCP_SPEU); \
788 return; \
789 } \
790 gen_set_access_type(ctx, ACCESS_INT); \
791 t0 = tcg_temp_new(); \
792 if (Rc(ctx->opcode)) { \
793 gen_addr_spe_imm_index(ctx, t0, sh); \
794 } else { \
795 gen_addr_reg_index(ctx, t0); \
796 } \
797 gen_op_##name(ctx, t0); \
798 tcg_temp_free(t0); \
799}
800
801GEN_SPEOP_LDST(evldd, 0x00, 3);
802GEN_SPEOP_LDST(evldw, 0x01, 3);
803GEN_SPEOP_LDST(evldh, 0x02, 3);
804GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
805GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
806GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
807GEN_SPEOP_LDST(evlwhe, 0x08, 2);
808GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
809GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
810GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
811GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
812
813GEN_SPEOP_LDST(evstdd, 0x10, 3);
814GEN_SPEOP_LDST(evstdw, 0x11, 3);
815GEN_SPEOP_LDST(evstdh, 0x12, 3);
816GEN_SPEOP_LDST(evstwhe, 0x18, 2);
817GEN_SPEOP_LDST(evstwho, 0x1A, 2);
818GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
819GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
820
821
822#if 0
823GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
824GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
825GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
826GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
827GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
828GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
829GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
830GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
831GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
832GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
833GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
834GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
835
836GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
837GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
838GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE);
839GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
840GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
841GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
842GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
843GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
844GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE);
845GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
846GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
847GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
848
849GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
850GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
851GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
852GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
853GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE);
854
855GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE);
856GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
857GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE);
858GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
859GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE);
860GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
861GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE);
862GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
863GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE);
864GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
865GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE);
866GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
867
868GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE);
869GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE);
870GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
871GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
872
873GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE);
874GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
875GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE);
876GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
877GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE);
878GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
879GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE);
880GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
881GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE);
882GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
883GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE);
884GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
885
886GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE);
887GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE);
888GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
889GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE);
890GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
891#endif
892
893
894#define GEN_SPEFPUOP_CONV_32_32(name) \
895static inline void gen_##name(DisasContext *ctx) \
896{ \
897 TCGv_i32 t0 = tcg_temp_new_i32(); \
898 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
899 gen_helper_##name(t0, cpu_env, t0); \
900 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
901 tcg_temp_free_i32(t0); \
902}
903#define GEN_SPEFPUOP_CONV_32_64(name) \
904static inline void gen_##name(DisasContext *ctx) \
905{ \
906 TCGv_i64 t0 = tcg_temp_new_i64(); \
907 TCGv_i32 t1 = tcg_temp_new_i32(); \
908 gen_load_gpr64(t0, rB(ctx->opcode)); \
909 gen_helper_##name(t1, cpu_env, t0); \
910 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); \
911 tcg_temp_free_i64(t0); \
912 tcg_temp_free_i32(t1); \
913}
914#define GEN_SPEFPUOP_CONV_64_32(name) \
915static inline void gen_##name(DisasContext *ctx) \
916{ \
917 TCGv_i64 t0 = tcg_temp_new_i64(); \
918 TCGv_i32 t1 = tcg_temp_new_i32(); \
919 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
920 gen_helper_##name(t0, cpu_env, t1); \
921 gen_store_gpr64(rD(ctx->opcode), t0); \
922 tcg_temp_free_i64(t0); \
923 tcg_temp_free_i32(t1); \
924}
925#define GEN_SPEFPUOP_CONV_64_64(name) \
926static inline void gen_##name(DisasContext *ctx) \
927{ \
928 TCGv_i64 t0 = tcg_temp_new_i64(); \
929 gen_load_gpr64(t0, rB(ctx->opcode)); \
930 gen_helper_##name(t0, cpu_env, t0); \
931 gen_store_gpr64(rD(ctx->opcode), t0); \
932 tcg_temp_free_i64(t0); \
933}
934#define GEN_SPEFPUOP_ARITH2_32_32(name) \
935static inline void gen_##name(DisasContext *ctx) \
936{ \
937 TCGv_i32 t0, t1; \
938 if (unlikely(!ctx->spe_enabled)) { \
939 gen_exception(ctx, POWERPC_EXCP_SPEU); \
940 return; \
941 } \
942 t0 = tcg_temp_new_i32(); \
943 t1 = tcg_temp_new_i32(); \
944 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
945 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
946 gen_helper_##name(t0, cpu_env, t0, t1); \
947 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
948 \
949 tcg_temp_free_i32(t0); \
950 tcg_temp_free_i32(t1); \
951}
952#define GEN_SPEFPUOP_ARITH2_64_64(name) \
953static inline void gen_##name(DisasContext *ctx) \
954{ \
955 TCGv_i64 t0, t1; \
956 if (unlikely(!ctx->spe_enabled)) { \
957 gen_exception(ctx, POWERPC_EXCP_SPEU); \
958 return; \
959 } \
960 t0 = tcg_temp_new_i64(); \
961 t1 = tcg_temp_new_i64(); \
962 gen_load_gpr64(t0, rA(ctx->opcode)); \
963 gen_load_gpr64(t1, rB(ctx->opcode)); \
964 gen_helper_##name(t0, cpu_env, t0, t1); \
965 gen_store_gpr64(rD(ctx->opcode), t0); \
966 tcg_temp_free_i64(t0); \
967 tcg_temp_free_i64(t1); \
968}
969#define GEN_SPEFPUOP_COMP_32(name) \
970static inline void gen_##name(DisasContext *ctx) \
971{ \
972 TCGv_i32 t0, t1; \
973 if (unlikely(!ctx->spe_enabled)) { \
974 gen_exception(ctx, POWERPC_EXCP_SPEU); \
975 return; \
976 } \
977 t0 = tcg_temp_new_i32(); \
978 t1 = tcg_temp_new_i32(); \
979 \
980 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
981 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
982 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
983 \
984 tcg_temp_free_i32(t0); \
985 tcg_temp_free_i32(t1); \
986}
987#define GEN_SPEFPUOP_COMP_64(name) \
988static inline void gen_##name(DisasContext *ctx) \
989{ \
990 TCGv_i64 t0, t1; \
991 if (unlikely(!ctx->spe_enabled)) { \
992 gen_exception(ctx, POWERPC_EXCP_SPEU); \
993 return; \
994 } \
995 t0 = tcg_temp_new_i64(); \
996 t1 = tcg_temp_new_i64(); \
997 gen_load_gpr64(t0, rA(ctx->opcode)); \
998 gen_load_gpr64(t1, rB(ctx->opcode)); \
999 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
1000 tcg_temp_free_i64(t0); \
1001 tcg_temp_free_i64(t1); \
1002}
1003
1004
1005
1006GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
1007GEN_SPEFPUOP_ARITH2_64_64(evfssub);
1008GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
1009GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
1010static inline void gen_evfsabs(DisasContext *ctx)
1011{
1012 if (unlikely(!ctx->spe_enabled)) {
1013 gen_exception(ctx, POWERPC_EXCP_SPEU);
1014 return;
1015 }
1016 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1017 ~0x80000000);
1018 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
1019 ~0x80000000);
1020}
1021static inline void gen_evfsnabs(DisasContext *ctx)
1022{
1023 if (unlikely(!ctx->spe_enabled)) {
1024 gen_exception(ctx, POWERPC_EXCP_SPEU);
1025 return;
1026 }
1027 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1028 0x80000000);
1029 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
1030 0x80000000);
1031}
1032static inline void gen_evfsneg(DisasContext *ctx)
1033{
1034 if (unlikely(!ctx->spe_enabled)) {
1035 gen_exception(ctx, POWERPC_EXCP_SPEU);
1036 return;
1037 }
1038 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1039 0x80000000);
1040 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
1041 0x80000000);
1042}
1043
1044
1045GEN_SPEFPUOP_CONV_64_64(evfscfui);
1046GEN_SPEFPUOP_CONV_64_64(evfscfsi);
1047GEN_SPEFPUOP_CONV_64_64(evfscfuf);
1048GEN_SPEFPUOP_CONV_64_64(evfscfsf);
1049GEN_SPEFPUOP_CONV_64_64(evfsctui);
1050GEN_SPEFPUOP_CONV_64_64(evfsctsi);
1051GEN_SPEFPUOP_CONV_64_64(evfsctuf);
1052GEN_SPEFPUOP_CONV_64_64(evfsctsf);
1053GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
1054GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
1055
1056
1057GEN_SPEFPUOP_COMP_64(evfscmpgt);
1058GEN_SPEFPUOP_COMP_64(evfscmplt);
1059GEN_SPEFPUOP_COMP_64(evfscmpeq);
1060GEN_SPEFPUOP_COMP_64(evfststgt);
1061GEN_SPEFPUOP_COMP_64(evfststlt);
1062GEN_SPEFPUOP_COMP_64(evfststeq);
1063
1064
1065GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE);
1066GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE);
1067GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE);
1068GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE);
1069GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE);
1070GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE);
1071GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1072GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1073GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1074GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1075GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE);
1076GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE);
1077GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE);
1078GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE);
1079
1080
1081
1082GEN_SPEFPUOP_ARITH2_32_32(efsadd);
1083GEN_SPEFPUOP_ARITH2_32_32(efssub);
1084GEN_SPEFPUOP_ARITH2_32_32(efsmul);
1085GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
1086static inline void gen_efsabs(DisasContext *ctx)
1087{
1088 if (unlikely(!ctx->spe_enabled)) {
1089 gen_exception(ctx, POWERPC_EXCP_SPEU);
1090 return;
1091 }
1092 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
1093}
1094static inline void gen_efsnabs(DisasContext *ctx)
1095{
1096 if (unlikely(!ctx->spe_enabled)) {
1097 gen_exception(ctx, POWERPC_EXCP_SPEU);
1098 return;
1099 }
1100 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1101}
1102static inline void gen_efsneg(DisasContext *ctx)
1103{
1104 if (unlikely(!ctx->spe_enabled)) {
1105 gen_exception(ctx, POWERPC_EXCP_SPEU);
1106 return;
1107 }
1108 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1109}
1110
1111
1112GEN_SPEFPUOP_CONV_32_32(efscfui);
1113GEN_SPEFPUOP_CONV_32_32(efscfsi);
1114GEN_SPEFPUOP_CONV_32_32(efscfuf);
1115GEN_SPEFPUOP_CONV_32_32(efscfsf);
1116GEN_SPEFPUOP_CONV_32_32(efsctui);
1117GEN_SPEFPUOP_CONV_32_32(efsctsi);
1118GEN_SPEFPUOP_CONV_32_32(efsctuf);
1119GEN_SPEFPUOP_CONV_32_32(efsctsf);
1120GEN_SPEFPUOP_CONV_32_32(efsctuiz);
1121GEN_SPEFPUOP_CONV_32_32(efsctsiz);
1122GEN_SPEFPUOP_CONV_32_64(efscfd);
1123
1124
1125GEN_SPEFPUOP_COMP_32(efscmpgt);
1126GEN_SPEFPUOP_COMP_32(efscmplt);
1127GEN_SPEFPUOP_COMP_32(efscmpeq);
1128GEN_SPEFPUOP_COMP_32(efststgt);
1129GEN_SPEFPUOP_COMP_32(efststlt);
1130GEN_SPEFPUOP_COMP_32(efststeq);
1131
1132
1133GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE);
1134GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE);
1135GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE);
1136GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE);
1137GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE);
1138GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE);
1139GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1140GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1141GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1142GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE);
1143GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE);
1144GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE);
1145GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE);
1146GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE);
1147
1148
1149
1150GEN_SPEFPUOP_ARITH2_64_64(efdadd);
1151GEN_SPEFPUOP_ARITH2_64_64(efdsub);
1152GEN_SPEFPUOP_ARITH2_64_64(efdmul);
1153GEN_SPEFPUOP_ARITH2_64_64(efddiv);
1154static inline void gen_efdabs(DisasContext *ctx)
1155{
1156 if (unlikely(!ctx->spe_enabled)) {
1157 gen_exception(ctx, POWERPC_EXCP_SPEU);
1158 return;
1159 }
1160 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1161 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
1162 ~0x80000000);
1163}
1164static inline void gen_efdnabs(DisasContext *ctx)
1165{
1166 if (unlikely(!ctx->spe_enabled)) {
1167 gen_exception(ctx, POWERPC_EXCP_SPEU);
1168 return;
1169 }
1170 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1171 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
1172 0x80000000);
1173}
1174static inline void gen_efdneg(DisasContext *ctx)
1175{
1176 if (unlikely(!ctx->spe_enabled)) {
1177 gen_exception(ctx, POWERPC_EXCP_SPEU);
1178 return;
1179 }
1180 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1181 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
1182 0x80000000);
1183}
1184
1185
1186GEN_SPEFPUOP_CONV_64_32(efdcfui);
1187GEN_SPEFPUOP_CONV_64_32(efdcfsi);
1188GEN_SPEFPUOP_CONV_64_32(efdcfuf);
1189GEN_SPEFPUOP_CONV_64_32(efdcfsf);
1190GEN_SPEFPUOP_CONV_32_64(efdctui);
1191GEN_SPEFPUOP_CONV_32_64(efdctsi);
1192GEN_SPEFPUOP_CONV_32_64(efdctuf);
1193GEN_SPEFPUOP_CONV_32_64(efdctsf);
1194GEN_SPEFPUOP_CONV_32_64(efdctuiz);
1195GEN_SPEFPUOP_CONV_32_64(efdctsiz);
1196GEN_SPEFPUOP_CONV_64_32(efdcfs);
1197GEN_SPEFPUOP_CONV_64_64(efdcfuid);
1198GEN_SPEFPUOP_CONV_64_64(efdcfsid);
1199GEN_SPEFPUOP_CONV_64_64(efdctuidz);
1200GEN_SPEFPUOP_CONV_64_64(efdctsidz);
1201
1202
1203GEN_SPEFPUOP_COMP_64(efdcmpgt);
1204GEN_SPEFPUOP_COMP_64(efdcmplt);
1205GEN_SPEFPUOP_COMP_64(efdcmpeq);
1206GEN_SPEFPUOP_COMP_64(efdtstgt);
1207GEN_SPEFPUOP_COMP_64(efdtstlt);
1208GEN_SPEFPUOP_COMP_64(efdtsteq);
1209
1210
1211GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE);
1212GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE);
1213GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE);
1214GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE);
1215GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE);
1216GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE);
1217GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE);
1218GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE);
1219GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE);
1220GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE);
1221GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE);
1222GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE);
1223GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE);
1224GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE);
1225GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE);
1226GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE);
1227
1228#undef GEN_SPE
1229#undef GEN_SPEOP_LDST
1230