1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "cpu.h"
23#include "internal.h"
24#include "disas/disas.h"
25#include "exec/exec-all.h"
26#include "tcg/tcg-op.h"
27#include "tcg/tcg-op-gvec.h"
28#include "qemu/host-utils.h"
29#include "qemu/main-loop.h"
30#include "exec/cpu_ldst.h"
31
32#include "exec/helper-proto.h"
33#include "exec/helper-gen.h"
34
35#include "exec/translator.h"
36#include "exec/log.h"
37#include "qemu/atomic128.h"
38#include "spr_common.h"
39#include "power8-pmu.h"
40
41#include "qemu/qemu-print.h"
42#include "qapi/error.h"
43
44#define CPU_SINGLE_STEP 0x1
45#define CPU_BRANCH_STEP 0x2
46
47
48
49
50#ifdef PPC_DEBUG_DISAS
51# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
52#else
53# define LOG_DISAS(...) do { } while (0)
54#endif
55
56
57
58
59static char cpu_reg_names[10 * 3 + 22 * 4
60 + 10 * 4 + 22 * 5
61 + 8 * 5 ];
62static TCGv cpu_gpr[32];
63static TCGv cpu_gprh[32];
64static TCGv_i32 cpu_crf[8];
65static TCGv cpu_nip;
66static TCGv cpu_msr;
67static TCGv cpu_ctr;
68static TCGv cpu_lr;
69#if defined(TARGET_PPC64)
70static TCGv cpu_cfar;
71#endif
72static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca, cpu_ov32, cpu_ca32;
73static TCGv cpu_reserve;
74static TCGv cpu_reserve_val;
75static TCGv cpu_fpscr;
76static TCGv_i32 cpu_access_type;
77
78#include "exec/gen-icount.h"
79
80void ppc_translate_init(void)
81{
82 int i;
83 char *p;
84 size_t cpu_reg_names_size;
85
86 p = cpu_reg_names;
87 cpu_reg_names_size = sizeof(cpu_reg_names);
88
89 for (i = 0; i < 8; i++) {
90 snprintf(p, cpu_reg_names_size, "crf%d", i);
91 cpu_crf[i] = tcg_global_mem_new_i32(cpu_env,
92 offsetof(CPUPPCState, crf[i]), p);
93 p += 5;
94 cpu_reg_names_size -= 5;
95 }
96
97 for (i = 0; i < 32; i++) {
98 snprintf(p, cpu_reg_names_size, "r%d", i);
99 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
100 offsetof(CPUPPCState, gpr[i]), p);
101 p += (i < 10) ? 3 : 4;
102 cpu_reg_names_size -= (i < 10) ? 3 : 4;
103 snprintf(p, cpu_reg_names_size, "r%dH", i);
104 cpu_gprh[i] = tcg_global_mem_new(cpu_env,
105 offsetof(CPUPPCState, gprh[i]), p);
106 p += (i < 10) ? 4 : 5;
107 cpu_reg_names_size -= (i < 10) ? 4 : 5;
108 }
109
110 cpu_nip = tcg_global_mem_new(cpu_env,
111 offsetof(CPUPPCState, nip), "nip");
112
113 cpu_msr = tcg_global_mem_new(cpu_env,
114 offsetof(CPUPPCState, msr), "msr");
115
116 cpu_ctr = tcg_global_mem_new(cpu_env,
117 offsetof(CPUPPCState, ctr), "ctr");
118
119 cpu_lr = tcg_global_mem_new(cpu_env,
120 offsetof(CPUPPCState, lr), "lr");
121
122#if defined(TARGET_PPC64)
123 cpu_cfar = tcg_global_mem_new(cpu_env,
124 offsetof(CPUPPCState, cfar), "cfar");
125#endif
126
127 cpu_xer = tcg_global_mem_new(cpu_env,
128 offsetof(CPUPPCState, xer), "xer");
129 cpu_so = tcg_global_mem_new(cpu_env,
130 offsetof(CPUPPCState, so), "SO");
131 cpu_ov = tcg_global_mem_new(cpu_env,
132 offsetof(CPUPPCState, ov), "OV");
133 cpu_ca = tcg_global_mem_new(cpu_env,
134 offsetof(CPUPPCState, ca), "CA");
135 cpu_ov32 = tcg_global_mem_new(cpu_env,
136 offsetof(CPUPPCState, ov32), "OV32");
137 cpu_ca32 = tcg_global_mem_new(cpu_env,
138 offsetof(CPUPPCState, ca32), "CA32");
139
140 cpu_reserve = tcg_global_mem_new(cpu_env,
141 offsetof(CPUPPCState, reserve_addr),
142 "reserve_addr");
143 cpu_reserve_val = tcg_global_mem_new(cpu_env,
144 offsetof(CPUPPCState, reserve_val),
145 "reserve_val");
146
147 cpu_fpscr = tcg_global_mem_new(cpu_env,
148 offsetof(CPUPPCState, fpscr), "fpscr");
149
150 cpu_access_type = tcg_global_mem_new_i32(cpu_env,
151 offsetof(CPUPPCState, access_type),
152 "access_type");
153}
154
155
156struct DisasContext {
157 DisasContextBase base;
158 target_ulong cia;
159 uint32_t opcode;
160
161 bool pr, hv, dr, le_mode;
162 bool lazy_tlb_flush;
163 bool need_access_type;
164 int mem_idx;
165 int access_type;
166
167 MemOp default_tcg_memop_mask;
168#if defined(TARGET_PPC64)
169 bool sf_mode;
170 bool has_cfar;
171#endif
172 bool fpu_enabled;
173 bool altivec_enabled;
174 bool vsx_enabled;
175 bool spe_enabled;
176 bool tm_enabled;
177 bool gtse;
178 bool hr;
179 bool mmcr0_pmcc0;
180 bool mmcr0_pmcc1;
181 bool mmcr0_pmcjce;
182 bool pmc_other;
183 bool pmu_insn_cnt;
184 ppc_spr_t *spr_cb;
185 int singlestep_enabled;
186 uint32_t flags;
187 uint64_t insns_flags;
188 uint64_t insns_flags2;
189};
190
191#define DISAS_EXIT DISAS_TARGET_0
192#define DISAS_EXIT_UPDATE DISAS_TARGET_1
193#define DISAS_CHAIN DISAS_TARGET_2
194#define DISAS_CHAIN_UPDATE DISAS_TARGET_3
195
196
197static inline bool need_byteswap(const DisasContext *ctx)
198{
199#if TARGET_BIG_ENDIAN
200 return ctx->le_mode;
201#else
202 return !ctx->le_mode;
203#endif
204}
205
206
207#ifdef TARGET_PPC64
208# define NARROW_MODE(C) (!(C)->sf_mode)
209#else
210# define NARROW_MODE(C) 0
211#endif
212
213struct opc_handler_t {
214
215 uint32_t inval1;
216
217 uint32_t inval2;
218
219 uint64_t type;
220
221 uint64_t type2;
222
223 void (*handler)(DisasContext *ctx);
224};
225
226
227static inline void gen_load_spr(TCGv t, int reg)
228{
229 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
230}
231
232static inline void gen_store_spr(int reg, TCGv t)
233{
234 tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
235}
236
237static inline void gen_set_access_type(DisasContext *ctx, int access_type)
238{
239 if (ctx->need_access_type && ctx->access_type != access_type) {
240 tcg_gen_movi_i32(cpu_access_type, access_type);
241 ctx->access_type = access_type;
242 }
243}
244
245static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
246{
247 if (NARROW_MODE(ctx)) {
248 nip = (uint32_t)nip;
249 }
250 tcg_gen_movi_tl(cpu_nip, nip);
251}
252
253static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
254{
255 TCGv_i32 t0, t1;
256
257
258
259
260
261 gen_update_nip(ctx, ctx->cia);
262 t0 = tcg_const_i32(excp);
263 t1 = tcg_const_i32(error);
264 gen_helper_raise_exception_err(cpu_env, t0, t1);
265 tcg_temp_free_i32(t0);
266 tcg_temp_free_i32(t1);
267 ctx->base.is_jmp = DISAS_NORETURN;
268}
269
270static void gen_exception(DisasContext *ctx, uint32_t excp)
271{
272 TCGv_i32 t0;
273
274
275
276
277
278 gen_update_nip(ctx, ctx->cia);
279 t0 = tcg_const_i32(excp);
280 gen_helper_raise_exception(cpu_env, t0);
281 tcg_temp_free_i32(t0);
282 ctx->base.is_jmp = DISAS_NORETURN;
283}
284
285static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
286 target_ulong nip)
287{
288 TCGv_i32 t0;
289
290 gen_update_nip(ctx, nip);
291 t0 = tcg_const_i32(excp);
292 gen_helper_raise_exception(cpu_env, t0);
293 tcg_temp_free_i32(t0);
294 ctx->base.is_jmp = DISAS_NORETURN;
295}
296
297static void gen_icount_io_start(DisasContext *ctx)
298{
299 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
300 gen_io_start();
301
302
303
304
305
306
307 ctx->base.is_jmp = DISAS_TOO_MANY;
308 }
309}
310
311#if !defined(CONFIG_USER_ONLY)
312static void gen_ppc_maybe_interrupt(DisasContext *ctx)
313{
314 gen_icount_io_start(ctx);
315 gen_helper_ppc_maybe_interrupt(cpu_env);
316}
317#endif
318
319
320
321
322
323
324
325
326static uint32_t gen_prep_dbgex(DisasContext *ctx)
327{
328 if (ctx->flags & POWERPC_FLAG_DE) {
329 target_ulong dbsr = 0;
330 if (ctx->singlestep_enabled & CPU_SINGLE_STEP) {
331 dbsr = DBCR0_ICMP;
332 } else {
333
334 dbsr = DBCR0_BRT;
335 }
336 TCGv t0 = tcg_temp_new();
337 gen_load_spr(t0, SPR_BOOKE_DBSR);
338 tcg_gen_ori_tl(t0, t0, dbsr);
339 gen_store_spr(SPR_BOOKE_DBSR, t0);
340 tcg_temp_free(t0);
341 return POWERPC_EXCP_DEBUG;
342 } else {
343 return POWERPC_EXCP_TRACE;
344 }
345}
346
347static void gen_debug_exception(DisasContext *ctx)
348{
349 gen_helper_raise_exception(cpu_env, tcg_constant_i32(gen_prep_dbgex(ctx)));
350 ctx->base.is_jmp = DISAS_NORETURN;
351}
352
353static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
354{
355
356 gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_INVAL | error);
357}
358
359static inline void gen_priv_exception(DisasContext *ctx, uint32_t error)
360{
361 gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_PRIV | error);
362}
363
364static inline void gen_hvpriv_exception(DisasContext *ctx, uint32_t error)
365{
366
367 gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error);
368}
369
370
371
372
373void spr_noaccess(DisasContext *ctx, int gprn, int sprn)
374{
375#if 0
376 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
377 printf("ERROR: try to access SPR %d !\n", sprn);
378#endif
379}
380
381
382
383
384
385
386
387static void spr_load_dump_spr(int sprn)
388{
389#ifdef PPC_DUMP_SPR_ACCESSES
390 TCGv_i32 t0 = tcg_const_i32(sprn);
391 gen_helper_load_dump_spr(cpu_env, t0);
392 tcg_temp_free_i32(t0);
393#endif
394}
395
396void spr_read_generic(DisasContext *ctx, int gprn, int sprn)
397{
398 gen_load_spr(cpu_gpr[gprn], sprn);
399 spr_load_dump_spr(sprn);
400}
401
402static void spr_store_dump_spr(int sprn)
403{
404#ifdef PPC_DUMP_SPR_ACCESSES
405 TCGv_i32 t0 = tcg_const_i32(sprn);
406 gen_helper_store_dump_spr(cpu_env, t0);
407 tcg_temp_free_i32(t0);
408#endif
409}
410
411void spr_write_generic(DisasContext *ctx, int sprn, int gprn)
412{
413 gen_store_spr(sprn, cpu_gpr[gprn]);
414 spr_store_dump_spr(sprn);
415}
416
417void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn)
418{
419 spr_write_generic(ctx, sprn, gprn);
420
421
422
423
424
425
426 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
427}
428
429#if !defined(CONFIG_USER_ONLY)
430void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
431{
432#ifdef TARGET_PPC64
433 TCGv t0 = tcg_temp_new();
434 tcg_gen_ext32u_tl(t0, cpu_gpr[gprn]);
435 gen_store_spr(sprn, t0);
436 tcg_temp_free(t0);
437 spr_store_dump_spr(sprn);
438#else
439 spr_write_generic(ctx, sprn, gprn);
440#endif
441}
442
443void spr_write_clear(DisasContext *ctx, int sprn, int gprn)
444{
445 TCGv t0 = tcg_temp_new();
446 TCGv t1 = tcg_temp_new();
447 gen_load_spr(t0, sprn);
448 tcg_gen_neg_tl(t1, cpu_gpr[gprn]);
449 tcg_gen_and_tl(t0, t0, t1);
450 gen_store_spr(sprn, t0);
451 tcg_temp_free(t0);
452 tcg_temp_free(t1);
453}
454
455void spr_access_nop(DisasContext *ctx, int sprn, int gprn)
456{
457}
458
459#endif
460
461
462
463void spr_read_xer(DisasContext *ctx, int gprn, int sprn)
464{
465 TCGv dst = cpu_gpr[gprn];
466 TCGv t0 = tcg_temp_new();
467 TCGv t1 = tcg_temp_new();
468 TCGv t2 = tcg_temp_new();
469 tcg_gen_mov_tl(dst, cpu_xer);
470 tcg_gen_shli_tl(t0, cpu_so, XER_SO);
471 tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
472 tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
473 tcg_gen_or_tl(t0, t0, t1);
474 tcg_gen_or_tl(dst, dst, t2);
475 tcg_gen_or_tl(dst, dst, t0);
476 if (is_isa300(ctx)) {
477 tcg_gen_shli_tl(t0, cpu_ov32, XER_OV32);
478 tcg_gen_or_tl(dst, dst, t0);
479 tcg_gen_shli_tl(t0, cpu_ca32, XER_CA32);
480 tcg_gen_or_tl(dst, dst, t0);
481 }
482 tcg_temp_free(t0);
483 tcg_temp_free(t1);
484 tcg_temp_free(t2);
485}
486
487void spr_write_xer(DisasContext *ctx, int sprn, int gprn)
488{
489 TCGv src = cpu_gpr[gprn];
490
491 tcg_gen_andi_tl(cpu_xer, src,
492 ~((1u << XER_SO) |
493 (1u << XER_OV) | (1u << XER_OV32) |
494 (1u << XER_CA) | (1u << XER_CA32)));
495 tcg_gen_extract_tl(cpu_ov32, src, XER_OV32, 1);
496 tcg_gen_extract_tl(cpu_ca32, src, XER_CA32, 1);
497 tcg_gen_extract_tl(cpu_so, src, XER_SO, 1);
498 tcg_gen_extract_tl(cpu_ov, src, XER_OV, 1);
499 tcg_gen_extract_tl(cpu_ca, src, XER_CA, 1);
500}
501
502
503void spr_read_lr(DisasContext *ctx, int gprn, int sprn)
504{
505 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_lr);
506}
507
508void spr_write_lr(DisasContext *ctx, int sprn, int gprn)
509{
510 tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
511}
512
513
514#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
515void spr_read_cfar(DisasContext *ctx, int gprn, int sprn)
516{
517 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_cfar);
518}
519
520void spr_write_cfar(DisasContext *ctx, int sprn, int gprn)
521{
522 tcg_gen_mov_tl(cpu_cfar, cpu_gpr[gprn]);
523}
524#endif
525
526
527void spr_read_ctr(DisasContext *ctx, int gprn, int sprn)
528{
529 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_ctr);
530}
531
532void spr_write_ctr(DisasContext *ctx, int sprn, int gprn)
533{
534 tcg_gen_mov_tl(cpu_ctr, cpu_gpr[gprn]);
535}
536
537
538
539
540
541
542
543void spr_read_ureg(DisasContext *ctx, int gprn, int sprn)
544{
545 gen_load_spr(cpu_gpr[gprn], sprn + 0x10);
546}
547
548#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
549void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
550{
551 gen_store_spr(sprn + 0x10, cpu_gpr[gprn]);
552}
553#endif
554
555
556
557#if !defined(CONFIG_USER_ONLY)
558void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
559{
560 gen_icount_io_start(ctx);
561 gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
562}
563
564void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
565{
566 gen_icount_io_start(ctx);
567 gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
568}
569#endif
570
571
572
573void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
574{
575 gen_icount_io_start(ctx);
576 gen_helper_load_tbl(cpu_gpr[gprn], cpu_env);
577}
578
579void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
580{
581 gen_icount_io_start(ctx);
582 gen_helper_load_tbu(cpu_gpr[gprn], cpu_env);
583}
584
585void spr_read_atbl(DisasContext *ctx, int gprn, int sprn)
586{
587 gen_helper_load_atbl(cpu_gpr[gprn], cpu_env);
588}
589
590void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
591{
592 gen_helper_load_atbu(cpu_gpr[gprn], cpu_env);
593}
594
595#if !defined(CONFIG_USER_ONLY)
596void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
597{
598 gen_icount_io_start(ctx);
599 gen_helper_store_tbl(cpu_env, cpu_gpr[gprn]);
600}
601
602void spr_write_tbu(DisasContext *ctx, int sprn, int gprn)
603{
604 gen_icount_io_start(ctx);
605 gen_helper_store_tbu(cpu_env, cpu_gpr[gprn]);
606}
607
608void spr_write_atbl(DisasContext *ctx, int sprn, int gprn)
609{
610 gen_helper_store_atbl(cpu_env, cpu_gpr[gprn]);
611}
612
613void spr_write_atbu(DisasContext *ctx, int sprn, int gprn)
614{
615 gen_helper_store_atbu(cpu_env, cpu_gpr[gprn]);
616}
617
618#if defined(TARGET_PPC64)
619void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
620{
621 gen_icount_io_start(ctx);
622 gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
623}
624
625void spr_write_purr(DisasContext *ctx, int sprn, int gprn)
626{
627 gen_icount_io_start(ctx);
628 gen_helper_store_purr(cpu_env, cpu_gpr[gprn]);
629}
630
631
632void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
633{
634 gen_icount_io_start(ctx);
635 gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
636}
637
638void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn)
639{
640 gen_icount_io_start(ctx);
641 gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
642}
643
644void spr_read_vtb(DisasContext *ctx, int gprn, int sprn)
645{
646 gen_icount_io_start(ctx);
647 gen_helper_load_vtb(cpu_gpr[gprn], cpu_env);
648}
649
650void spr_write_vtb(DisasContext *ctx, int sprn, int gprn)
651{
652 gen_icount_io_start(ctx);
653 gen_helper_store_vtb(cpu_env, cpu_gpr[gprn]);
654}
655
656void spr_write_tbu40(DisasContext *ctx, int sprn, int gprn)
657{
658 gen_icount_io_start(ctx);
659 gen_helper_store_tbu40(cpu_env, cpu_gpr[gprn]);
660}
661
662#endif
663#endif
664
665#if !defined(CONFIG_USER_ONLY)
666
667
668void spr_read_ibat(DisasContext *ctx, int gprn, int sprn)
669{
670 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
671 offsetof(CPUPPCState,
672 IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
673}
674
675void spr_read_ibat_h(DisasContext *ctx, int gprn, int sprn)
676{
677 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
678 offsetof(CPUPPCState,
679 IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4]));
680}
681
682void spr_write_ibatu(DisasContext *ctx, int sprn, int gprn)
683{
684 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
685 gen_helper_store_ibatu(cpu_env, t0, cpu_gpr[gprn]);
686 tcg_temp_free_i32(t0);
687}
688
689void spr_write_ibatu_h(DisasContext *ctx, int sprn, int gprn)
690{
691 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_IBAT4U) / 2) + 4);
692 gen_helper_store_ibatu(cpu_env, t0, cpu_gpr[gprn]);
693 tcg_temp_free_i32(t0);
694}
695
696void spr_write_ibatl(DisasContext *ctx, int sprn, int gprn)
697{
698 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0L) / 2);
699 gen_helper_store_ibatl(cpu_env, t0, cpu_gpr[gprn]);
700 tcg_temp_free_i32(t0);
701}
702
703void spr_write_ibatl_h(DisasContext *ctx, int sprn, int gprn)
704{
705 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_IBAT4L) / 2) + 4);
706 gen_helper_store_ibatl(cpu_env, t0, cpu_gpr[gprn]);
707 tcg_temp_free_i32(t0);
708}
709
710
711
712void spr_read_dbat(DisasContext *ctx, int gprn, int sprn)
713{
714 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
715 offsetof(CPUPPCState,
716 DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
717}
718
719void spr_read_dbat_h(DisasContext *ctx, int gprn, int sprn)
720{
721 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
722 offsetof(CPUPPCState,
723 DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
724}
725
726void spr_write_dbatu(DisasContext *ctx, int sprn, int gprn)
727{
728 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0U) / 2);
729 gen_helper_store_dbatu(cpu_env, t0, cpu_gpr[gprn]);
730 tcg_temp_free_i32(t0);
731}
732
733void spr_write_dbatu_h(DisasContext *ctx, int sprn, int gprn)
734{
735 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4U) / 2) + 4);
736 gen_helper_store_dbatu(cpu_env, t0, cpu_gpr[gprn]);
737 tcg_temp_free_i32(t0);
738}
739
740void spr_write_dbatl(DisasContext *ctx, int sprn, int gprn)
741{
742 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0L) / 2);
743 gen_helper_store_dbatl(cpu_env, t0, cpu_gpr[gprn]);
744 tcg_temp_free_i32(t0);
745}
746
747void spr_write_dbatl_h(DisasContext *ctx, int sprn, int gprn)
748{
749 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4L) / 2) + 4);
750 gen_helper_store_dbatl(cpu_env, t0, cpu_gpr[gprn]);
751 tcg_temp_free_i32(t0);
752}
753
754
755void spr_write_sdr1(DisasContext *ctx, int sprn, int gprn)
756{
757 gen_helper_store_sdr1(cpu_env, cpu_gpr[gprn]);
758}
759
760#if defined(TARGET_PPC64)
761
762
763void spr_write_pidr(DisasContext *ctx, int sprn, int gprn)
764{
765 gen_helper_store_pidr(cpu_env, cpu_gpr[gprn]);
766}
767
768void spr_write_lpidr(DisasContext *ctx, int sprn, int gprn)
769{
770 gen_helper_store_lpidr(cpu_env, cpu_gpr[gprn]);
771}
772
773void spr_read_hior(DisasContext *ctx, int gprn, int sprn)
774{
775 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix));
776}
777
778void spr_write_hior(DisasContext *ctx, int sprn, int gprn)
779{
780 TCGv t0 = tcg_temp_new();
781 tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0x3FFFFF00000ULL);
782 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
783 tcg_temp_free(t0);
784}
785void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
786{
787 gen_helper_store_ptcr(cpu_env, cpu_gpr[gprn]);
788}
789
790void spr_write_pcr(DisasContext *ctx, int sprn, int gprn)
791{
792 gen_helper_store_pcr(cpu_env, cpu_gpr[gprn]);
793}
794
795
796void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn)
797{
798 gen_helper_load_dpdes(cpu_gpr[gprn], cpu_env);
799}
800
801void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
802{
803 gen_helper_store_dpdes(cpu_env, cpu_gpr[gprn]);
804}
805#endif
806#endif
807
808
809#if !defined(CONFIG_USER_ONLY)
810void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn)
811{
812 gen_icount_io_start(ctx);
813 gen_helper_load_40x_pit(cpu_gpr[gprn], cpu_env);
814}
815
816void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn)
817{
818 gen_icount_io_start(ctx);
819 gen_helper_store_40x_pit(cpu_env, cpu_gpr[gprn]);
820}
821
822void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn)
823{
824 gen_icount_io_start(ctx);
825 gen_store_spr(sprn, cpu_gpr[gprn]);
826 gen_helper_store_40x_dbcr0(cpu_env, cpu_gpr[gprn]);
827
828 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
829}
830
831void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn)
832{
833 gen_icount_io_start(ctx);
834 gen_helper_store_40x_sler(cpu_env, cpu_gpr[gprn]);
835}
836
837void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn)
838{
839 gen_icount_io_start(ctx);
840 gen_helper_store_40x_tcr(cpu_env, cpu_gpr[gprn]);
841}
842
843void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn)
844{
845 gen_icount_io_start(ctx);
846 gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]);
847}
848
849void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn)
850{
851 TCGv t0 = tcg_temp_new();
852 tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xFF);
853 gen_helper_store_40x_pid(cpu_env, t0);
854 tcg_temp_free(t0);
855}
856
857void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn)
858{
859 gen_icount_io_start(ctx);
860 gen_helper_store_booke_tcr(cpu_env, cpu_gpr[gprn]);
861}
862
863void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn)
864{
865 gen_icount_io_start(ctx);
866 gen_helper_store_booke_tsr(cpu_env, cpu_gpr[gprn]);
867}
868#endif
869
870
871#if !defined(CONFIG_USER_ONLY)
872void spr_write_pir(DisasContext *ctx, int sprn, int gprn)
873{
874 TCGv t0 = tcg_temp_new();
875 tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xF);
876 gen_store_spr(SPR_PIR, t0);
877 tcg_temp_free(t0);
878}
879#endif
880
881
882void spr_read_spefscr(DisasContext *ctx, int gprn, int sprn)
883{
884 TCGv_i32 t0 = tcg_temp_new_i32();
885 tcg_gen_ld_i32(t0, cpu_env, offsetof(CPUPPCState, spe_fscr));
886 tcg_gen_extu_i32_tl(cpu_gpr[gprn], t0);
887 tcg_temp_free_i32(t0);
888}
889
890void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn)
891{
892 TCGv_i32 t0 = tcg_temp_new_i32();
893 tcg_gen_trunc_tl_i32(t0, cpu_gpr[gprn]);
894 tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, spe_fscr));
895 tcg_temp_free_i32(t0);
896}
897
898#if !defined(CONFIG_USER_ONLY)
899
900void spr_write_excp_prefix(DisasContext *ctx, int sprn, int gprn)
901{
902 TCGv t0 = tcg_temp_new();
903 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUPPCState, ivpr_mask));
904 tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
905 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
906 gen_store_spr(sprn, t0);
907 tcg_temp_free(t0);
908}
909
910void spr_write_excp_vector(DisasContext *ctx, int sprn, int gprn)
911{
912 int sprn_offs;
913
914 if (sprn >= SPR_BOOKE_IVOR0 && sprn <= SPR_BOOKE_IVOR15) {
915 sprn_offs = sprn - SPR_BOOKE_IVOR0;
916 } else if (sprn >= SPR_BOOKE_IVOR32 && sprn <= SPR_BOOKE_IVOR37) {
917 sprn_offs = sprn - SPR_BOOKE_IVOR32 + 32;
918 } else if (sprn >= SPR_BOOKE_IVOR38 && sprn <= SPR_BOOKE_IVOR42) {
919 sprn_offs = sprn - SPR_BOOKE_IVOR38 + 38;
920 } else {
921 qemu_log_mask(LOG_GUEST_ERROR, "Trying to write an unknown exception"
922 " vector 0x%03x\n", sprn);
923 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
924 return;
925 }
926
927 TCGv t0 = tcg_temp_new();
928 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUPPCState, ivor_mask));
929 tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
930 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_vectors[sprn_offs]));
931 gen_store_spr(sprn, t0);
932 tcg_temp_free(t0);
933}
934#endif
935
936#ifdef TARGET_PPC64
937#ifndef CONFIG_USER_ONLY
938void spr_write_amr(DisasContext *ctx, int sprn, int gprn)
939{
940 TCGv t0 = tcg_temp_new();
941 TCGv t1 = tcg_temp_new();
942 TCGv t2 = tcg_temp_new();
943
944
945
946
947
948
949
950 if (ctx->pr) {
951 gen_load_spr(t1, SPR_UAMOR);
952 } else {
953 gen_load_spr(t1, SPR_AMOR);
954 }
955
956
957 tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
958
959
960 gen_load_spr(t0, SPR_AMR);
961 tcg_gen_andc_tl(t0, t0, t1);
962
963
964 tcg_gen_or_tl(t0, t0, t2);
965 gen_store_spr(SPR_AMR, t0);
966 spr_store_dump_spr(SPR_AMR);
967
968 tcg_temp_free(t0);
969 tcg_temp_free(t1);
970 tcg_temp_free(t2);
971}
972
973void spr_write_uamor(DisasContext *ctx, int sprn, int gprn)
974{
975 TCGv t0 = tcg_temp_new();
976 TCGv t1 = tcg_temp_new();
977 TCGv t2 = tcg_temp_new();
978
979
980
981
982
983
984
985 gen_load_spr(t1, SPR_AMOR);
986
987
988 tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
989
990
991 gen_load_spr(t0, SPR_UAMOR);
992 tcg_gen_andc_tl(t0, t0, t1);
993
994
995 tcg_gen_or_tl(t0, t0, t2);
996 gen_store_spr(SPR_UAMOR, t0);
997 spr_store_dump_spr(SPR_UAMOR);
998
999 tcg_temp_free(t0);
1000 tcg_temp_free(t1);
1001 tcg_temp_free(t2);
1002}
1003
1004void spr_write_iamr(DisasContext *ctx, int sprn, int gprn)
1005{
1006 TCGv t0 = tcg_temp_new();
1007 TCGv t1 = tcg_temp_new();
1008 TCGv t2 = tcg_temp_new();
1009
1010
1011
1012
1013
1014
1015
1016 gen_load_spr(t1, SPR_AMOR);
1017
1018
1019 tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
1020
1021
1022 gen_load_spr(t0, SPR_IAMR);
1023 tcg_gen_andc_tl(t0, t0, t1);
1024
1025
1026 tcg_gen_or_tl(t0, t0, t2);
1027 gen_store_spr(SPR_IAMR, t0);
1028 spr_store_dump_spr(SPR_IAMR);
1029
1030 tcg_temp_free(t0);
1031 tcg_temp_free(t1);
1032 tcg_temp_free(t2);
1033}
1034#endif
1035#endif
1036
1037#ifndef CONFIG_USER_ONLY
1038void spr_read_thrm(DisasContext *ctx, int gprn, int sprn)
1039{
1040 gen_helper_fixup_thrm(cpu_env);
1041 gen_load_spr(cpu_gpr[gprn], sprn);
1042 spr_load_dump_spr(sprn);
1043}
1044#endif
1045
1046#if !defined(CONFIG_USER_ONLY)
1047void spr_write_e500_l1csr0(DisasContext *ctx, int sprn, int gprn)
1048{
1049 TCGv t0 = tcg_temp_new();
1050
1051 tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR0_DCE | L1CSR0_CPE);
1052 gen_store_spr(sprn, t0);
1053 tcg_temp_free(t0);
1054}
1055
1056void spr_write_e500_l1csr1(DisasContext *ctx, int sprn, int gprn)
1057{
1058 TCGv t0 = tcg_temp_new();
1059
1060 tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR1_ICE | L1CSR1_CPE);
1061 gen_store_spr(sprn, t0);
1062 tcg_temp_free(t0);
1063}
1064
1065void spr_write_e500_l2csr0(DisasContext *ctx, int sprn, int gprn)
1066{
1067 TCGv t0 = tcg_temp_new();
1068
1069 tcg_gen_andi_tl(t0, cpu_gpr[gprn],
1070 ~(E500_L2CSR0_L2FI | E500_L2CSR0_L2FL | E500_L2CSR0_L2LFC));
1071 gen_store_spr(sprn, t0);
1072 tcg_temp_free(t0);
1073}
1074
1075void spr_write_booke206_mmucsr0(DisasContext *ctx, int sprn, int gprn)
1076{
1077 gen_helper_booke206_tlbflush(cpu_env, cpu_gpr[gprn]);
1078}
1079
1080void spr_write_booke_pid(DisasContext *ctx, int sprn, int gprn)
1081{
1082 TCGv_i32 t0 = tcg_const_i32(sprn);
1083 gen_helper_booke_setpid(cpu_env, t0, cpu_gpr[gprn]);
1084 tcg_temp_free_i32(t0);
1085}
1086void spr_write_eplc(DisasContext *ctx, int sprn, int gprn)
1087{
1088 gen_helper_booke_set_eplc(cpu_env, cpu_gpr[gprn]);
1089}
1090void spr_write_epsc(DisasContext *ctx, int sprn, int gprn)
1091{
1092 gen_helper_booke_set_epsc(cpu_env, cpu_gpr[gprn]);
1093}
1094
1095#endif
1096
1097#if !defined(CONFIG_USER_ONLY)
1098void spr_write_mas73(DisasContext *ctx, int sprn, int gprn)
1099{
1100 TCGv val = tcg_temp_new();
1101 tcg_gen_ext32u_tl(val, cpu_gpr[gprn]);
1102 gen_store_spr(SPR_BOOKE_MAS3, val);
1103 tcg_gen_shri_tl(val, cpu_gpr[gprn], 32);
1104 gen_store_spr(SPR_BOOKE_MAS7, val);
1105 tcg_temp_free(val);
1106}
1107
1108void spr_read_mas73(DisasContext *ctx, int gprn, int sprn)
1109{
1110 TCGv mas7 = tcg_temp_new();
1111 TCGv mas3 = tcg_temp_new();
1112 gen_load_spr(mas7, SPR_BOOKE_MAS7);
1113 tcg_gen_shli_tl(mas7, mas7, 32);
1114 gen_load_spr(mas3, SPR_BOOKE_MAS3);
1115 tcg_gen_or_tl(cpu_gpr[gprn], mas3, mas7);
1116 tcg_temp_free(mas3);
1117 tcg_temp_free(mas7);
1118}
1119
1120#endif
1121
1122#ifdef TARGET_PPC64
1123static void gen_fscr_facility_check(DisasContext *ctx, int facility_sprn,
1124 int bit, int sprn, int cause)
1125{
1126 TCGv_i32 t1 = tcg_const_i32(bit);
1127 TCGv_i32 t2 = tcg_const_i32(sprn);
1128 TCGv_i32 t3 = tcg_const_i32(cause);
1129
1130 gen_helper_fscr_facility_check(cpu_env, t1, t2, t3);
1131
1132 tcg_temp_free_i32(t3);
1133 tcg_temp_free_i32(t2);
1134 tcg_temp_free_i32(t1);
1135}
1136
1137static void gen_msr_facility_check(DisasContext *ctx, int facility_sprn,
1138 int bit, int sprn, int cause)
1139{
1140 TCGv_i32 t1 = tcg_const_i32(bit);
1141 TCGv_i32 t2 = tcg_const_i32(sprn);
1142 TCGv_i32 t3 = tcg_const_i32(cause);
1143
1144 gen_helper_msr_facility_check(cpu_env, t1, t2, t3);
1145
1146 tcg_temp_free_i32(t3);
1147 tcg_temp_free_i32(t2);
1148 tcg_temp_free_i32(t1);
1149}
1150
1151void spr_read_prev_upper32(DisasContext *ctx, int gprn, int sprn)
1152{
1153 TCGv spr_up = tcg_temp_new();
1154 TCGv spr = tcg_temp_new();
1155
1156 gen_load_spr(spr, sprn - 1);
1157 tcg_gen_shri_tl(spr_up, spr, 32);
1158 tcg_gen_ext32u_tl(cpu_gpr[gprn], spr_up);
1159
1160 tcg_temp_free(spr);
1161 tcg_temp_free(spr_up);
1162}
1163
1164void spr_write_prev_upper32(DisasContext *ctx, int sprn, int gprn)
1165{
1166 TCGv spr = tcg_temp_new();
1167
1168 gen_load_spr(spr, sprn - 1);
1169 tcg_gen_deposit_tl(spr, spr, cpu_gpr[gprn], 32, 32);
1170 gen_store_spr(sprn - 1, spr);
1171
1172 tcg_temp_free(spr);
1173}
1174
1175#if !defined(CONFIG_USER_ONLY)
1176void spr_write_hmer(DisasContext *ctx, int sprn, int gprn)
1177{
1178 TCGv hmer = tcg_temp_new();
1179
1180 gen_load_spr(hmer, sprn);
1181 tcg_gen_and_tl(hmer, cpu_gpr[gprn], hmer);
1182 gen_store_spr(sprn, hmer);
1183 spr_store_dump_spr(sprn);
1184 tcg_temp_free(hmer);
1185}
1186
1187void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn)
1188{
1189 gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]);
1190}
1191#endif
1192
1193void spr_read_tar(DisasContext *ctx, int gprn, int sprn)
1194{
1195 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_TAR, sprn, FSCR_IC_TAR);
1196 spr_read_generic(ctx, gprn, sprn);
1197}
1198
1199void spr_write_tar(DisasContext *ctx, int sprn, int gprn)
1200{
1201 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_TAR, sprn, FSCR_IC_TAR);
1202 spr_write_generic(ctx, sprn, gprn);
1203}
1204
1205void spr_read_tm(DisasContext *ctx, int gprn, int sprn)
1206{
1207 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1208 spr_read_generic(ctx, gprn, sprn);
1209}
1210
1211void spr_write_tm(DisasContext *ctx, int sprn, int gprn)
1212{
1213 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1214 spr_write_generic(ctx, sprn, gprn);
1215}
1216
1217void spr_read_tm_upper32(DisasContext *ctx, int gprn, int sprn)
1218{
1219 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1220 spr_read_prev_upper32(ctx, gprn, sprn);
1221}
1222
1223void spr_write_tm_upper32(DisasContext *ctx, int sprn, int gprn)
1224{
1225 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1226 spr_write_prev_upper32(ctx, sprn, gprn);
1227}
1228
1229void spr_read_ebb(DisasContext *ctx, int gprn, int sprn)
1230{
1231 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1232 spr_read_generic(ctx, gprn, sprn);
1233}
1234
1235void spr_write_ebb(DisasContext *ctx, int sprn, int gprn)
1236{
1237 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1238 spr_write_generic(ctx, sprn, gprn);
1239}
1240
1241void spr_read_ebb_upper32(DisasContext *ctx, int gprn, int sprn)
1242{
1243 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1244 spr_read_prev_upper32(ctx, gprn, sprn);
1245}
1246
1247void spr_write_ebb_upper32(DisasContext *ctx, int sprn, int gprn)
1248{
1249 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1250 spr_write_prev_upper32(ctx, sprn, gprn);
1251}
1252#endif
1253
1254#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
1255GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
1256
1257#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
1258GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
1259
1260#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
1261GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
1262
1263#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
1264GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
1265
1266#define GEN_HANDLER_E_2(name, opc1, opc2, opc3, opc4, inval, type, type2) \
1267GEN_OPCODE3(name, opc1, opc2, opc3, opc4, inval, type, type2)
1268
1269#define GEN_HANDLER2_E_2(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2) \
1270GEN_OPCODE4(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2)
1271
1272typedef struct opcode_t {
1273 unsigned char opc1, opc2, opc3, opc4;
1274#if HOST_LONG_BITS == 64
1275 unsigned char pad[4];
1276#endif
1277 opc_handler_t handler;
1278 const char *oname;
1279} opcode_t;
1280
1281static void gen_priv_opc(DisasContext *ctx)
1282{
1283 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1284}
1285
1286
1287#define GEN_PRIV(CTX) \
1288 do { \
1289 gen_priv_opc(CTX); return; \
1290 } while (0)
1291
1292#if defined(CONFIG_USER_ONLY)
1293#define CHK_HV(CTX) GEN_PRIV(CTX)
1294#define CHK_SV(CTX) GEN_PRIV(CTX)
1295#define CHK_HVRM(CTX) GEN_PRIV(CTX)
1296#else
1297#define CHK_HV(CTX) \
1298 do { \
1299 if (unlikely(ctx->pr || !ctx->hv)) {\
1300 GEN_PRIV(CTX); \
1301 } \
1302 } while (0)
1303#define CHK_SV(CTX) \
1304 do { \
1305 if (unlikely(ctx->pr)) { \
1306 GEN_PRIV(CTX); \
1307 } \
1308 } while (0)
1309#define CHK_HVRM(CTX) \
1310 do { \
1311 if (unlikely(ctx->pr || !ctx->hv || ctx->dr)) { \
1312 GEN_PRIV(CTX); \
1313 } \
1314 } while (0)
1315#endif
1316
1317#define CHK_NONE(CTX)
1318
1319
1320
1321
1322#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
1323{ \
1324 .opc1 = op1, \
1325 .opc2 = op2, \
1326 .opc3 = op3, \
1327 .opc4 = 0xff, \
1328 .handler = { \
1329 .inval1 = invl, \
1330 .type = _typ, \
1331 .type2 = _typ2, \
1332 .handler = &gen_##name, \
1333 }, \
1334 .oname = stringify(name), \
1335}
1336#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
1337{ \
1338 .opc1 = op1, \
1339 .opc2 = op2, \
1340 .opc3 = op3, \
1341 .opc4 = 0xff, \
1342 .handler = { \
1343 .inval1 = invl1, \
1344 .inval2 = invl2, \
1345 .type = _typ, \
1346 .type2 = _typ2, \
1347 .handler = &gen_##name, \
1348 }, \
1349 .oname = stringify(name), \
1350}
1351#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
1352{ \
1353 .opc1 = op1, \
1354 .opc2 = op2, \
1355 .opc3 = op3, \
1356 .opc4 = 0xff, \
1357 .handler = { \
1358 .inval1 = invl, \
1359 .type = _typ, \
1360 .type2 = _typ2, \
1361 .handler = &gen_##name, \
1362 }, \
1363 .oname = onam, \
1364}
1365#define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2) \
1366{ \
1367 .opc1 = op1, \
1368 .opc2 = op2, \
1369 .opc3 = op3, \
1370 .opc4 = op4, \
1371 .handler = { \
1372 .inval1 = invl, \
1373 .type = _typ, \
1374 .type2 = _typ2, \
1375 .handler = &gen_##name, \
1376 }, \
1377 .oname = stringify(name), \
1378}
1379#define GEN_OPCODE4(name, onam, op1, op2, op3, op4, invl, _typ, _typ2) \
1380{ \
1381 .opc1 = op1, \
1382 .opc2 = op2, \
1383 .opc3 = op3, \
1384 .opc4 = op4, \
1385 .handler = { \
1386 .inval1 = invl, \
1387 .type = _typ, \
1388 .type2 = _typ2, \
1389 .handler = &gen_##name, \
1390 }, \
1391 .oname = onam, \
1392}
1393
1394
1395static void gen_invalid(DisasContext *ctx)
1396{
1397 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1398}
1399
1400static opc_handler_t invalid_handler = {
1401 .inval1 = 0xFFFFFFFF,
1402 .inval2 = 0xFFFFFFFF,
1403 .type = PPC_NONE,
1404 .type2 = PPC_NONE,
1405 .handler = gen_invalid,
1406};
1407
1408
1409
1410static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
1411{
1412 TCGv t0 = tcg_temp_new();
1413 TCGv t1 = tcg_temp_new();
1414 TCGv_i32 t = tcg_temp_new_i32();
1415
1416 tcg_gen_movi_tl(t0, CRF_EQ);
1417 tcg_gen_movi_tl(t1, CRF_LT);
1418 tcg_gen_movcond_tl((s ? TCG_COND_LT : TCG_COND_LTU),
1419 t0, arg0, arg1, t1, t0);
1420 tcg_gen_movi_tl(t1, CRF_GT);
1421 tcg_gen_movcond_tl((s ? TCG_COND_GT : TCG_COND_GTU),
1422 t0, arg0, arg1, t1, t0);
1423
1424 tcg_gen_trunc_tl_i32(t, t0);
1425 tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
1426 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t);
1427
1428 tcg_temp_free(t0);
1429 tcg_temp_free(t1);
1430 tcg_temp_free_i32(t);
1431}
1432
1433static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
1434{
1435 TCGv t0 = tcg_const_tl(arg1);
1436 gen_op_cmp(arg0, t0, s, crf);
1437 tcg_temp_free(t0);
1438}
1439
1440static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
1441{
1442 TCGv t0, t1;
1443 t0 = tcg_temp_new();
1444 t1 = tcg_temp_new();
1445 if (s) {
1446 tcg_gen_ext32s_tl(t0, arg0);
1447 tcg_gen_ext32s_tl(t1, arg1);
1448 } else {
1449 tcg_gen_ext32u_tl(t0, arg0);
1450 tcg_gen_ext32u_tl(t1, arg1);
1451 }
1452 gen_op_cmp(t0, t1, s, crf);
1453 tcg_temp_free(t1);
1454 tcg_temp_free(t0);
1455}
1456
1457static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
1458{
1459 TCGv t0 = tcg_const_tl(arg1);
1460 gen_op_cmp32(arg0, t0, s, crf);
1461 tcg_temp_free(t0);
1462}
1463
1464static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
1465{
1466 if (NARROW_MODE(ctx)) {
1467 gen_op_cmpi32(reg, 0, 1, 0);
1468 } else {
1469 gen_op_cmpi(reg, 0, 1, 0);
1470 }
1471}
1472
1473
1474static void gen_cmprb(DisasContext *ctx)
1475{
1476 TCGv_i32 src1 = tcg_temp_new_i32();
1477 TCGv_i32 src2 = tcg_temp_new_i32();
1478 TCGv_i32 src2lo = tcg_temp_new_i32();
1479 TCGv_i32 src2hi = tcg_temp_new_i32();
1480 TCGv_i32 crf = cpu_crf[crfD(ctx->opcode)];
1481
1482 tcg_gen_trunc_tl_i32(src1, cpu_gpr[rA(ctx->opcode)]);
1483 tcg_gen_trunc_tl_i32(src2, cpu_gpr[rB(ctx->opcode)]);
1484
1485 tcg_gen_andi_i32(src1, src1, 0xFF);
1486 tcg_gen_ext8u_i32(src2lo, src2);
1487 tcg_gen_shri_i32(src2, src2, 8);
1488 tcg_gen_ext8u_i32(src2hi, src2);
1489
1490 tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
1491 tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
1492 tcg_gen_and_i32(crf, src2lo, src2hi);
1493
1494 if (ctx->opcode & 0x00200000) {
1495 tcg_gen_shri_i32(src2, src2, 8);
1496 tcg_gen_ext8u_i32(src2lo, src2);
1497 tcg_gen_shri_i32(src2, src2, 8);
1498 tcg_gen_ext8u_i32(src2hi, src2);
1499 tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
1500 tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
1501 tcg_gen_and_i32(src2lo, src2lo, src2hi);
1502 tcg_gen_or_i32(crf, crf, src2lo);
1503 }
1504 tcg_gen_shli_i32(crf, crf, CRF_GT_BIT);
1505 tcg_temp_free_i32(src1);
1506 tcg_temp_free_i32(src2);
1507 tcg_temp_free_i32(src2lo);
1508 tcg_temp_free_i32(src2hi);
1509}
1510
1511#if defined(TARGET_PPC64)
1512
1513static void gen_cmpeqb(DisasContext *ctx)
1514{
1515 gen_helper_cmpeqb(cpu_crf[crfD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1516 cpu_gpr[rB(ctx->opcode)]);
1517}
1518#endif
1519
1520
1521static void gen_isel(DisasContext *ctx)
1522{
1523 uint32_t bi = rC(ctx->opcode);
1524 uint32_t mask = 0x08 >> (bi & 0x03);
1525 TCGv t0 = tcg_temp_new();
1526 TCGv zr;
1527
1528 tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
1529 tcg_gen_andi_tl(t0, t0, mask);
1530
1531 zr = tcg_const_tl(0);
1532 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr,
1533 rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr,
1534 cpu_gpr[rB(ctx->opcode)]);
1535 tcg_temp_free(zr);
1536 tcg_temp_free(t0);
1537}
1538
1539
1540static void gen_cmpb(DisasContext *ctx)
1541{
1542 gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
1543 cpu_gpr[rB(ctx->opcode)]);
1544}
1545
1546
1547
1548static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
1549 TCGv arg1, TCGv arg2, int sub)
1550{
1551 TCGv t0 = tcg_temp_new();
1552
1553 tcg_gen_xor_tl(cpu_ov, arg0, arg2);
1554 tcg_gen_xor_tl(t0, arg1, arg2);
1555 if (sub) {
1556 tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
1557 } else {
1558 tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
1559 }
1560 tcg_temp_free(t0);
1561 if (NARROW_MODE(ctx)) {
1562 tcg_gen_extract_tl(cpu_ov, cpu_ov, 31, 1);
1563 if (is_isa300(ctx)) {
1564 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
1565 }
1566 } else {
1567 if (is_isa300(ctx)) {
1568 tcg_gen_extract_tl(cpu_ov32, cpu_ov, 31, 1);
1569 }
1570 tcg_gen_extract_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1, 1);
1571 }
1572 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1573}
1574
1575static inline void gen_op_arith_compute_ca32(DisasContext *ctx,
1576 TCGv res, TCGv arg0, TCGv arg1,
1577 TCGv ca32, int sub)
1578{
1579 TCGv t0;
1580
1581 if (!is_isa300(ctx)) {
1582 return;
1583 }
1584
1585 t0 = tcg_temp_new();
1586 if (sub) {
1587 tcg_gen_eqv_tl(t0, arg0, arg1);
1588 } else {
1589 tcg_gen_xor_tl(t0, arg0, arg1);
1590 }
1591 tcg_gen_xor_tl(t0, t0, res);
1592 tcg_gen_extract_tl(ca32, t0, 32, 1);
1593 tcg_temp_free(t0);
1594}
1595
1596
1597static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
1598 TCGv arg2, TCGv ca, TCGv ca32,
1599 bool add_ca, bool compute_ca,
1600 bool compute_ov, bool compute_rc0)
1601{
1602 TCGv t0 = ret;
1603
1604 if (compute_ca || compute_ov) {
1605 t0 = tcg_temp_new();
1606 }
1607
1608 if (compute_ca) {
1609 if (NARROW_MODE(ctx)) {
1610
1611
1612
1613
1614
1615 TCGv t1 = tcg_temp_new();
1616 tcg_gen_xor_tl(t1, arg1, arg2);
1617 tcg_gen_add_tl(t0, arg1, arg2);
1618 if (add_ca) {
1619 tcg_gen_add_tl(t0, t0, ca);
1620 }
1621 tcg_gen_xor_tl(ca, t0, t1);
1622 tcg_temp_free(t1);
1623 tcg_gen_extract_tl(ca, ca, 32, 1);
1624 if (is_isa300(ctx)) {
1625 tcg_gen_mov_tl(ca32, ca);
1626 }
1627 } else {
1628 TCGv zero = tcg_const_tl(0);
1629 if (add_ca) {
1630 tcg_gen_add2_tl(t0, ca, arg1, zero, ca, zero);
1631 tcg_gen_add2_tl(t0, ca, t0, ca, arg2, zero);
1632 } else {
1633 tcg_gen_add2_tl(t0, ca, arg1, zero, arg2, zero);
1634 }
1635 gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, ca32, 0);
1636 tcg_temp_free(zero);
1637 }
1638 } else {
1639 tcg_gen_add_tl(t0, arg1, arg2);
1640 if (add_ca) {
1641 tcg_gen_add_tl(t0, t0, ca);
1642 }
1643 }
1644
1645 if (compute_ov) {
1646 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
1647 }
1648 if (unlikely(compute_rc0)) {
1649 gen_set_Rc0(ctx, t0);
1650 }
1651
1652 if (t0 != ret) {
1653 tcg_gen_mov_tl(ret, t0);
1654 tcg_temp_free(t0);
1655 }
1656}
1657
1658#define GEN_INT_ARITH_ADD(name, opc3, ca, add_ca, compute_ca, compute_ov) \
1659static void glue(gen_, name)(DisasContext *ctx) \
1660{ \
1661 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
1662 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1663 ca, glue(ca, 32), \
1664 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
1665}
1666
1667#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, ca, \
1668 add_ca, compute_ca, compute_ov) \
1669static void glue(gen_, name)(DisasContext *ctx) \
1670{ \
1671 TCGv t0 = tcg_const_tl(const_val); \
1672 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
1673 cpu_gpr[rA(ctx->opcode)], t0, \
1674 ca, glue(ca, 32), \
1675 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
1676 tcg_temp_free(t0); \
1677}
1678
1679
1680GEN_INT_ARITH_ADD(add, 0x08, cpu_ca, 0, 0, 0)
1681GEN_INT_ARITH_ADD(addo, 0x18, cpu_ca, 0, 0, 1)
1682
1683GEN_INT_ARITH_ADD(addc, 0x00, cpu_ca, 0, 1, 0)
1684GEN_INT_ARITH_ADD(addco, 0x10, cpu_ca, 0, 1, 1)
1685
1686GEN_INT_ARITH_ADD(adde, 0x04, cpu_ca, 1, 1, 0)
1687GEN_INT_ARITH_ADD(addeo, 0x14, cpu_ca, 1, 1, 1)
1688
1689GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, cpu_ca, 1, 1, 0)
1690GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, cpu_ca, 1, 1, 1)
1691
1692GEN_INT_ARITH_ADD(addex, 0x05, cpu_ov, 1, 1, 0);
1693
1694GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, cpu_ca, 1, 1, 0)
1695GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, cpu_ca, 1, 1, 1)
1696
1697static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
1698{
1699 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
1700 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1701 c, cpu_ca, cpu_ca32, 0, 1, 0, compute_rc0);
1702 tcg_temp_free(c);
1703}
1704
1705static void gen_addic(DisasContext *ctx)
1706{
1707 gen_op_addic(ctx, 0);
1708}
1709
1710static void gen_addic_(DisasContext *ctx)
1711{
1712 gen_op_addic(ctx, 1);
1713}
1714
1715static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
1716 TCGv arg2, int sign, int compute_ov)
1717{
1718 TCGv_i32 t0 = tcg_temp_new_i32();
1719 TCGv_i32 t1 = tcg_temp_new_i32();
1720 TCGv_i32 t2 = tcg_temp_new_i32();
1721 TCGv_i32 t3 = tcg_temp_new_i32();
1722
1723 tcg_gen_trunc_tl_i32(t0, arg1);
1724 tcg_gen_trunc_tl_i32(t1, arg2);
1725 if (sign) {
1726 tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN);
1727 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1);
1728 tcg_gen_and_i32(t2, t2, t3);
1729 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0);
1730 tcg_gen_or_i32(t2, t2, t3);
1731 tcg_gen_movi_i32(t3, 0);
1732 tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
1733 tcg_gen_div_i32(t3, t0, t1);
1734 tcg_gen_extu_i32_tl(ret, t3);
1735 } else {
1736 tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t1, 0);
1737 tcg_gen_movi_i32(t3, 0);
1738 tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
1739 tcg_gen_divu_i32(t3, t0, t1);
1740 tcg_gen_extu_i32_tl(ret, t3);
1741 }
1742 if (compute_ov) {
1743 tcg_gen_extu_i32_tl(cpu_ov, t2);
1744 if (is_isa300(ctx)) {
1745 tcg_gen_extu_i32_tl(cpu_ov32, t2);
1746 }
1747 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1748 }
1749 tcg_temp_free_i32(t0);
1750 tcg_temp_free_i32(t1);
1751 tcg_temp_free_i32(t2);
1752 tcg_temp_free_i32(t3);
1753
1754 if (unlikely(Rc(ctx->opcode) != 0)) {
1755 gen_set_Rc0(ctx, ret);
1756 }
1757}
1758
1759#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
1760static void glue(gen_, name)(DisasContext *ctx) \
1761{ \
1762 gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
1763 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1764 sign, compute_ov); \
1765}
1766
1767GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
1768GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
1769
1770GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1771GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
1772
1773
1774#define GEN_DIVE(name, hlpr, compute_ov) \
1775static void gen_##name(DisasContext *ctx) \
1776{ \
1777 TCGv_i32 t0 = tcg_const_i32(compute_ov); \
1778 gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env, \
1779 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \
1780 tcg_temp_free_i32(t0); \
1781 if (unlikely(Rc(ctx->opcode) != 0)) { \
1782 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
1783 } \
1784}
1785
1786GEN_DIVE(divweu, divweu, 0);
1787GEN_DIVE(divweuo, divweu, 1);
1788GEN_DIVE(divwe, divwe, 0);
1789GEN_DIVE(divweo, divwe, 1);
1790
1791#if defined(TARGET_PPC64)
1792static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
1793 TCGv arg2, int sign, int compute_ov)
1794{
1795 TCGv_i64 t0 = tcg_temp_new_i64();
1796 TCGv_i64 t1 = tcg_temp_new_i64();
1797 TCGv_i64 t2 = tcg_temp_new_i64();
1798 TCGv_i64 t3 = tcg_temp_new_i64();
1799
1800 tcg_gen_mov_i64(t0, arg1);
1801 tcg_gen_mov_i64(t1, arg2);
1802 if (sign) {
1803 tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN);
1804 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1);
1805 tcg_gen_and_i64(t2, t2, t3);
1806 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0);
1807 tcg_gen_or_i64(t2, t2, t3);
1808 tcg_gen_movi_i64(t3, 0);
1809 tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
1810 tcg_gen_div_i64(ret, t0, t1);
1811 } else {
1812 tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t1, 0);
1813 tcg_gen_movi_i64(t3, 0);
1814 tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
1815 tcg_gen_divu_i64(ret, t0, t1);
1816 }
1817 if (compute_ov) {
1818 tcg_gen_mov_tl(cpu_ov, t2);
1819 if (is_isa300(ctx)) {
1820 tcg_gen_mov_tl(cpu_ov32, t2);
1821 }
1822 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1823 }
1824 tcg_temp_free_i64(t0);
1825 tcg_temp_free_i64(t1);
1826 tcg_temp_free_i64(t2);
1827 tcg_temp_free_i64(t3);
1828
1829 if (unlikely(Rc(ctx->opcode) != 0)) {
1830 gen_set_Rc0(ctx, ret);
1831 }
1832}
1833
1834#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
1835static void glue(gen_, name)(DisasContext *ctx) \
1836{ \
1837 gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
1838 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1839 sign, compute_ov); \
1840}
1841
1842GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1843GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1844
1845GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1846GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1847
1848GEN_DIVE(divdeu, divdeu, 0);
1849GEN_DIVE(divdeuo, divdeu, 1);
1850GEN_DIVE(divde, divde, 0);
1851GEN_DIVE(divdeo, divde, 1);
1852#endif
1853
1854static inline void gen_op_arith_modw(DisasContext *ctx, TCGv ret, TCGv arg1,
1855 TCGv arg2, int sign)
1856{
1857 TCGv_i32 t0 = tcg_temp_new_i32();
1858 TCGv_i32 t1 = tcg_temp_new_i32();
1859
1860 tcg_gen_trunc_tl_i32(t0, arg1);
1861 tcg_gen_trunc_tl_i32(t1, arg2);
1862 if (sign) {
1863 TCGv_i32 t2 = tcg_temp_new_i32();
1864 TCGv_i32 t3 = tcg_temp_new_i32();
1865 tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN);
1866 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1);
1867 tcg_gen_and_i32(t2, t2, t3);
1868 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0);
1869 tcg_gen_or_i32(t2, t2, t3);
1870 tcg_gen_movi_i32(t3, 0);
1871 tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
1872 tcg_gen_rem_i32(t3, t0, t1);
1873 tcg_gen_ext_i32_tl(ret, t3);
1874 tcg_temp_free_i32(t2);
1875 tcg_temp_free_i32(t3);
1876 } else {
1877 TCGv_i32 t2 = tcg_const_i32(1);
1878 TCGv_i32 t3 = tcg_const_i32(0);
1879 tcg_gen_movcond_i32(TCG_COND_EQ, t1, t1, t3, t2, t1);
1880 tcg_gen_remu_i32(t3, t0, t1);
1881 tcg_gen_extu_i32_tl(ret, t3);
1882 tcg_temp_free_i32(t2);
1883 tcg_temp_free_i32(t3);
1884 }
1885 tcg_temp_free_i32(t0);
1886 tcg_temp_free_i32(t1);
1887}
1888
1889#define GEN_INT_ARITH_MODW(name, opc3, sign) \
1890static void glue(gen_, name)(DisasContext *ctx) \
1891{ \
1892 gen_op_arith_modw(ctx, cpu_gpr[rD(ctx->opcode)], \
1893 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1894 sign); \
1895}
1896
1897GEN_INT_ARITH_MODW(moduw, 0x08, 0);
1898GEN_INT_ARITH_MODW(modsw, 0x18, 1);
1899
1900#if defined(TARGET_PPC64)
1901static inline void gen_op_arith_modd(DisasContext *ctx, TCGv ret, TCGv arg1,
1902 TCGv arg2, int sign)
1903{
1904 TCGv_i64 t0 = tcg_temp_new_i64();
1905 TCGv_i64 t1 = tcg_temp_new_i64();
1906
1907 tcg_gen_mov_i64(t0, arg1);
1908 tcg_gen_mov_i64(t1, arg2);
1909 if (sign) {
1910 TCGv_i64 t2 = tcg_temp_new_i64();
1911 TCGv_i64 t3 = tcg_temp_new_i64();
1912 tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN);
1913 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1);
1914 tcg_gen_and_i64(t2, t2, t3);
1915 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0);
1916 tcg_gen_or_i64(t2, t2, t3);
1917 tcg_gen_movi_i64(t3, 0);
1918 tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
1919 tcg_gen_rem_i64(ret, t0, t1);
1920 tcg_temp_free_i64(t2);
1921 tcg_temp_free_i64(t3);
1922 } else {
1923 TCGv_i64 t2 = tcg_const_i64(1);
1924 TCGv_i64 t3 = tcg_const_i64(0);
1925 tcg_gen_movcond_i64(TCG_COND_EQ, t1, t1, t3, t2, t1);
1926 tcg_gen_remu_i64(ret, t0, t1);
1927 tcg_temp_free_i64(t2);
1928 tcg_temp_free_i64(t3);
1929 }
1930 tcg_temp_free_i64(t0);
1931 tcg_temp_free_i64(t1);
1932}
1933
1934#define GEN_INT_ARITH_MODD(name, opc3, sign) \
1935static void glue(gen_, name)(DisasContext *ctx) \
1936{ \
1937 gen_op_arith_modd(ctx, cpu_gpr[rD(ctx->opcode)], \
1938 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1939 sign); \
1940}
1941
1942GEN_INT_ARITH_MODD(modud, 0x08, 0);
1943GEN_INT_ARITH_MODD(modsd, 0x18, 1);
1944#endif
1945
1946
1947static void gen_mulhw(DisasContext *ctx)
1948{
1949 TCGv_i32 t0 = tcg_temp_new_i32();
1950 TCGv_i32 t1 = tcg_temp_new_i32();
1951
1952 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1953 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1954 tcg_gen_muls2_i32(t0, t1, t0, t1);
1955 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1956 tcg_temp_free_i32(t0);
1957 tcg_temp_free_i32(t1);
1958 if (unlikely(Rc(ctx->opcode) != 0)) {
1959 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1960 }
1961}
1962
1963
1964static void gen_mulhwu(DisasContext *ctx)
1965{
1966 TCGv_i32 t0 = tcg_temp_new_i32();
1967 TCGv_i32 t1 = tcg_temp_new_i32();
1968
1969 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1970 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1971 tcg_gen_mulu2_i32(t0, t1, t0, t1);
1972 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1973 tcg_temp_free_i32(t0);
1974 tcg_temp_free_i32(t1);
1975 if (unlikely(Rc(ctx->opcode) != 0)) {
1976 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1977 }
1978}
1979
1980
1981static void gen_mullw(DisasContext *ctx)
1982{
1983#if defined(TARGET_PPC64)
1984 TCGv_i64 t0, t1;
1985 t0 = tcg_temp_new_i64();
1986 t1 = tcg_temp_new_i64();
1987 tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1988 tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1989 tcg_gen_mul_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1990 tcg_temp_free(t0);
1991 tcg_temp_free(t1);
1992#else
1993 tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1994 cpu_gpr[rB(ctx->opcode)]);
1995#endif
1996 if (unlikely(Rc(ctx->opcode) != 0)) {
1997 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1998 }
1999}
2000
2001
2002static void gen_mullwo(DisasContext *ctx)
2003{
2004 TCGv_i32 t0 = tcg_temp_new_i32();
2005 TCGv_i32 t1 = tcg_temp_new_i32();
2006
2007 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
2008 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
2009 tcg_gen_muls2_i32(t0, t1, t0, t1);
2010#if defined(TARGET_PPC64)
2011 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
2012#else
2013 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0);
2014#endif
2015
2016 tcg_gen_sari_i32(t0, t0, 31);
2017 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
2018 tcg_gen_extu_i32_tl(cpu_ov, t0);
2019 if (is_isa300(ctx)) {
2020 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
2021 }
2022 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
2023
2024 tcg_temp_free_i32(t0);
2025 tcg_temp_free_i32(t1);
2026 if (unlikely(Rc(ctx->opcode) != 0)) {
2027 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2028 }
2029}
2030
2031
2032static void gen_mulli(DisasContext *ctx)
2033{
2034 tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2035 SIMM(ctx->opcode));
2036}
2037
2038#if defined(TARGET_PPC64)
2039
2040static void gen_mulhd(DisasContext *ctx)
2041{
2042 TCGv lo = tcg_temp_new();
2043 tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
2044 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2045 tcg_temp_free(lo);
2046 if (unlikely(Rc(ctx->opcode) != 0)) {
2047 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2048 }
2049}
2050
2051
2052static void gen_mulhdu(DisasContext *ctx)
2053{
2054 TCGv lo = tcg_temp_new();
2055 tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
2056 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2057 tcg_temp_free(lo);
2058 if (unlikely(Rc(ctx->opcode) != 0)) {
2059 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2060 }
2061}
2062
2063
2064static void gen_mulld(DisasContext *ctx)
2065{
2066 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2067 cpu_gpr[rB(ctx->opcode)]);
2068 if (unlikely(Rc(ctx->opcode) != 0)) {
2069 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2070 }
2071}
2072
2073
2074static void gen_mulldo(DisasContext *ctx)
2075{
2076 TCGv_i64 t0 = tcg_temp_new_i64();
2077 TCGv_i64 t1 = tcg_temp_new_i64();
2078
2079 tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)],
2080 cpu_gpr[rB(ctx->opcode)]);
2081 tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0);
2082
2083 tcg_gen_sari_i64(t0, t0, 63);
2084 tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
2085 if (is_isa300(ctx)) {
2086 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
2087 }
2088 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
2089
2090 tcg_temp_free_i64(t0);
2091 tcg_temp_free_i64(t1);
2092
2093 if (unlikely(Rc(ctx->opcode) != 0)) {
2094 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2095 }
2096}
2097#endif
2098
2099
2100static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
2101 TCGv arg2, bool add_ca, bool compute_ca,
2102 bool compute_ov, bool compute_rc0)
2103{
2104 TCGv t0 = ret;
2105
2106 if (compute_ca || compute_ov) {
2107 t0 = tcg_temp_new();
2108 }
2109
2110 if (compute_ca) {
2111
2112 if (NARROW_MODE(ctx)) {
2113
2114
2115
2116
2117
2118 TCGv inv1 = tcg_temp_new();
2119 TCGv t1 = tcg_temp_new();
2120 tcg_gen_not_tl(inv1, arg1);
2121 if (add_ca) {
2122 tcg_gen_add_tl(t0, arg2, cpu_ca);
2123 } else {
2124 tcg_gen_addi_tl(t0, arg2, 1);
2125 }
2126 tcg_gen_xor_tl(t1, arg2, inv1);
2127 tcg_gen_add_tl(t0, t0, inv1);
2128 tcg_temp_free(inv1);
2129 tcg_gen_xor_tl(cpu_ca, t0, t1);
2130 tcg_temp_free(t1);
2131 tcg_gen_extract_tl(cpu_ca, cpu_ca, 32, 1);
2132 if (is_isa300(ctx)) {
2133 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
2134 }
2135 } else if (add_ca) {
2136 TCGv zero, inv1 = tcg_temp_new();
2137 tcg_gen_not_tl(inv1, arg1);
2138 zero = tcg_const_tl(0);
2139 tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
2140 tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
2141 gen_op_arith_compute_ca32(ctx, t0, inv1, arg2, cpu_ca32, 0);
2142 tcg_temp_free(zero);
2143 tcg_temp_free(inv1);
2144 } else {
2145 tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
2146 tcg_gen_sub_tl(t0, arg2, arg1);
2147 gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, cpu_ca32, 1);
2148 }
2149 } else if (add_ca) {
2150
2151
2152
2153
2154 tcg_gen_sub_tl(t0, arg2, arg1);
2155 tcg_gen_add_tl(t0, t0, cpu_ca);
2156 tcg_gen_subi_tl(t0, t0, 1);
2157 } else {
2158 tcg_gen_sub_tl(t0, arg2, arg1);
2159 }
2160
2161 if (compute_ov) {
2162 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
2163 }
2164 if (unlikely(compute_rc0)) {
2165 gen_set_Rc0(ctx, t0);
2166 }
2167
2168 if (t0 != ret) {
2169 tcg_gen_mov_tl(ret, t0);
2170 tcg_temp_free(t0);
2171 }
2172}
2173
2174#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
2175static void glue(gen_, name)(DisasContext *ctx) \
2176{ \
2177 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
2178 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
2179 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
2180}
2181
2182#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
2183 add_ca, compute_ca, compute_ov) \
2184static void glue(gen_, name)(DisasContext *ctx) \
2185{ \
2186 TCGv t0 = tcg_const_tl(const_val); \
2187 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
2188 cpu_gpr[rA(ctx->opcode)], t0, \
2189 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
2190 tcg_temp_free(t0); \
2191}
2192
2193GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
2194GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
2195
2196GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
2197GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
2198
2199GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
2200GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
2201
2202GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
2203GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
2204
2205GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
2206GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
2207
2208
2209static void gen_subfic(DisasContext *ctx)
2210{
2211 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
2212 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2213 c, 0, 1, 0, 0);
2214 tcg_temp_free(c);
2215}
2216
2217
2218static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
2219{
2220 TCGv zero = tcg_const_tl(0);
2221 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2222 zero, 0, 0, compute_ov, Rc(ctx->opcode));
2223 tcg_temp_free(zero);
2224}
2225
2226static void gen_neg(DisasContext *ctx)
2227{
2228 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
2229 if (unlikely(Rc(ctx->opcode))) {
2230 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2231 }
2232}
2233
2234static void gen_nego(DisasContext *ctx)
2235{
2236 gen_op_arith_neg(ctx, 1);
2237}
2238
2239
2240#define GEN_LOGICAL2(name, tcg_op, opc, type) \
2241static void glue(gen_, name)(DisasContext *ctx) \
2242{ \
2243 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
2244 cpu_gpr[rB(ctx->opcode)]); \
2245 if (unlikely(Rc(ctx->opcode) != 0)) \
2246 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
2247}
2248
2249#define GEN_LOGICAL1(name, tcg_op, opc, type) \
2250static void glue(gen_, name)(DisasContext *ctx) \
2251{ \
2252 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
2253 if (unlikely(Rc(ctx->opcode) != 0)) \
2254 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
2255}
2256
2257
2258GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
2259
2260GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
2261
2262
2263static void gen_andi_(DisasContext *ctx)
2264{
2265 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2266 UIMM(ctx->opcode));
2267 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2268}
2269
2270
2271static void gen_andis_(DisasContext *ctx)
2272{
2273 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2274 UIMM(ctx->opcode) << 16);
2275 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2276}
2277
2278
2279static void gen_cntlzw(DisasContext *ctx)
2280{
2281 TCGv_i32 t = tcg_temp_new_i32();
2282
2283 tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]);
2284 tcg_gen_clzi_i32(t, t, 32);
2285 tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t);
2286 tcg_temp_free_i32(t);
2287
2288 if (unlikely(Rc(ctx->opcode) != 0)) {
2289 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2290 }
2291}
2292
2293
2294static void gen_cnttzw(DisasContext *ctx)
2295{
2296 TCGv_i32 t = tcg_temp_new_i32();
2297
2298 tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]);
2299 tcg_gen_ctzi_i32(t, t, 32);
2300 tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t);
2301 tcg_temp_free_i32(t);
2302
2303 if (unlikely(Rc(ctx->opcode) != 0)) {
2304 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2305 }
2306}
2307
2308
2309GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
2310
2311GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
2312
2313GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
2314
2315GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
2316
2317GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
2318
2319#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
2320static void gen_pause(DisasContext *ctx)
2321{
2322 TCGv_i32 t0 = tcg_const_i32(0);
2323 tcg_gen_st_i32(t0, cpu_env,
2324 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
2325 tcg_temp_free_i32(t0);
2326
2327
2328 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
2329}
2330#endif
2331
2332
2333static void gen_or(DisasContext *ctx)
2334{
2335 int rs, ra, rb;
2336
2337 rs = rS(ctx->opcode);
2338 ra = rA(ctx->opcode);
2339 rb = rB(ctx->opcode);
2340
2341 if (rs != ra || rs != rb) {
2342 if (rs != rb) {
2343 tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
2344 } else {
2345 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
2346 }
2347 if (unlikely(Rc(ctx->opcode) != 0)) {
2348 gen_set_Rc0(ctx, cpu_gpr[ra]);
2349 }
2350 } else if (unlikely(Rc(ctx->opcode) != 0)) {
2351 gen_set_Rc0(ctx, cpu_gpr[rs]);
2352#if defined(TARGET_PPC64)
2353 } else if (rs != 0) {
2354 int prio = 0;
2355
2356 switch (rs) {
2357 case 1:
2358
2359 prio = 2;
2360 break;
2361 case 6:
2362
2363 prio = 3;
2364 break;
2365 case 2:
2366
2367 prio = 4;
2368 break;
2369#if !defined(CONFIG_USER_ONLY)
2370 case 31:
2371 if (!ctx->pr) {
2372
2373 prio = 1;
2374 }
2375 break;
2376 case 5:
2377 if (!ctx->pr) {
2378
2379 prio = 5;
2380 }
2381 break;
2382 case 3:
2383 if (!ctx->pr) {
2384
2385 prio = 6;
2386 }
2387 break;
2388 case 7:
2389 if (ctx->hv && !ctx->pr) {
2390
2391 prio = 7;
2392 }
2393 break;
2394#endif
2395 default:
2396 break;
2397 }
2398 if (prio) {
2399 TCGv t0 = tcg_temp_new();
2400 gen_load_spr(t0, SPR_PPR);
2401 tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
2402 tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
2403 gen_store_spr(SPR_PPR, t0);
2404 tcg_temp_free(t0);
2405 }
2406#if !defined(CONFIG_USER_ONLY)
2407
2408
2409
2410
2411
2412
2413 gen_pause(ctx);
2414#endif
2415#endif
2416 }
2417}
2418
2419GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
2420
2421
2422static void gen_xor(DisasContext *ctx)
2423{
2424
2425 if (rS(ctx->opcode) != rB(ctx->opcode)) {
2426 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2427 cpu_gpr[rB(ctx->opcode)]);
2428 } else {
2429 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
2430 }
2431 if (unlikely(Rc(ctx->opcode) != 0)) {
2432 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2433 }
2434}
2435
2436
2437static void gen_ori(DisasContext *ctx)
2438{
2439 target_ulong uimm = UIMM(ctx->opcode);
2440
2441 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
2442 return;
2443 }
2444 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
2445}
2446
2447
2448static void gen_oris(DisasContext *ctx)
2449{
2450 target_ulong uimm = UIMM(ctx->opcode);
2451
2452 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
2453
2454 return;
2455 }
2456 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2457 uimm << 16);
2458}
2459
2460
2461static void gen_xori(DisasContext *ctx)
2462{
2463 target_ulong uimm = UIMM(ctx->opcode);
2464
2465 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
2466
2467 return;
2468 }
2469 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
2470}
2471
2472
2473static void gen_xoris(DisasContext *ctx)
2474{
2475 target_ulong uimm = UIMM(ctx->opcode);
2476
2477 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
2478
2479 return;
2480 }
2481 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2482 uimm << 16);
2483}
2484
2485
2486static void gen_popcntb(DisasContext *ctx)
2487{
2488 gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2489}
2490
2491static void gen_popcntw(DisasContext *ctx)
2492{
2493#if defined(TARGET_PPC64)
2494 gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2495#else
2496 tcg_gen_ctpop_i32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2497#endif
2498}
2499
2500#if defined(TARGET_PPC64)
2501
2502static void gen_popcntd(DisasContext *ctx)
2503{
2504 tcg_gen_ctpop_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2505}
2506#endif
2507
2508
2509static void gen_prtyw(DisasContext *ctx)
2510{
2511 TCGv ra = cpu_gpr[rA(ctx->opcode)];
2512 TCGv rs = cpu_gpr[rS(ctx->opcode)];
2513 TCGv t0 = tcg_temp_new();
2514 tcg_gen_shri_tl(t0, rs, 16);
2515 tcg_gen_xor_tl(ra, rs, t0);
2516 tcg_gen_shri_tl(t0, ra, 8);
2517 tcg_gen_xor_tl(ra, ra, t0);
2518 tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
2519 tcg_temp_free(t0);
2520}
2521
2522#if defined(TARGET_PPC64)
2523
2524static void gen_prtyd(DisasContext *ctx)
2525{
2526 TCGv ra = cpu_gpr[rA(ctx->opcode)];
2527 TCGv rs = cpu_gpr[rS(ctx->opcode)];
2528 TCGv t0 = tcg_temp_new();
2529 tcg_gen_shri_tl(t0, rs, 32);
2530 tcg_gen_xor_tl(ra, rs, t0);
2531 tcg_gen_shri_tl(t0, ra, 16);
2532 tcg_gen_xor_tl(ra, ra, t0);
2533 tcg_gen_shri_tl(t0, ra, 8);
2534 tcg_gen_xor_tl(ra, ra, t0);
2535 tcg_gen_andi_tl(ra, ra, 1);
2536 tcg_temp_free(t0);
2537}
2538#endif
2539
2540#if defined(TARGET_PPC64)
2541
2542static void gen_bpermd(DisasContext *ctx)
2543{
2544 gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)],
2545 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2546}
2547#endif
2548
2549#if defined(TARGET_PPC64)
2550
2551GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
2552
2553
2554static void gen_cntlzd(DisasContext *ctx)
2555{
2556 tcg_gen_clzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64);
2557 if (unlikely(Rc(ctx->opcode) != 0)) {
2558 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2559 }
2560}
2561
2562
2563static void gen_cnttzd(DisasContext *ctx)
2564{
2565 tcg_gen_ctzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64);
2566 if (unlikely(Rc(ctx->opcode) != 0)) {
2567 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2568 }
2569}
2570
2571
2572static void gen_darn(DisasContext *ctx)
2573{
2574 int l = L(ctx->opcode);
2575
2576 if (l > 2) {
2577 tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1);
2578 } else {
2579 gen_icount_io_start(ctx);
2580 if (l == 0) {
2581 gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]);
2582 } else {
2583
2584 gen_helper_darn64(cpu_gpr[rD(ctx->opcode)]);
2585 }
2586 }
2587}
2588#endif
2589
2590
2591
2592
2593static void gen_rlwimi(DisasContext *ctx)
2594{
2595 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2596 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2597 uint32_t sh = SH(ctx->opcode);
2598 uint32_t mb = MB(ctx->opcode);
2599 uint32_t me = ME(ctx->opcode);
2600
2601 if (sh == (31 - me) && mb <= me) {
2602 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
2603 } else {
2604 target_ulong mask;
2605 bool mask_in_32b = true;
2606 TCGv t1;
2607
2608#if defined(TARGET_PPC64)
2609 mb += 32;
2610 me += 32;
2611#endif
2612 mask = MASK(mb, me);
2613
2614#if defined(TARGET_PPC64)
2615 if (mask > 0xffffffffu) {
2616 mask_in_32b = false;
2617 }
2618#endif
2619 t1 = tcg_temp_new();
2620 if (mask_in_32b) {
2621 TCGv_i32 t0 = tcg_temp_new_i32();
2622 tcg_gen_trunc_tl_i32(t0, t_rs);
2623 tcg_gen_rotli_i32(t0, t0, sh);
2624 tcg_gen_extu_i32_tl(t1, t0);
2625 tcg_temp_free_i32(t0);
2626 } else {
2627#if defined(TARGET_PPC64)
2628 tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
2629 tcg_gen_rotli_i64(t1, t1, sh);
2630#else
2631 g_assert_not_reached();
2632#endif
2633 }
2634
2635 tcg_gen_andi_tl(t1, t1, mask);
2636 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
2637 tcg_gen_or_tl(t_ra, t_ra, t1);
2638 tcg_temp_free(t1);
2639 }
2640 if (unlikely(Rc(ctx->opcode) != 0)) {
2641 gen_set_Rc0(ctx, t_ra);
2642 }
2643}
2644
2645
2646static void gen_rlwinm(DisasContext *ctx)
2647{
2648 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2649 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2650 int sh = SH(ctx->opcode);
2651 int mb = MB(ctx->opcode);
2652 int me = ME(ctx->opcode);
2653 int len = me - mb + 1;
2654 int rsh = (32 - sh) & 31;
2655
2656 if (sh != 0 && len > 0 && me == (31 - sh)) {
2657 tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len);
2658 } else if (me == 31 && rsh + len <= 32) {
2659 tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
2660 } else {
2661 target_ulong mask;
2662 bool mask_in_32b = true;
2663#if defined(TARGET_PPC64)
2664 mb += 32;
2665 me += 32;
2666#endif
2667 mask = MASK(mb, me);
2668#if defined(TARGET_PPC64)
2669 if (mask > 0xffffffffu) {
2670 mask_in_32b = false;
2671 }
2672#endif
2673 if (mask_in_32b) {
2674 if (sh == 0) {
2675 tcg_gen_andi_tl(t_ra, t_rs, mask);
2676 } else {
2677 TCGv_i32 t0 = tcg_temp_new_i32();
2678 tcg_gen_trunc_tl_i32(t0, t_rs);
2679 tcg_gen_rotli_i32(t0, t0, sh);
2680 tcg_gen_andi_i32(t0, t0, mask);
2681 tcg_gen_extu_i32_tl(t_ra, t0);
2682 tcg_temp_free_i32(t0);
2683 }
2684 } else {
2685#if defined(TARGET_PPC64)
2686 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
2687 tcg_gen_rotli_i64(t_ra, t_ra, sh);
2688 tcg_gen_andi_i64(t_ra, t_ra, mask);
2689#else
2690 g_assert_not_reached();
2691#endif
2692 }
2693 }
2694 if (unlikely(Rc(ctx->opcode) != 0)) {
2695 gen_set_Rc0(ctx, t_ra);
2696 }
2697}
2698
2699
2700static void gen_rlwnm(DisasContext *ctx)
2701{
2702 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2703 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2704 TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
2705 uint32_t mb = MB(ctx->opcode);
2706 uint32_t me = ME(ctx->opcode);
2707 target_ulong mask;
2708 bool mask_in_32b = true;
2709
2710#if defined(TARGET_PPC64)
2711 mb += 32;
2712 me += 32;
2713#endif
2714 mask = MASK(mb, me);
2715
2716#if defined(TARGET_PPC64)
2717 if (mask > 0xffffffffu) {
2718 mask_in_32b = false;
2719 }
2720#endif
2721 if (mask_in_32b) {
2722 TCGv_i32 t0 = tcg_temp_new_i32();
2723 TCGv_i32 t1 = tcg_temp_new_i32();
2724 tcg_gen_trunc_tl_i32(t0, t_rb);
2725 tcg_gen_trunc_tl_i32(t1, t_rs);
2726 tcg_gen_andi_i32(t0, t0, 0x1f);
2727 tcg_gen_rotl_i32(t1, t1, t0);
2728 tcg_gen_extu_i32_tl(t_ra, t1);
2729 tcg_temp_free_i32(t0);
2730 tcg_temp_free_i32(t1);
2731 } else {
2732#if defined(TARGET_PPC64)
2733 TCGv_i64 t0 = tcg_temp_new_i64();
2734 tcg_gen_andi_i64(t0, t_rb, 0x1f);
2735 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
2736 tcg_gen_rotl_i64(t_ra, t_ra, t0);
2737 tcg_temp_free_i64(t0);
2738#else
2739 g_assert_not_reached();
2740#endif
2741 }
2742
2743 tcg_gen_andi_tl(t_ra, t_ra, mask);
2744
2745 if (unlikely(Rc(ctx->opcode) != 0)) {
2746 gen_set_Rc0(ctx, t_ra);
2747 }
2748}
2749
2750#if defined(TARGET_PPC64)
2751#define GEN_PPC64_R2(name, opc1, opc2) \
2752static void glue(gen_, name##0)(DisasContext *ctx) \
2753{ \
2754 gen_##name(ctx, 0); \
2755} \
2756 \
2757static void glue(gen_, name##1)(DisasContext *ctx) \
2758{ \
2759 gen_##name(ctx, 1); \
2760}
2761#define GEN_PPC64_R4(name, opc1, opc2) \
2762static void glue(gen_, name##0)(DisasContext *ctx) \
2763{ \
2764 gen_##name(ctx, 0, 0); \
2765} \
2766 \
2767static void glue(gen_, name##1)(DisasContext *ctx) \
2768{ \
2769 gen_##name(ctx, 0, 1); \
2770} \
2771 \
2772static void glue(gen_, name##2)(DisasContext *ctx) \
2773{ \
2774 gen_##name(ctx, 1, 0); \
2775} \
2776 \
2777static void glue(gen_, name##3)(DisasContext *ctx) \
2778{ \
2779 gen_##name(ctx, 1, 1); \
2780}
2781
2782static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh)
2783{
2784 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2785 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2786 int len = me - mb + 1;
2787 int rsh = (64 - sh) & 63;
2788
2789 if (sh != 0 && len > 0 && me == (63 - sh)) {
2790 tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len);
2791 } else if (me == 63 && rsh + len <= 64) {
2792 tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
2793 } else {
2794 tcg_gen_rotli_tl(t_ra, t_rs, sh);
2795 tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
2796 }
2797 if (unlikely(Rc(ctx->opcode) != 0)) {
2798 gen_set_Rc0(ctx, t_ra);
2799 }
2800}
2801
2802
2803static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
2804{
2805 uint32_t sh, mb;
2806
2807 sh = SH(ctx->opcode) | (shn << 5);
2808 mb = MB(ctx->opcode) | (mbn << 5);
2809 gen_rldinm(ctx, mb, 63, sh);
2810}
2811GEN_PPC64_R4(rldicl, 0x1E, 0x00);
2812
2813
2814static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
2815{
2816 uint32_t sh, me;
2817
2818 sh = SH(ctx->opcode) | (shn << 5);
2819 me = MB(ctx->opcode) | (men << 5);
2820 gen_rldinm(ctx, 0, me, sh);
2821}
2822GEN_PPC64_R4(rldicr, 0x1E, 0x02);
2823
2824
2825static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
2826{
2827 uint32_t sh, mb;
2828
2829 sh = SH(ctx->opcode) | (shn << 5);
2830 mb = MB(ctx->opcode) | (mbn << 5);
2831 gen_rldinm(ctx, mb, 63 - sh, sh);
2832}
2833GEN_PPC64_R4(rldic, 0x1E, 0x04);
2834
2835static void gen_rldnm(DisasContext *ctx, int mb, int me)
2836{
2837 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2838 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2839 TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
2840 TCGv t0;
2841
2842 t0 = tcg_temp_new();
2843 tcg_gen_andi_tl(t0, t_rb, 0x3f);
2844 tcg_gen_rotl_tl(t_ra, t_rs, t0);
2845 tcg_temp_free(t0);
2846
2847 tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
2848 if (unlikely(Rc(ctx->opcode) != 0)) {
2849 gen_set_Rc0(ctx, t_ra);
2850 }
2851}
2852
2853
2854static inline void gen_rldcl(DisasContext *ctx, int mbn)
2855{
2856 uint32_t mb;
2857
2858 mb = MB(ctx->opcode) | (mbn << 5);
2859 gen_rldnm(ctx, mb, 63);
2860}
2861GEN_PPC64_R2(rldcl, 0x1E, 0x08);
2862
2863
2864static inline void gen_rldcr(DisasContext *ctx, int men)
2865{
2866 uint32_t me;
2867
2868 me = MB(ctx->opcode) | (men << 5);
2869 gen_rldnm(ctx, 0, me);
2870}
2871GEN_PPC64_R2(rldcr, 0x1E, 0x09);
2872
2873
2874static void gen_rldimi(DisasContext *ctx, int mbn, int shn)
2875{
2876 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2877 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2878 uint32_t sh = SH(ctx->opcode) | (shn << 5);
2879 uint32_t mb = MB(ctx->opcode) | (mbn << 5);
2880 uint32_t me = 63 - sh;
2881
2882 if (mb <= me) {
2883 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
2884 } else {
2885 target_ulong mask = MASK(mb, me);
2886 TCGv t1 = tcg_temp_new();
2887
2888 tcg_gen_rotli_tl(t1, t_rs, sh);
2889 tcg_gen_andi_tl(t1, t1, mask);
2890 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
2891 tcg_gen_or_tl(t_ra, t_ra, t1);
2892 tcg_temp_free(t1);
2893 }
2894 if (unlikely(Rc(ctx->opcode) != 0)) {
2895 gen_set_Rc0(ctx, t_ra);
2896 }
2897}
2898GEN_PPC64_R4(rldimi, 0x1E, 0x06);
2899#endif
2900
2901
2902
2903
2904static void gen_slw(DisasContext *ctx)
2905{
2906 TCGv t0, t1;
2907
2908 t0 = tcg_temp_new();
2909
2910#if defined(TARGET_PPC64)
2911 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
2912 tcg_gen_sari_tl(t0, t0, 0x3f);
2913#else
2914 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
2915 tcg_gen_sari_tl(t0, t0, 0x1f);
2916#endif
2917 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2918 t1 = tcg_temp_new();
2919 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
2920 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2921 tcg_temp_free(t1);
2922 tcg_temp_free(t0);
2923 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
2924 if (unlikely(Rc(ctx->opcode) != 0)) {
2925 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2926 }
2927}
2928
2929
2930static void gen_sraw(DisasContext *ctx)
2931{
2932 gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
2933 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2934 if (unlikely(Rc(ctx->opcode) != 0)) {
2935 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2936 }
2937}
2938
2939
2940static void gen_srawi(DisasContext *ctx)
2941{
2942 int sh = SH(ctx->opcode);
2943 TCGv dst = cpu_gpr[rA(ctx->opcode)];
2944 TCGv src = cpu_gpr[rS(ctx->opcode)];
2945 if (sh == 0) {
2946 tcg_gen_ext32s_tl(dst, src);
2947 tcg_gen_movi_tl(cpu_ca, 0);
2948 if (is_isa300(ctx)) {
2949 tcg_gen_movi_tl(cpu_ca32, 0);
2950 }
2951 } else {
2952 TCGv t0;
2953 tcg_gen_ext32s_tl(dst, src);
2954 tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
2955 t0 = tcg_temp_new();
2956 tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
2957 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
2958 tcg_temp_free(t0);
2959 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
2960 if (is_isa300(ctx)) {
2961 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
2962 }
2963 tcg_gen_sari_tl(dst, dst, sh);
2964 }
2965 if (unlikely(Rc(ctx->opcode) != 0)) {
2966 gen_set_Rc0(ctx, dst);
2967 }
2968}
2969
2970
2971static void gen_srw(DisasContext *ctx)
2972{
2973 TCGv t0, t1;
2974
2975 t0 = tcg_temp_new();
2976
2977#if defined(TARGET_PPC64)
2978 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
2979 tcg_gen_sari_tl(t0, t0, 0x3f);
2980#else
2981 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
2982 tcg_gen_sari_tl(t0, t0, 0x1f);
2983#endif
2984 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2985 tcg_gen_ext32u_tl(t0, t0);
2986 t1 = tcg_temp_new();
2987 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
2988 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2989 tcg_temp_free(t1);
2990 tcg_temp_free(t0);
2991 if (unlikely(Rc(ctx->opcode) != 0)) {
2992 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2993 }
2994}
2995
2996#if defined(TARGET_PPC64)
2997
2998static void gen_sld(DisasContext *ctx)
2999{
3000 TCGv t0, t1;
3001
3002 t0 = tcg_temp_new();
3003
3004 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
3005 tcg_gen_sari_tl(t0, t0, 0x3f);
3006 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
3007 t1 = tcg_temp_new();
3008 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
3009 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
3010 tcg_temp_free(t1);
3011 tcg_temp_free(t0);
3012 if (unlikely(Rc(ctx->opcode) != 0)) {
3013 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
3014 }
3015}
3016
3017
3018static void gen_srad(DisasContext *ctx)
3019{
3020 gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
3021 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
3022 if (unlikely(Rc(ctx->opcode) != 0)) {
3023 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
3024 }
3025}
3026
3027static inline void gen_sradi(DisasContext *ctx, int n)
3028{
3029 int sh = SH(ctx->opcode) + (n << 5);
3030 TCGv dst = cpu_gpr[rA(ctx->opcode)];
3031 TCGv src = cpu_gpr[rS(ctx->opcode)];
3032 if (sh == 0) {
3033 tcg_gen_mov_tl(dst, src);
3034 tcg_gen_movi_tl(cpu_ca, 0);
3035 if (is_isa300(ctx)) {
3036 tcg_gen_movi_tl(cpu_ca32, 0);
3037 }
3038 } else {
3039 TCGv t0;
3040 tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
3041 t0 = tcg_temp_new();
3042 tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
3043 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
3044 tcg_temp_free(t0);
3045 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
3046 if (is_isa300(ctx)) {
3047 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
3048 }
3049 tcg_gen_sari_tl(dst, src, sh);
3050 }
3051 if (unlikely(Rc(ctx->opcode) != 0)) {
3052 gen_set_Rc0(ctx, dst);
3053 }
3054}
3055
3056static void gen_sradi0(DisasContext *ctx)
3057{
3058 gen_sradi(ctx, 0);
3059}
3060
3061static void gen_sradi1(DisasContext *ctx)
3062{
3063 gen_sradi(ctx, 1);
3064}
3065
3066
3067static inline void gen_extswsli(DisasContext *ctx, int n)
3068{
3069 int sh = SH(ctx->opcode) + (n << 5);
3070 TCGv dst = cpu_gpr[rA(ctx->opcode)];
3071 TCGv src = cpu_gpr[rS(ctx->opcode)];
3072
3073 tcg_gen_ext32s_tl(dst, src);
3074 tcg_gen_shli_tl(dst, dst, sh);
3075 if (unlikely(Rc(ctx->opcode) != 0)) {
3076 gen_set_Rc0(ctx, dst);
3077 }
3078}
3079
3080static void gen_extswsli0(DisasContext *ctx)
3081{
3082 gen_extswsli(ctx, 0);
3083}
3084
3085static void gen_extswsli1(DisasContext *ctx)
3086{
3087 gen_extswsli(ctx, 1);
3088}
3089
3090
3091static void gen_srd(DisasContext *ctx)
3092{
3093 TCGv t0, t1;
3094
3095 t0 = tcg_temp_new();
3096
3097 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
3098 tcg_gen_sari_tl(t0, t0, 0x3f);
3099 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
3100 t1 = tcg_temp_new();
3101 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
3102 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
3103 tcg_temp_free(t1);
3104 tcg_temp_free(t0);
3105 if (unlikely(Rc(ctx->opcode) != 0)) {
3106 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
3107 }
3108}
3109#endif
3110
3111
3112
3113static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
3114 target_long maskl)
3115{
3116 target_long simm = SIMM(ctx->opcode);
3117
3118 simm &= ~maskl;
3119 if (rA(ctx->opcode) == 0) {
3120 if (NARROW_MODE(ctx)) {
3121 simm = (uint32_t)simm;
3122 }
3123 tcg_gen_movi_tl(EA, simm);
3124 } else if (likely(simm != 0)) {
3125 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
3126 if (NARROW_MODE(ctx)) {
3127 tcg_gen_ext32u_tl(EA, EA);
3128 }
3129 } else {
3130 if (NARROW_MODE(ctx)) {
3131 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
3132 } else {
3133 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
3134 }
3135 }
3136}
3137
3138static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
3139{
3140 if (rA(ctx->opcode) == 0) {
3141 if (NARROW_MODE(ctx)) {
3142 tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
3143 } else {
3144 tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
3145 }
3146 } else {
3147 tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
3148 if (NARROW_MODE(ctx)) {
3149 tcg_gen_ext32u_tl(EA, EA);
3150 }
3151 }
3152}
3153
3154static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
3155{
3156 if (rA(ctx->opcode) == 0) {
3157 tcg_gen_movi_tl(EA, 0);
3158 } else if (NARROW_MODE(ctx)) {
3159 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
3160 } else {
3161 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
3162 }
3163}
3164
3165static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
3166 target_long val)
3167{
3168 tcg_gen_addi_tl(ret, arg1, val);
3169 if (NARROW_MODE(ctx)) {
3170 tcg_gen_ext32u_tl(ret, ret);
3171 }
3172}
3173
3174static inline void gen_align_no_le(DisasContext *ctx)
3175{
3176 gen_exception_err(ctx, POWERPC_EXCP_ALIGN,
3177 (ctx->opcode & 0x03FF0000) | POWERPC_EXCP_ALIGN_LE);
3178}
3179
3180static TCGv do_ea_calc(DisasContext *ctx, int ra, TCGv displ)
3181{
3182 TCGv ea = tcg_temp_new();
3183 if (ra) {
3184 tcg_gen_add_tl(ea, cpu_gpr[ra], displ);
3185 } else {
3186 tcg_gen_mov_tl(ea, displ);
3187 }
3188 if (NARROW_MODE(ctx)) {
3189 tcg_gen_ext32u_tl(ea, ea);
3190 }
3191 return ea;
3192}
3193
3194
3195#define DEF_MEMOP(op) ((op) | ctx->default_tcg_memop_mask)
3196#define BSWAP_MEMOP(op) ((op) | (ctx->default_tcg_memop_mask ^ MO_BSWAP))
3197
3198#define GEN_QEMU_LOAD_TL(ldop, op) \
3199static void glue(gen_qemu_, ldop)(DisasContext *ctx, \
3200 TCGv val, \
3201 TCGv addr) \
3202{ \
3203 tcg_gen_qemu_ld_tl(val, addr, ctx->mem_idx, op); \
3204}
3205
3206GEN_QEMU_LOAD_TL(ld8u, DEF_MEMOP(MO_UB))
3207GEN_QEMU_LOAD_TL(ld16u, DEF_MEMOP(MO_UW))
3208GEN_QEMU_LOAD_TL(ld16s, DEF_MEMOP(MO_SW))
3209GEN_QEMU_LOAD_TL(ld32u, DEF_MEMOP(MO_UL))
3210GEN_QEMU_LOAD_TL(ld32s, DEF_MEMOP(MO_SL))
3211
3212GEN_QEMU_LOAD_TL(ld16ur, BSWAP_MEMOP(MO_UW))
3213GEN_QEMU_LOAD_TL(ld32ur, BSWAP_MEMOP(MO_UL))
3214
3215#define GEN_QEMU_LOAD_64(ldop, op) \
3216static void glue(gen_qemu_, glue(ldop, _i64))(DisasContext *ctx, \
3217 TCGv_i64 val, \
3218 TCGv addr) \
3219{ \
3220 tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, op); \
3221}
3222
3223GEN_QEMU_LOAD_64(ld8u, DEF_MEMOP(MO_UB))
3224GEN_QEMU_LOAD_64(ld16u, DEF_MEMOP(MO_UW))
3225GEN_QEMU_LOAD_64(ld32u, DEF_MEMOP(MO_UL))
3226GEN_QEMU_LOAD_64(ld32s, DEF_MEMOP(MO_SL))
3227GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_UQ))
3228
3229#if defined(TARGET_PPC64)
3230GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_UQ))
3231#endif
3232
3233#define GEN_QEMU_STORE_TL(stop, op) \
3234static void glue(gen_qemu_, stop)(DisasContext *ctx, \
3235 TCGv val, \
3236 TCGv addr) \
3237{ \
3238 tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, op); \
3239}
3240
3241#if defined(TARGET_PPC64) || !defined(CONFIG_USER_ONLY)
3242GEN_QEMU_STORE_TL(st8, DEF_MEMOP(MO_UB))
3243#endif
3244GEN_QEMU_STORE_TL(st16, DEF_MEMOP(MO_UW))
3245GEN_QEMU_STORE_TL(st32, DEF_MEMOP(MO_UL))
3246
3247GEN_QEMU_STORE_TL(st16r, BSWAP_MEMOP(MO_UW))
3248GEN_QEMU_STORE_TL(st32r, BSWAP_MEMOP(MO_UL))
3249
3250#define GEN_QEMU_STORE_64(stop, op) \
3251static void glue(gen_qemu_, glue(stop, _i64))(DisasContext *ctx, \
3252 TCGv_i64 val, \
3253 TCGv addr) \
3254{ \
3255 tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, op); \
3256}
3257
3258GEN_QEMU_STORE_64(st8, DEF_MEMOP(MO_UB))
3259GEN_QEMU_STORE_64(st16, DEF_MEMOP(MO_UW))
3260GEN_QEMU_STORE_64(st32, DEF_MEMOP(MO_UL))
3261GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_UQ))
3262
3263#if defined(TARGET_PPC64)
3264GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_UQ))
3265#endif
3266
3267#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \
3268static void glue(gen_, name##x)(DisasContext *ctx) \
3269{ \
3270 TCGv EA; \
3271 chk(ctx); \
3272 gen_set_access_type(ctx, ACCESS_INT); \
3273 EA = tcg_temp_new(); \
3274 gen_addr_reg_index(ctx, EA); \
3275 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
3276 tcg_temp_free(EA); \
3277}
3278
3279#define GEN_LDX(name, ldop, opc2, opc3, type) \
3280 GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_NONE)
3281
3282#define GEN_LDX_HVRM(name, ldop, opc2, opc3, type) \
3283 GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
3284
3285#define GEN_LDEPX(name, ldop, opc2, opc3) \
3286static void glue(gen_, name##epx)(DisasContext *ctx) \
3287{ \
3288 TCGv EA; \
3289 CHK_SV(ctx); \
3290 gen_set_access_type(ctx, ACCESS_INT); \
3291 EA = tcg_temp_new(); \
3292 gen_addr_reg_index(ctx, EA); \
3293 tcg_gen_qemu_ld_tl(cpu_gpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_LOAD, ldop);\
3294 tcg_temp_free(EA); \
3295}
3296
3297GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
3298GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
3299GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
3300#if defined(TARGET_PPC64)
3301GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00)
3302#endif
3303
3304#if defined(TARGET_PPC64)
3305
3306GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
3307GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x15, PPC_CILDST)
3308GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
3309GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
3310#endif
3311
3312
3313#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk) \
3314static void glue(gen_, name##x)(DisasContext *ctx) \
3315{ \
3316 TCGv EA; \
3317 chk(ctx); \
3318 gen_set_access_type(ctx, ACCESS_INT); \
3319 EA = tcg_temp_new(); \
3320 gen_addr_reg_index(ctx, EA); \
3321 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
3322 tcg_temp_free(EA); \
3323}
3324#define GEN_STX(name, stop, opc2, opc3, type) \
3325 GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_NONE)
3326
3327#define GEN_STX_HVRM(name, stop, opc2, opc3, type) \
3328 GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
3329
3330#define GEN_STEPX(name, stop, opc2, opc3) \
3331static void glue(gen_, name##epx)(DisasContext *ctx) \
3332{ \
3333 TCGv EA; \
3334 CHK_SV(ctx); \
3335 gen_set_access_type(ctx, ACCESS_INT); \
3336 EA = tcg_temp_new(); \
3337 gen_addr_reg_index(ctx, EA); \
3338 tcg_gen_qemu_st_tl( \
3339 cpu_gpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_STORE, stop); \
3340 tcg_temp_free(EA); \
3341}
3342
3343GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
3344GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
3345GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
3346#if defined(TARGET_PPC64)
3347GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1d, 0x04)
3348#endif
3349
3350#if defined(TARGET_PPC64)
3351GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
3352GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
3353GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
3354GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
3355#endif
3356
3357
3358
3359GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
3360
3361
3362GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
3363
3364#if defined(TARGET_PPC64)
3365
3366GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE);
3367
3368GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE);
3369#endif
3370
3371
3372GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
3373
3374GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
3375
3376
3377
3378
3379static void gen_lmw(DisasContext *ctx)
3380{
3381 TCGv t0;
3382 TCGv_i32 t1;
3383
3384 if (ctx->le_mode) {
3385 gen_align_no_le(ctx);
3386 return;
3387 }
3388 gen_set_access_type(ctx, ACCESS_INT);
3389 t0 = tcg_temp_new();
3390 t1 = tcg_const_i32(rD(ctx->opcode));
3391 gen_addr_imm_index(ctx, t0, 0);
3392 gen_helper_lmw(cpu_env, t0, t1);
3393 tcg_temp_free(t0);
3394 tcg_temp_free_i32(t1);
3395}
3396
3397
3398static void gen_stmw(DisasContext *ctx)
3399{
3400 TCGv t0;
3401 TCGv_i32 t1;
3402
3403 if (ctx->le_mode) {
3404 gen_align_no_le(ctx);
3405 return;
3406 }
3407 gen_set_access_type(ctx, ACCESS_INT);
3408 t0 = tcg_temp_new();
3409 t1 = tcg_const_i32(rS(ctx->opcode));
3410 gen_addr_imm_index(ctx, t0, 0);
3411 gen_helper_stmw(cpu_env, t0, t1);
3412 tcg_temp_free(t0);
3413 tcg_temp_free_i32(t1);
3414}
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425static void gen_lswi(DisasContext *ctx)
3426{
3427 TCGv t0;
3428 TCGv_i32 t1, t2;
3429 int nb = NB(ctx->opcode);
3430 int start = rD(ctx->opcode);
3431 int ra = rA(ctx->opcode);
3432 int nr;
3433
3434 if (ctx->le_mode) {
3435 gen_align_no_le(ctx);
3436 return;
3437 }
3438 if (nb == 0) {
3439 nb = 32;
3440 }
3441 nr = DIV_ROUND_UP(nb, 4);
3442 if (unlikely(lsw_reg_in_range(start, nr, ra))) {
3443 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3444 return;
3445 }
3446 gen_set_access_type(ctx, ACCESS_INT);
3447 t0 = tcg_temp_new();
3448 gen_addr_register(ctx, t0);
3449 t1 = tcg_const_i32(nb);
3450 t2 = tcg_const_i32(start);
3451 gen_helper_lsw(cpu_env, t0, t1, t2);
3452 tcg_temp_free(t0);
3453 tcg_temp_free_i32(t1);
3454 tcg_temp_free_i32(t2);
3455}
3456
3457
3458static void gen_lswx(DisasContext *ctx)
3459{
3460 TCGv t0;
3461 TCGv_i32 t1, t2, t3;
3462
3463 if (ctx->le_mode) {
3464 gen_align_no_le(ctx);
3465 return;
3466 }
3467 gen_set_access_type(ctx, ACCESS_INT);
3468 t0 = tcg_temp_new();
3469 gen_addr_reg_index(ctx, t0);
3470 t1 = tcg_const_i32(rD(ctx->opcode));
3471 t2 = tcg_const_i32(rA(ctx->opcode));
3472 t3 = tcg_const_i32(rB(ctx->opcode));
3473 gen_helper_lswx(cpu_env, t0, t1, t2, t3);
3474 tcg_temp_free(t0);
3475 tcg_temp_free_i32(t1);
3476 tcg_temp_free_i32(t2);
3477 tcg_temp_free_i32(t3);
3478}
3479
3480
3481static void gen_stswi(DisasContext *ctx)
3482{
3483 TCGv t0;
3484 TCGv_i32 t1, t2;
3485 int nb = NB(ctx->opcode);
3486
3487 if (ctx->le_mode) {
3488 gen_align_no_le(ctx);
3489 return;
3490 }
3491 gen_set_access_type(ctx, ACCESS_INT);
3492 t0 = tcg_temp_new();
3493 gen_addr_register(ctx, t0);
3494 if (nb == 0) {
3495 nb = 32;
3496 }
3497 t1 = tcg_const_i32(nb);
3498 t2 = tcg_const_i32(rS(ctx->opcode));
3499 gen_helper_stsw(cpu_env, t0, t1, t2);
3500 tcg_temp_free(t0);
3501 tcg_temp_free_i32(t1);
3502 tcg_temp_free_i32(t2);
3503}
3504
3505
3506static void gen_stswx(DisasContext *ctx)
3507{
3508 TCGv t0;
3509 TCGv_i32 t1, t2;
3510
3511 if (ctx->le_mode) {
3512 gen_align_no_le(ctx);
3513 return;
3514 }
3515 gen_set_access_type(ctx, ACCESS_INT);
3516 t0 = tcg_temp_new();
3517 gen_addr_reg_index(ctx, t0);
3518 t1 = tcg_temp_new_i32();
3519 tcg_gen_trunc_tl_i32(t1, cpu_xer);
3520 tcg_gen_andi_i32(t1, t1, 0x7F);
3521 t2 = tcg_const_i32(rS(ctx->opcode));
3522 gen_helper_stsw(cpu_env, t0, t1, t2);
3523 tcg_temp_free(t0);
3524 tcg_temp_free_i32(t1);
3525 tcg_temp_free_i32(t2);
3526}
3527
3528
3529
3530static void gen_eieio(DisasContext *ctx)
3531{
3532 TCGBar bar = TCG_MO_ALL;
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563 if (ctx->opcode & 0x2000000) {
3564
3565
3566
3567
3568
3569
3570 if (!(ctx->insns_flags2 & PPC2_ISA300)) {
3571 qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
3572 TARGET_FMT_lx "\n", ctx->cia);
3573 } else {
3574 bar = TCG_MO_ST_LD;
3575 }
3576 }
3577
3578 tcg_gen_mb(bar | TCG_BAR_SC);
3579}
3580
3581#if !defined(CONFIG_USER_ONLY)
3582static inline void gen_check_tlb_flush(DisasContext *ctx, bool global)
3583{
3584 TCGv_i32 t;
3585 TCGLabel *l;
3586
3587 if (!ctx->lazy_tlb_flush) {
3588 return;
3589 }
3590 l = gen_new_label();
3591 t = tcg_temp_new_i32();
3592 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
3593 tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
3594 if (global) {
3595 gen_helper_check_tlb_flush_global(cpu_env);
3596 } else {
3597 gen_helper_check_tlb_flush_local(cpu_env);
3598 }
3599 gen_set_label(l);
3600 tcg_temp_free_i32(t);
3601}
3602#else
3603static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) { }
3604#endif
3605
3606
3607static void gen_isync(DisasContext *ctx)
3608{
3609
3610
3611
3612
3613 if (!ctx->pr) {
3614 gen_check_tlb_flush(ctx, false);
3615 }
3616 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
3617 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
3618}
3619
3620#define MEMOP_GET_SIZE(x) (1 << ((x) & MO_SIZE))
3621
3622static void gen_load_locked(DisasContext *ctx, MemOp memop)
3623{
3624 TCGv gpr = cpu_gpr[rD(ctx->opcode)];
3625 TCGv t0 = tcg_temp_new();
3626
3627 gen_set_access_type(ctx, ACCESS_RES);
3628 gen_addr_reg_index(ctx, t0);
3629 tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, memop | MO_ALIGN);
3630 tcg_gen_mov_tl(cpu_reserve, t0);
3631 tcg_gen_mov_tl(cpu_reserve_val, gpr);
3632 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
3633 tcg_temp_free(t0);
3634}
3635
3636#define LARX(name, memop) \
3637static void gen_##name(DisasContext *ctx) \
3638{ \
3639 gen_load_locked(ctx, memop); \
3640}
3641
3642
3643LARX(lbarx, DEF_MEMOP(MO_UB))
3644LARX(lharx, DEF_MEMOP(MO_UW))
3645LARX(lwarx, DEF_MEMOP(MO_UL))
3646
3647static void gen_fetch_inc_conditional(DisasContext *ctx, MemOp memop,
3648 TCGv EA, TCGCond cond, int addend)
3649{
3650 TCGv t = tcg_temp_new();
3651 TCGv t2 = tcg_temp_new();
3652 TCGv u = tcg_temp_new();
3653
3654 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
3655 tcg_gen_addi_tl(t2, EA, MEMOP_GET_SIZE(memop));
3656 tcg_gen_qemu_ld_tl(t2, t2, ctx->mem_idx, memop);
3657 tcg_gen_addi_tl(u, t, addend);
3658
3659
3660
3661 tcg_gen_movcond_tl(cond, u, t, t2, u, t);
3662 tcg_gen_qemu_st_tl(u, EA, ctx->mem_idx, memop);
3663
3664
3665 tcg_gen_movi_tl(u, 1 << (MEMOP_GET_SIZE(memop) * 8 - 1));
3666 tcg_gen_movcond_tl(cond, cpu_gpr[rD(ctx->opcode)], t, t2, t, u);
3667
3668 tcg_temp_free(t);
3669 tcg_temp_free(t2);
3670 tcg_temp_free(u);
3671}
3672
3673static void gen_ld_atomic(DisasContext *ctx, MemOp memop)
3674{
3675 uint32_t gpr_FC = FC(ctx->opcode);
3676 TCGv EA = tcg_temp_new();
3677 int rt = rD(ctx->opcode);
3678 bool need_serial;
3679 TCGv src, dst;
3680
3681 gen_addr_register(ctx, EA);
3682 dst = cpu_gpr[rt];
3683 src = cpu_gpr[(rt + 1) & 31];
3684
3685 need_serial = false;
3686 memop |= MO_ALIGN;
3687 switch (gpr_FC) {
3688 case 0:
3689 tcg_gen_atomic_fetch_add_tl(dst, EA, src, ctx->mem_idx, memop);
3690 break;
3691 case 1:
3692 tcg_gen_atomic_fetch_xor_tl(dst, EA, src, ctx->mem_idx, memop);
3693 break;
3694 case 2:
3695 tcg_gen_atomic_fetch_or_tl(dst, EA, src, ctx->mem_idx, memop);
3696 break;
3697 case 3:
3698 tcg_gen_atomic_fetch_and_tl(dst, EA, src, ctx->mem_idx, memop);
3699 break;
3700 case 4:
3701 tcg_gen_atomic_fetch_umax_tl(dst, EA, src, ctx->mem_idx, memop);
3702 break;
3703 case 5:
3704 tcg_gen_atomic_fetch_smax_tl(dst, EA, src, ctx->mem_idx, memop);
3705 break;
3706 case 6:
3707 tcg_gen_atomic_fetch_umin_tl(dst, EA, src, ctx->mem_idx, memop);
3708 break;
3709 case 7:
3710 tcg_gen_atomic_fetch_smin_tl(dst, EA, src, ctx->mem_idx, memop);
3711 break;
3712 case 8:
3713 tcg_gen_atomic_xchg_tl(dst, EA, src, ctx->mem_idx, memop);
3714 break;
3715
3716 case 16:
3717 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3718 need_serial = true;
3719 } else {
3720 TCGv t0 = tcg_temp_new();
3721 TCGv t1 = tcg_temp_new();
3722
3723 tcg_gen_qemu_ld_tl(t0, EA, ctx->mem_idx, memop);
3724 if ((memop & MO_SIZE) == MO_64 || TARGET_LONG_BITS == 32) {
3725 tcg_gen_mov_tl(t1, src);
3726 } else {
3727 tcg_gen_ext32u_tl(t1, src);
3728 }
3729 tcg_gen_movcond_tl(TCG_COND_NE, t1, t0, t1,
3730 cpu_gpr[(rt + 2) & 31], t0);
3731 tcg_gen_qemu_st_tl(t1, EA, ctx->mem_idx, memop);
3732 tcg_gen_mov_tl(dst, t0);
3733
3734 tcg_temp_free(t0);
3735 tcg_temp_free(t1);
3736 }
3737 break;
3738
3739 case 24:
3740 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3741 need_serial = true;
3742 } else {
3743 gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_NE, 1);
3744 }
3745 break;
3746 case 25:
3747 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3748 need_serial = true;
3749 } else {
3750 gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_EQ, 1);
3751 }
3752 break;
3753 case 28:
3754 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3755 need_serial = true;
3756 } else {
3757 gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_NE, -1);
3758 }
3759 break;
3760
3761 default:
3762
3763 gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
3764 }
3765 tcg_temp_free(EA);
3766
3767 if (need_serial) {
3768
3769 gen_helper_exit_atomic(cpu_env);
3770 ctx->base.is_jmp = DISAS_NORETURN;
3771 }
3772}
3773
3774static void gen_lwat(DisasContext *ctx)
3775{
3776 gen_ld_atomic(ctx, DEF_MEMOP(MO_UL));
3777}
3778
3779#ifdef TARGET_PPC64
3780static void gen_ldat(DisasContext *ctx)
3781{
3782 gen_ld_atomic(ctx, DEF_MEMOP(MO_UQ));
3783}
3784#endif
3785
3786static void gen_st_atomic(DisasContext *ctx, MemOp memop)
3787{
3788 uint32_t gpr_FC = FC(ctx->opcode);
3789 TCGv EA = tcg_temp_new();
3790 TCGv src, discard;
3791
3792 gen_addr_register(ctx, EA);
3793 src = cpu_gpr[rD(ctx->opcode)];
3794 discard = tcg_temp_new();
3795
3796 memop |= MO_ALIGN;
3797 switch (gpr_FC) {
3798 case 0:
3799 tcg_gen_atomic_add_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3800 break;
3801 case 1:
3802 tcg_gen_atomic_xor_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3803 break;
3804 case 2:
3805 tcg_gen_atomic_or_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3806 break;
3807 case 3:
3808 tcg_gen_atomic_and_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3809 break;
3810 case 4:
3811 tcg_gen_atomic_umax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3812 break;
3813 case 5:
3814 tcg_gen_atomic_smax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3815 break;
3816 case 6:
3817 tcg_gen_atomic_umin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3818 break;
3819 case 7:
3820 tcg_gen_atomic_smin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3821 break;
3822 case 24:
3823 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3824
3825 gen_helper_exit_atomic(cpu_env);
3826 ctx->base.is_jmp = DISAS_NORETURN;
3827 } else {
3828 TCGv t = tcg_temp_new();
3829 TCGv t2 = tcg_temp_new();
3830 TCGv s = tcg_temp_new();
3831 TCGv s2 = tcg_temp_new();
3832 TCGv ea_plus_s = tcg_temp_new();
3833
3834 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
3835 tcg_gen_addi_tl(ea_plus_s, EA, MEMOP_GET_SIZE(memop));
3836 tcg_gen_qemu_ld_tl(t2, ea_plus_s, ctx->mem_idx, memop);
3837 tcg_gen_movcond_tl(TCG_COND_EQ, s, t, t2, src, t);
3838 tcg_gen_movcond_tl(TCG_COND_EQ, s2, t, t2, src, t2);
3839 tcg_gen_qemu_st_tl(s, EA, ctx->mem_idx, memop);
3840 tcg_gen_qemu_st_tl(s2, ea_plus_s, ctx->mem_idx, memop);
3841
3842 tcg_temp_free(ea_plus_s);
3843 tcg_temp_free(s2);
3844 tcg_temp_free(s);
3845 tcg_temp_free(t2);
3846 tcg_temp_free(t);
3847 }
3848 break;
3849 default:
3850
3851 gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
3852 }
3853 tcg_temp_free(discard);
3854 tcg_temp_free(EA);
3855}
3856
3857static void gen_stwat(DisasContext *ctx)
3858{
3859 gen_st_atomic(ctx, DEF_MEMOP(MO_UL));
3860}
3861
3862#ifdef TARGET_PPC64
3863static void gen_stdat(DisasContext *ctx)
3864{
3865 gen_st_atomic(ctx, DEF_MEMOP(MO_UQ));
3866}
3867#endif
3868
3869static void gen_conditional_store(DisasContext *ctx, MemOp memop)
3870{
3871 TCGLabel *l1 = gen_new_label();
3872 TCGLabel *l2 = gen_new_label();
3873 TCGv t0 = tcg_temp_new();
3874 int reg = rS(ctx->opcode);
3875
3876 gen_set_access_type(ctx, ACCESS_RES);
3877 gen_addr_reg_index(ctx, t0);
3878 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3879 tcg_temp_free(t0);
3880
3881 t0 = tcg_temp_new();
3882 tcg_gen_atomic_cmpxchg_tl(t0, cpu_reserve, cpu_reserve_val,
3883 cpu_gpr[reg], ctx->mem_idx,
3884 DEF_MEMOP(memop) | MO_ALIGN);
3885 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_reserve_val);
3886 tcg_gen_shli_tl(t0, t0, CRF_EQ_BIT);
3887 tcg_gen_or_tl(t0, t0, cpu_so);
3888 tcg_gen_trunc_tl_i32(cpu_crf[0], t0);
3889 tcg_temp_free(t0);
3890 tcg_gen_br(l2);
3891
3892 gen_set_label(l1);
3893
3894
3895
3896
3897
3898 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
3899 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3900
3901 gen_set_label(l2);
3902 tcg_gen_movi_tl(cpu_reserve, -1);
3903}
3904
3905#define STCX(name, memop) \
3906static void gen_##name(DisasContext *ctx) \
3907{ \
3908 gen_conditional_store(ctx, memop); \
3909}
3910
3911STCX(stbcx_, DEF_MEMOP(MO_UB))
3912STCX(sthcx_, DEF_MEMOP(MO_UW))
3913STCX(stwcx_, DEF_MEMOP(MO_UL))
3914
3915#if defined(TARGET_PPC64)
3916
3917LARX(ldarx, DEF_MEMOP(MO_UQ))
3918
3919STCX(stdcx_, DEF_MEMOP(MO_UQ))
3920
3921
3922static void gen_lqarx(DisasContext *ctx)
3923{
3924 int rd = rD(ctx->opcode);
3925 TCGv EA, hi, lo;
3926
3927 if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) ||
3928 (rd == rB(ctx->opcode)))) {
3929 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3930 return;
3931 }
3932
3933 gen_set_access_type(ctx, ACCESS_RES);
3934 EA = tcg_temp_new();
3935 gen_addr_reg_index(ctx, EA);
3936
3937
3938 lo = cpu_gpr[rd + 1];
3939 hi = cpu_gpr[rd];
3940
3941 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3942 if (HAVE_ATOMIC128) {
3943 TCGv_i32 oi = tcg_temp_new_i32();
3944 if (ctx->le_mode) {
3945 tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128 | MO_ALIGN,
3946 ctx->mem_idx));
3947 gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
3948 } else {
3949 tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128 | MO_ALIGN,
3950 ctx->mem_idx));
3951 gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
3952 }
3953 tcg_temp_free_i32(oi);
3954 tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
3955 } else {
3956
3957 gen_helper_exit_atomic(cpu_env);
3958 ctx->base.is_jmp = DISAS_NORETURN;
3959 tcg_temp_free(EA);
3960 return;
3961 }
3962 } else if (ctx->le_mode) {
3963 tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEUQ | MO_ALIGN_16);
3964 tcg_gen_mov_tl(cpu_reserve, EA);
3965 gen_addr_add(ctx, EA, EA, 8);
3966 tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEUQ);
3967 } else {
3968 tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEUQ | MO_ALIGN_16);
3969 tcg_gen_mov_tl(cpu_reserve, EA);
3970 gen_addr_add(ctx, EA, EA, 8);
3971 tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEUQ);
3972 }
3973 tcg_temp_free(EA);
3974
3975 tcg_gen_st_tl(hi, cpu_env, offsetof(CPUPPCState, reserve_val));
3976 tcg_gen_st_tl(lo, cpu_env, offsetof(CPUPPCState, reserve_val2));
3977}
3978
3979
3980static void gen_stqcx_(DisasContext *ctx)
3981{
3982 int rs = rS(ctx->opcode);
3983 TCGv EA, hi, lo;
3984
3985 if (unlikely(rs & 1)) {
3986 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3987 return;
3988 }
3989
3990 gen_set_access_type(ctx, ACCESS_RES);
3991 EA = tcg_temp_new();
3992 gen_addr_reg_index(ctx, EA);
3993
3994
3995 lo = cpu_gpr[rs + 1];
3996 hi = cpu_gpr[rs];
3997
3998 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3999 if (HAVE_CMPXCHG128) {
4000 TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_128) | MO_ALIGN);
4001 if (ctx->le_mode) {
4002 gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env,
4003 EA, lo, hi, oi);
4004 } else {
4005 gen_helper_stqcx_be_parallel(cpu_crf[0], cpu_env,
4006 EA, lo, hi, oi);
4007 }
4008 tcg_temp_free_i32(oi);
4009 } else {
4010
4011 gen_helper_exit_atomic(cpu_env);
4012 ctx->base.is_jmp = DISAS_NORETURN;
4013 }
4014 tcg_temp_free(EA);
4015 } else {
4016 TCGLabel *lab_fail = gen_new_label();
4017 TCGLabel *lab_over = gen_new_label();
4018 TCGv_i64 t0 = tcg_temp_new_i64();
4019 TCGv_i64 t1 = tcg_temp_new_i64();
4020
4021 tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, lab_fail);
4022 tcg_temp_free(EA);
4023
4024 gen_qemu_ld64_i64(ctx, t0, cpu_reserve);
4025 tcg_gen_ld_i64(t1, cpu_env, (ctx->le_mode
4026 ? offsetof(CPUPPCState, reserve_val2)
4027 : offsetof(CPUPPCState, reserve_val)));
4028 tcg_gen_brcond_i64(TCG_COND_NE, t0, t1, lab_fail);
4029
4030 tcg_gen_addi_i64(t0, cpu_reserve, 8);
4031 gen_qemu_ld64_i64(ctx, t0, t0);
4032 tcg_gen_ld_i64(t1, cpu_env, (ctx->le_mode
4033 ? offsetof(CPUPPCState, reserve_val)
4034 : offsetof(CPUPPCState, reserve_val2)));
4035 tcg_gen_brcond_i64(TCG_COND_NE, t0, t1, lab_fail);
4036
4037
4038 gen_qemu_st64_i64(ctx, ctx->le_mode ? lo : hi, cpu_reserve);
4039 tcg_gen_addi_i64(t0, cpu_reserve, 8);
4040 gen_qemu_st64_i64(ctx, ctx->le_mode ? hi : lo, t0);
4041
4042 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
4043 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ);
4044 tcg_gen_br(lab_over);
4045
4046 gen_set_label(lab_fail);
4047 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
4048
4049 gen_set_label(lab_over);
4050 tcg_gen_movi_tl(cpu_reserve, -1);
4051 tcg_temp_free_i64(t0);
4052 tcg_temp_free_i64(t1);
4053 }
4054}
4055#endif
4056
4057
4058static void gen_sync(DisasContext *ctx)
4059{
4060 TCGBar bar = TCG_MO_ALL;
4061 uint32_t l = (ctx->opcode >> 21) & 3;
4062
4063 if ((l == 1) && (ctx->insns_flags2 & PPC2_MEM_LWSYNC)) {
4064 bar = TCG_MO_LD_LD | TCG_MO_LD_ST | TCG_MO_ST_ST;
4065 }
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075 if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
4076 gen_check_tlb_flush(ctx, true);
4077 }
4078
4079 tcg_gen_mb(bar | TCG_BAR_SC);
4080}
4081
4082
4083static void gen_wait(DisasContext *ctx)
4084{
4085 uint32_t wc;
4086
4087 if (ctx->insns_flags & PPC_WAIT) {
4088
4089
4090 if (ctx->insns_flags2 & PPC2_PM_ISA206) {
4091
4092 wc = WC(ctx->opcode);
4093 } else {
4094 wc = 0;
4095 }
4096
4097 } else if (ctx->insns_flags2 & PPC2_ISA300) {
4098
4099 wc = WC(ctx->opcode);
4100 if (ctx->insns_flags2 & PPC2_ISA310) {
4101 uint32_t pl = PL(ctx->opcode);
4102
4103
4104 if (wc == 3) {
4105 gen_invalid(ctx);
4106 return;
4107 }
4108
4109
4110 if (pl > 0 && wc != 2) {
4111 gen_invalid(ctx);
4112 return;
4113 }
4114
4115 } else {
4116
4117 if (wc > 0) {
4118 gen_invalid(ctx);
4119 return;
4120 }
4121 }
4122
4123 } else {
4124 warn_report("wait instruction decoded with wrong ISA flags.");
4125 gen_invalid(ctx);
4126 return;
4127 }
4128
4129
4130
4131
4132
4133 if (wc == 0) {
4134 TCGv_i32 t0 = tcg_const_i32(1);
4135 tcg_gen_st_i32(t0, cpu_env,
4136 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
4137 tcg_temp_free_i32(t0);
4138
4139 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4140 }
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170}
4171
4172#if defined(TARGET_PPC64)
4173static void gen_doze(DisasContext *ctx)
4174{
4175#if defined(CONFIG_USER_ONLY)
4176 GEN_PRIV(ctx);
4177#else
4178 TCGv_i32 t;
4179
4180 CHK_HV(ctx);
4181 t = tcg_const_i32(PPC_PM_DOZE);
4182 gen_helper_pminsn(cpu_env, t);
4183 tcg_temp_free_i32(t);
4184
4185 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4186#endif
4187}
4188
4189static void gen_nap(DisasContext *ctx)
4190{
4191#if defined(CONFIG_USER_ONLY)
4192 GEN_PRIV(ctx);
4193#else
4194 TCGv_i32 t;
4195
4196 CHK_HV(ctx);
4197 t = tcg_const_i32(PPC_PM_NAP);
4198 gen_helper_pminsn(cpu_env, t);
4199 tcg_temp_free_i32(t);
4200
4201 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4202#endif
4203}
4204
4205static void gen_stop(DisasContext *ctx)
4206{
4207#if defined(CONFIG_USER_ONLY)
4208 GEN_PRIV(ctx);
4209#else
4210 TCGv_i32 t;
4211
4212 CHK_HV(ctx);
4213 t = tcg_const_i32(PPC_PM_STOP);
4214 gen_helper_pminsn(cpu_env, t);
4215 tcg_temp_free_i32(t);
4216
4217 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4218#endif
4219}
4220
4221static void gen_sleep(DisasContext *ctx)
4222{
4223#if defined(CONFIG_USER_ONLY)
4224 GEN_PRIV(ctx);
4225#else
4226 TCGv_i32 t;
4227
4228 CHK_HV(ctx);
4229 t = tcg_const_i32(PPC_PM_SLEEP);
4230 gen_helper_pminsn(cpu_env, t);
4231 tcg_temp_free_i32(t);
4232
4233 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4234#endif
4235}
4236
4237static void gen_rvwinkle(DisasContext *ctx)
4238{
4239#if defined(CONFIG_USER_ONLY)
4240 GEN_PRIV(ctx);
4241#else
4242 TCGv_i32 t;
4243
4244 CHK_HV(ctx);
4245 t = tcg_const_i32(PPC_PM_RVWINKLE);
4246 gen_helper_pminsn(cpu_env, t);
4247 tcg_temp_free_i32(t);
4248
4249 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4250#endif
4251}
4252#endif
4253
4254static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
4255{
4256#if defined(TARGET_PPC64)
4257 if (ctx->has_cfar) {
4258 tcg_gen_movi_tl(cpu_cfar, nip);
4259 }
4260#endif
4261}
4262
4263#if defined(TARGET_PPC64)
4264static void pmu_count_insns(DisasContext *ctx)
4265{
4266
4267
4268
4269
4270 if (!ctx->pmu_insn_cnt) {
4271 return;
4272 }
4273
4274 #if !defined(CONFIG_USER_ONLY)
4275 TCGLabel *l;
4276 TCGv t0;
4277
4278
4279
4280
4281
4282
4283
4284 gen_icount_io_start(ctx);
4285
4286
4287 if (!ctx->pmc_other) {
4288 l = gen_new_label();
4289 t0 = tcg_temp_new();
4290
4291 gen_load_spr(t0, SPR_POWER_PMC5);
4292 tcg_gen_addi_tl(t0, t0, ctx->base.num_insns);
4293 gen_store_spr(SPR_POWER_PMC5, t0);
4294
4295 if (ctx->mmcr0_pmcjce) {
4296 tcg_gen_brcondi_tl(TCG_COND_LT, t0, PMC_COUNTER_NEGATIVE_VAL, l);
4297 gen_helper_handle_pmc5_overflow(cpu_env);
4298 }
4299
4300 gen_set_label(l);
4301 tcg_temp_free(t0);
4302 } else {
4303 gen_helper_insns_inc(cpu_env, tcg_constant_i32(ctx->base.num_insns));
4304 }
4305 #else
4306
4307
4308
4309
4310
4311 TCGv t0 = tcg_temp_new();
4312
4313 gen_load_spr(t0, SPR_POWER_PMC5);
4314 tcg_gen_addi_tl(t0, t0, ctx->base.num_insns);
4315 gen_store_spr(SPR_POWER_PMC5, t0);
4316
4317 tcg_temp_free(t0);
4318 #endif
4319}
4320#else
4321static void pmu_count_insns(DisasContext *ctx)
4322{
4323 return;
4324}
4325#endif
4326
4327static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4328{
4329 return translator_use_goto_tb(&ctx->base, dest);
4330}
4331
4332static void gen_lookup_and_goto_ptr(DisasContext *ctx)
4333{
4334 if (unlikely(ctx->singlestep_enabled)) {
4335 gen_debug_exception(ctx);
4336 } else {
4337
4338
4339
4340
4341 if (ctx->base.tb->flags & CF_NO_GOTO_PTR) {
4342 pmu_count_insns(ctx);
4343 }
4344
4345 tcg_gen_lookup_and_goto_ptr();
4346 }
4347}
4348
4349
4350static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4351{
4352 if (NARROW_MODE(ctx)) {
4353 dest = (uint32_t) dest;
4354 }
4355 if (use_goto_tb(ctx, dest)) {
4356 pmu_count_insns(ctx);
4357 tcg_gen_goto_tb(n);
4358 tcg_gen_movi_tl(cpu_nip, dest & ~3);
4359 tcg_gen_exit_tb(ctx->base.tb, n);
4360 } else {
4361 tcg_gen_movi_tl(cpu_nip, dest & ~3);
4362 gen_lookup_and_goto_ptr(ctx);
4363 }
4364}
4365
4366static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
4367{
4368 if (NARROW_MODE(ctx)) {
4369 nip = (uint32_t)nip;
4370 }
4371 tcg_gen_movi_tl(cpu_lr, nip);
4372}
4373
4374
4375static void gen_b(DisasContext *ctx)
4376{
4377 target_ulong li, target;
4378
4379
4380 li = LI(ctx->opcode);
4381 li = (li ^ 0x02000000) - 0x02000000;
4382 if (likely(AA(ctx->opcode) == 0)) {
4383 target = ctx->cia + li;
4384 } else {
4385 target = li;
4386 }
4387 if (LK(ctx->opcode)) {
4388 gen_setlr(ctx, ctx->base.pc_next);
4389 }
4390 gen_update_cfar(ctx, ctx->cia);
4391 gen_goto_tb(ctx, 0, target);
4392 ctx->base.is_jmp = DISAS_NORETURN;
4393}
4394
4395#define BCOND_IM 0
4396#define BCOND_LR 1
4397#define BCOND_CTR 2
4398#define BCOND_TAR 3
4399
4400static void gen_bcond(DisasContext *ctx, int type)
4401{
4402 uint32_t bo = BO(ctx->opcode);
4403 TCGLabel *l1;
4404 TCGv target;
4405
4406 if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
4407 target = tcg_temp_local_new();
4408 if (type == BCOND_CTR) {
4409 tcg_gen_mov_tl(target, cpu_ctr);
4410 } else if (type == BCOND_TAR) {
4411 gen_load_spr(target, SPR_TAR);
4412 } else {
4413 tcg_gen_mov_tl(target, cpu_lr);
4414 }
4415 } else {
4416 target = NULL;
4417 }
4418 if (LK(ctx->opcode)) {
4419 gen_setlr(ctx, ctx->base.pc_next);
4420 }
4421 l1 = gen_new_label();
4422 if ((bo & 0x4) == 0) {
4423
4424 TCGv temp = tcg_temp_new();
4425
4426 if (type == BCOND_CTR) {
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441 if (unlikely(!is_book3s_arch2x(ctx))) {
4442 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4443 tcg_temp_free(temp);
4444 tcg_temp_free(target);
4445 return;
4446 }
4447
4448 if (NARROW_MODE(ctx)) {
4449 tcg_gen_ext32u_tl(temp, cpu_ctr);
4450 } else {
4451 tcg_gen_mov_tl(temp, cpu_ctr);
4452 }
4453 if (bo & 0x2) {
4454 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
4455 } else {
4456 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
4457 }
4458 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
4459 } else {
4460 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
4461 if (NARROW_MODE(ctx)) {
4462 tcg_gen_ext32u_tl(temp, cpu_ctr);
4463 } else {
4464 tcg_gen_mov_tl(temp, cpu_ctr);
4465 }
4466 if (bo & 0x2) {
4467 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
4468 } else {
4469 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
4470 }
4471 }
4472 tcg_temp_free(temp);
4473 }
4474 if ((bo & 0x10) == 0) {
4475
4476 uint32_t bi = BI(ctx->opcode);
4477 uint32_t mask = 0x08 >> (bi & 0x03);
4478 TCGv_i32 temp = tcg_temp_new_i32();
4479
4480 if (bo & 0x8) {
4481 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4482 tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
4483 } else {
4484 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4485 tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
4486 }
4487 tcg_temp_free_i32(temp);
4488 }
4489 gen_update_cfar(ctx, ctx->cia);
4490 if (type == BCOND_IM) {
4491 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
4492 if (likely(AA(ctx->opcode) == 0)) {
4493 gen_goto_tb(ctx, 0, ctx->cia + li);
4494 } else {
4495 gen_goto_tb(ctx, 0, li);
4496 }
4497 } else {
4498 if (NARROW_MODE(ctx)) {
4499 tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
4500 } else {
4501 tcg_gen_andi_tl(cpu_nip, target, ~3);
4502 }
4503 gen_lookup_and_goto_ptr(ctx);
4504 tcg_temp_free(target);
4505 }
4506 if ((bo & 0x14) != 0x14) {
4507
4508 gen_set_label(l1);
4509 gen_goto_tb(ctx, 1, ctx->base.pc_next);
4510 }
4511 ctx->base.is_jmp = DISAS_NORETURN;
4512}
4513
4514static void gen_bc(DisasContext *ctx)
4515{
4516 gen_bcond(ctx, BCOND_IM);
4517}
4518
4519static void gen_bcctr(DisasContext *ctx)
4520{
4521 gen_bcond(ctx, BCOND_CTR);
4522}
4523
4524static void gen_bclr(DisasContext *ctx)
4525{
4526 gen_bcond(ctx, BCOND_LR);
4527}
4528
4529static void gen_bctar(DisasContext *ctx)
4530{
4531 gen_bcond(ctx, BCOND_TAR);
4532}
4533
4534
4535#define GEN_CRLOGIC(name, tcg_op, opc) \
4536static void glue(gen_, name)(DisasContext *ctx) \
4537{ \
4538 uint8_t bitmask; \
4539 int sh; \
4540 TCGv_i32 t0, t1; \
4541 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
4542 t0 = tcg_temp_new_i32(); \
4543 if (sh > 0) \
4544 tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
4545 else if (sh < 0) \
4546 tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
4547 else \
4548 tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
4549 t1 = tcg_temp_new_i32(); \
4550 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
4551 if (sh > 0) \
4552 tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
4553 else if (sh < 0) \
4554 tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
4555 else \
4556 tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
4557 tcg_op(t0, t0, t1); \
4558 bitmask = 0x08 >> (crbD(ctx->opcode) & 0x03); \
4559 tcg_gen_andi_i32(t0, t0, bitmask); \
4560 tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
4561 tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
4562 tcg_temp_free_i32(t0); \
4563 tcg_temp_free_i32(t1); \
4564}
4565
4566
4567GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
4568
4569GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
4570
4571GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
4572
4573GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
4574
4575GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
4576
4577GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
4578
4579GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
4580
4581GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
4582
4583
4584static void gen_mcrf(DisasContext *ctx)
4585{
4586 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
4587}
4588
4589
4590
4591
4592static void gen_rfi(DisasContext *ctx)
4593{
4594#if defined(CONFIG_USER_ONLY)
4595 GEN_PRIV(ctx);
4596#else
4597
4598
4599
4600
4601 if (is_book3s_arch2x(ctx)) {
4602 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4603 return;
4604 }
4605
4606 CHK_SV(ctx);
4607 gen_icount_io_start(ctx);
4608 gen_update_cfar(ctx, ctx->cia);
4609 gen_helper_rfi(cpu_env);
4610 ctx->base.is_jmp = DISAS_EXIT;
4611#endif
4612}
4613
4614#if defined(TARGET_PPC64)
4615static void gen_rfid(DisasContext *ctx)
4616{
4617#if defined(CONFIG_USER_ONLY)
4618 GEN_PRIV(ctx);
4619#else
4620
4621 CHK_SV(ctx);
4622 gen_icount_io_start(ctx);
4623 gen_update_cfar(ctx, ctx->cia);
4624 gen_helper_rfid(cpu_env);
4625 ctx->base.is_jmp = DISAS_EXIT;
4626#endif
4627}
4628
4629#if !defined(CONFIG_USER_ONLY)
4630static void gen_rfscv(DisasContext *ctx)
4631{
4632#if defined(CONFIG_USER_ONLY)
4633 GEN_PRIV(ctx);
4634#else
4635
4636 CHK_SV(ctx);
4637 gen_icount_io_start(ctx);
4638 gen_update_cfar(ctx, ctx->cia);
4639 gen_helper_rfscv(cpu_env);
4640 ctx->base.is_jmp = DISAS_EXIT;
4641#endif
4642}
4643#endif
4644
4645static void gen_hrfid(DisasContext *ctx)
4646{
4647#if defined(CONFIG_USER_ONLY)
4648 GEN_PRIV(ctx);
4649#else
4650
4651 CHK_HV(ctx);
4652 gen_helper_hrfid(cpu_env);
4653 ctx->base.is_jmp = DISAS_EXIT;
4654#endif
4655}
4656#endif
4657
4658
4659#if defined(CONFIG_USER_ONLY)
4660#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
4661#else
4662#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
4663#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED
4664#endif
4665static void gen_sc(DisasContext *ctx)
4666{
4667 uint32_t lev;
4668
4669 lev = (ctx->opcode >> 5) & 0x7F;
4670 gen_exception_err(ctx, POWERPC_SYSCALL, lev);
4671}
4672
4673#if defined(TARGET_PPC64)
4674#if !defined(CONFIG_USER_ONLY)
4675static void gen_scv(DisasContext *ctx)
4676{
4677 uint32_t lev = (ctx->opcode >> 5) & 0x7F;
4678
4679
4680 gen_update_nip(ctx, ctx->cia);
4681 gen_helper_scv(cpu_env, tcg_constant_i32(lev));
4682
4683 ctx->base.is_jmp = DISAS_NORETURN;
4684}
4685#endif
4686#endif
4687
4688
4689
4690
4691static bool check_unconditional_trap(DisasContext *ctx)
4692{
4693
4694 if (TO(ctx->opcode) == 0) {
4695 return true;
4696 }
4697
4698 if (TO(ctx->opcode) == 31) {
4699 gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
4700 return true;
4701 }
4702 return false;
4703}
4704
4705
4706static void gen_tw(DisasContext *ctx)
4707{
4708 TCGv_i32 t0;
4709
4710 if (check_unconditional_trap(ctx)) {
4711 return;
4712 }
4713 t0 = tcg_const_i32(TO(ctx->opcode));
4714 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4715 t0);
4716 tcg_temp_free_i32(t0);
4717}
4718
4719
4720static void gen_twi(DisasContext *ctx)
4721{
4722 TCGv t0;
4723 TCGv_i32 t1;
4724
4725 if (check_unconditional_trap(ctx)) {
4726 return;
4727 }
4728 t0 = tcg_const_tl(SIMM(ctx->opcode));
4729 t1 = tcg_const_i32(TO(ctx->opcode));
4730 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
4731 tcg_temp_free(t0);
4732 tcg_temp_free_i32(t1);
4733}
4734
4735#if defined(TARGET_PPC64)
4736
4737static void gen_td(DisasContext *ctx)
4738{
4739 TCGv_i32 t0;
4740
4741 if (check_unconditional_trap(ctx)) {
4742 return;
4743 }
4744 t0 = tcg_const_i32(TO(ctx->opcode));
4745 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4746 t0);
4747 tcg_temp_free_i32(t0);
4748}
4749
4750
4751static void gen_tdi(DisasContext *ctx)
4752{
4753 TCGv t0;
4754 TCGv_i32 t1;
4755
4756 if (check_unconditional_trap(ctx)) {
4757 return;
4758 }
4759 t0 = tcg_const_tl(SIMM(ctx->opcode));
4760 t1 = tcg_const_i32(TO(ctx->opcode));
4761 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
4762 tcg_temp_free(t0);
4763 tcg_temp_free_i32(t1);
4764}
4765#endif
4766
4767
4768
4769
4770static void gen_mcrxr(DisasContext *ctx)
4771{
4772 TCGv_i32 t0 = tcg_temp_new_i32();
4773 TCGv_i32 t1 = tcg_temp_new_i32();
4774 TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
4775
4776 tcg_gen_trunc_tl_i32(t0, cpu_so);
4777 tcg_gen_trunc_tl_i32(t1, cpu_ov);
4778 tcg_gen_trunc_tl_i32(dst, cpu_ca);
4779 tcg_gen_shli_i32(t0, t0, 3);
4780 tcg_gen_shli_i32(t1, t1, 2);
4781 tcg_gen_shli_i32(dst, dst, 1);
4782 tcg_gen_or_i32(dst, dst, t0);
4783 tcg_gen_or_i32(dst, dst, t1);
4784 tcg_temp_free_i32(t0);
4785 tcg_temp_free_i32(t1);
4786
4787 tcg_gen_movi_tl(cpu_so, 0);
4788 tcg_gen_movi_tl(cpu_ov, 0);
4789 tcg_gen_movi_tl(cpu_ca, 0);
4790}
4791
4792#ifdef TARGET_PPC64
4793
4794static void gen_mcrxrx(DisasContext *ctx)
4795{
4796 TCGv t0 = tcg_temp_new();
4797 TCGv t1 = tcg_temp_new();
4798 TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
4799
4800
4801 tcg_gen_shli_tl(t0, cpu_ov, 1);
4802 tcg_gen_or_tl(t0, t0, cpu_ov32);
4803 tcg_gen_shli_tl(t0, t0, 2);
4804
4805 tcg_gen_shli_tl(t1, cpu_ca, 1);
4806 tcg_gen_or_tl(t1, t1, cpu_ca32);
4807 tcg_gen_or_tl(t0, t0, t1);
4808 tcg_gen_trunc_tl_i32(dst, t0);
4809 tcg_temp_free(t0);
4810 tcg_temp_free(t1);
4811}
4812#endif
4813
4814
4815static void gen_mfcr(DisasContext *ctx)
4816{
4817 uint32_t crm, crn;
4818
4819 if (likely(ctx->opcode & 0x00100000)) {
4820 crm = CRM(ctx->opcode);
4821 if (likely(crm && ((crm & (crm - 1)) == 0))) {
4822 crn = ctz32(crm);
4823 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
4824 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
4825 cpu_gpr[rD(ctx->opcode)], crn * 4);
4826 }
4827 } else {
4828 TCGv_i32 t0 = tcg_temp_new_i32();
4829 tcg_gen_mov_i32(t0, cpu_crf[0]);
4830 tcg_gen_shli_i32(t0, t0, 4);
4831 tcg_gen_or_i32(t0, t0, cpu_crf[1]);
4832 tcg_gen_shli_i32(t0, t0, 4);
4833 tcg_gen_or_i32(t0, t0, cpu_crf[2]);
4834 tcg_gen_shli_i32(t0, t0, 4);
4835 tcg_gen_or_i32(t0, t0, cpu_crf[3]);
4836 tcg_gen_shli_i32(t0, t0, 4);
4837 tcg_gen_or_i32(t0, t0, cpu_crf[4]);
4838 tcg_gen_shli_i32(t0, t0, 4);
4839 tcg_gen_or_i32(t0, t0, cpu_crf[5]);
4840 tcg_gen_shli_i32(t0, t0, 4);
4841 tcg_gen_or_i32(t0, t0, cpu_crf[6]);
4842 tcg_gen_shli_i32(t0, t0, 4);
4843 tcg_gen_or_i32(t0, t0, cpu_crf[7]);
4844 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
4845 tcg_temp_free_i32(t0);
4846 }
4847}
4848
4849
4850static void gen_mfmsr(DisasContext *ctx)
4851{
4852 CHK_SV(ctx);
4853 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
4854}
4855
4856
4857static inline void gen_op_mfspr(DisasContext *ctx)
4858{
4859 void (*read_cb)(DisasContext *ctx, int gprn, int sprn);
4860 uint32_t sprn = SPR(ctx->opcode);
4861
4862#if defined(CONFIG_USER_ONLY)
4863 read_cb = ctx->spr_cb[sprn].uea_read;
4864#else
4865 if (ctx->pr) {
4866 read_cb = ctx->spr_cb[sprn].uea_read;
4867 } else if (ctx->hv) {
4868 read_cb = ctx->spr_cb[sprn].hea_read;
4869 } else {
4870 read_cb = ctx->spr_cb[sprn].oea_read;
4871 }
4872#endif
4873 if (likely(read_cb != NULL)) {
4874 if (likely(read_cb != SPR_NOACCESS)) {
4875 (*read_cb)(ctx, rD(ctx->opcode), sprn);
4876 } else {
4877
4878
4879
4880
4881
4882
4883 if (sprn != SPR_PVR) {
4884 qemu_log_mask(LOG_GUEST_ERROR, "Trying to read privileged spr "
4885 "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
4886 ctx->cia);
4887 }
4888 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
4889 }
4890 } else {
4891
4892 if ((ctx->insns_flags2 & PPC2_ISA207S) &&
4893 (sprn >= 808 && sprn <= 811)) {
4894
4895 return;
4896 }
4897
4898 qemu_log_mask(LOG_GUEST_ERROR,
4899 "Trying to read invalid spr %d (0x%03x) at "
4900 TARGET_FMT_lx "\n", sprn, sprn, ctx->cia);
4901
4902
4903
4904
4905
4906 if (sprn & 0x10) {
4907 if (ctx->pr) {
4908 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
4909 }
4910 } else {
4911 if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 || sprn == 6) {
4912 gen_hvpriv_exception(ctx, POWERPC_EXCP_PRIV_REG);
4913 }
4914 }
4915 }
4916}
4917
4918static void gen_mfspr(DisasContext *ctx)
4919{
4920 gen_op_mfspr(ctx);
4921}
4922
4923
4924static void gen_mftb(DisasContext *ctx)
4925{
4926 gen_op_mfspr(ctx);
4927}
4928
4929
4930static void gen_mtcrf(DisasContext *ctx)
4931{
4932 uint32_t crm, crn;
4933
4934 crm = CRM(ctx->opcode);
4935 if (likely((ctx->opcode & 0x00100000))) {
4936 if (crm && ((crm & (crm - 1)) == 0)) {
4937 TCGv_i32 temp = tcg_temp_new_i32();
4938 crn = ctz32(crm);
4939 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4940 tcg_gen_shri_i32(temp, temp, crn * 4);
4941 tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
4942 tcg_temp_free_i32(temp);
4943 }
4944 } else {
4945 TCGv_i32 temp = tcg_temp_new_i32();
4946 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4947 for (crn = 0 ; crn < 8 ; crn++) {
4948 if (crm & (1 << crn)) {
4949 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
4950 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
4951 }
4952 }
4953 tcg_temp_free_i32(temp);
4954 }
4955}
4956
4957
4958#if defined(TARGET_PPC64)
4959static void gen_mtmsrd(DisasContext *ctx)
4960{
4961 if (unlikely(!is_book3s_arch2x(ctx))) {
4962 gen_invalid(ctx);
4963 return;
4964 }
4965
4966 CHK_SV(ctx);
4967
4968#if !defined(CONFIG_USER_ONLY)
4969 TCGv t0, t1;
4970 target_ulong mask;
4971
4972 t0 = tcg_temp_new();
4973 t1 = tcg_temp_new();
4974
4975 gen_icount_io_start(ctx);
4976
4977 if (ctx->opcode & 0x00010000) {
4978
4979 mask = (1ULL << MSR_RI) | (1ULL << MSR_EE);
4980 } else {
4981
4982 mask = ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S) |
4983 (1ULL << MSR_HV));
4984
4985
4986
4987
4988
4989 gen_update_nip(ctx, ctx->base.pc_next);
4990 }
4991
4992 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], mask);
4993 tcg_gen_andi_tl(t1, cpu_msr, ~mask);
4994 tcg_gen_or_tl(t0, t0, t1);
4995
4996 gen_helper_store_msr(cpu_env, t0);
4997
4998
4999 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
5000
5001 tcg_temp_free(t0);
5002 tcg_temp_free(t1);
5003#endif
5004}
5005#endif
5006
5007static void gen_mtmsr(DisasContext *ctx)
5008{
5009 CHK_SV(ctx);
5010
5011#if !defined(CONFIG_USER_ONLY)
5012 TCGv t0, t1;
5013 target_ulong mask = 0xFFFFFFFF;
5014
5015 t0 = tcg_temp_new();
5016 t1 = tcg_temp_new();
5017
5018 gen_icount_io_start(ctx);
5019 if (ctx->opcode & 0x00010000) {
5020
5021 mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
5022 } else {
5023
5024 mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
5025
5026
5027
5028
5029
5030
5031 gen_update_nip(ctx, ctx->base.pc_next);
5032 }
5033
5034 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], mask);
5035 tcg_gen_andi_tl(t1, cpu_msr, ~mask);
5036 tcg_gen_or_tl(t0, t0, t1);
5037
5038 gen_helper_store_msr(cpu_env, t0);
5039
5040
5041 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
5042
5043 tcg_temp_free(t0);
5044 tcg_temp_free(t1);
5045#endif
5046}
5047
5048
5049static void gen_mtspr(DisasContext *ctx)
5050{
5051 void (*write_cb)(DisasContext *ctx, int sprn, int gprn);
5052 uint32_t sprn = SPR(ctx->opcode);
5053
5054#if defined(CONFIG_USER_ONLY)
5055 write_cb = ctx->spr_cb[sprn].uea_write;
5056#else
5057 if (ctx->pr) {
5058 write_cb = ctx->spr_cb[sprn].uea_write;
5059 } else if (ctx->hv) {
5060 write_cb = ctx->spr_cb[sprn].hea_write;
5061 } else {
5062 write_cb = ctx->spr_cb[sprn].oea_write;
5063 }
5064#endif
5065 if (likely(write_cb != NULL)) {
5066 if (likely(write_cb != SPR_NOACCESS)) {
5067 (*write_cb)(ctx, sprn, rS(ctx->opcode));
5068 } else {
5069
5070 qemu_log_mask(LOG_GUEST_ERROR, "Trying to write privileged spr "
5071 "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
5072 ctx->cia);
5073 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
5074 }
5075 } else {
5076
5077 if ((ctx->insns_flags2 & PPC2_ISA207S) &&
5078 (sprn >= 808 && sprn <= 811)) {
5079
5080 return;
5081 }
5082
5083
5084 qemu_log_mask(LOG_GUEST_ERROR,
5085 "Trying to write invalid spr %d (0x%03x) at "
5086 TARGET_FMT_lx "\n", sprn, sprn, ctx->cia);
5087
5088
5089
5090
5091
5092
5093 if (sprn & 0x10) {
5094 if (ctx->pr) {
5095 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
5096 }
5097 } else {
5098 if (ctx->pr || sprn == 0) {
5099 gen_hvpriv_exception(ctx, POWERPC_EXCP_PRIV_REG);
5100 }
5101 }
5102 }
5103}
5104
5105#if defined(TARGET_PPC64)
5106
5107static void gen_setb(DisasContext *ctx)
5108{
5109 TCGv_i32 t0 = tcg_temp_new_i32();
5110 TCGv_i32 t8 = tcg_constant_i32(8);
5111 TCGv_i32 tm1 = tcg_constant_i32(-1);
5112 int crf = crfS(ctx->opcode);
5113
5114 tcg_gen_setcondi_i32(TCG_COND_GEU, t0, cpu_crf[crf], 4);
5115 tcg_gen_movcond_i32(TCG_COND_GEU, t0, cpu_crf[crf], t8, tm1, t0);
5116 tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
5117
5118 tcg_temp_free_i32(t0);
5119}
5120#endif
5121
5122
5123
5124
5125static void gen_dcbf(DisasContext *ctx)
5126{
5127
5128 TCGv t0;
5129 gen_set_access_type(ctx, ACCESS_CACHE);
5130 t0 = tcg_temp_new();
5131 gen_addr_reg_index(ctx, t0);
5132 gen_qemu_ld8u(ctx, t0, t0);
5133 tcg_temp_free(t0);
5134}
5135
5136
5137static void gen_dcbfep(DisasContext *ctx)
5138{
5139
5140 TCGv t0;
5141 CHK_SV(ctx);
5142 gen_set_access_type(ctx, ACCESS_CACHE);
5143 t0 = tcg_temp_new();
5144 gen_addr_reg_index(ctx, t0);
5145 tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
5146 tcg_temp_free(t0);
5147}
5148
5149
5150static void gen_dcbi(DisasContext *ctx)
5151{
5152#if defined(CONFIG_USER_ONLY)
5153 GEN_PRIV(ctx);
5154#else
5155 TCGv EA, val;
5156
5157 CHK_SV(ctx);
5158 EA = tcg_temp_new();
5159 gen_set_access_type(ctx, ACCESS_CACHE);
5160 gen_addr_reg_index(ctx, EA);
5161 val = tcg_temp_new();
5162
5163 gen_qemu_ld8u(ctx, val, EA);
5164 gen_qemu_st8(ctx, val, EA);
5165 tcg_temp_free(val);
5166 tcg_temp_free(EA);
5167#endif
5168}
5169
5170
5171static void gen_dcbst(DisasContext *ctx)
5172{
5173
5174 TCGv t0;
5175 gen_set_access_type(ctx, ACCESS_CACHE);
5176 t0 = tcg_temp_new();
5177 gen_addr_reg_index(ctx, t0);
5178 gen_qemu_ld8u(ctx, t0, t0);
5179 tcg_temp_free(t0);
5180}
5181
5182
5183static void gen_dcbstep(DisasContext *ctx)
5184{
5185
5186 TCGv t0;
5187 gen_set_access_type(ctx, ACCESS_CACHE);
5188 t0 = tcg_temp_new();
5189 gen_addr_reg_index(ctx, t0);
5190 tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
5191 tcg_temp_free(t0);
5192}
5193
5194
5195static void gen_dcbt(DisasContext *ctx)
5196{
5197
5198
5199
5200
5201
5202}
5203
5204
5205static void gen_dcbtep(DisasContext *ctx)
5206{
5207
5208
5209
5210
5211
5212}
5213
5214
5215static void gen_dcbtst(DisasContext *ctx)
5216{
5217
5218
5219
5220
5221
5222}
5223
5224
5225static void gen_dcbtstep(DisasContext *ctx)
5226{
5227
5228
5229
5230
5231
5232}
5233
5234
5235static void gen_dcbtls(DisasContext *ctx)
5236{
5237
5238 TCGv t0 = tcg_temp_new();
5239 gen_load_spr(t0, SPR_Exxx_L1CSR0);
5240 tcg_gen_ori_tl(t0, t0, L1CSR0_CUL);
5241 gen_store_spr(SPR_Exxx_L1CSR0, t0);
5242 tcg_temp_free(t0);
5243}
5244
5245
5246static void gen_dcbz(DisasContext *ctx)
5247{
5248 TCGv tcgv_addr;
5249 TCGv_i32 tcgv_op;
5250
5251 gen_set_access_type(ctx, ACCESS_CACHE);
5252 tcgv_addr = tcg_temp_new();
5253 tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
5254 gen_addr_reg_index(ctx, tcgv_addr);
5255 gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_op);
5256 tcg_temp_free(tcgv_addr);
5257 tcg_temp_free_i32(tcgv_op);
5258}
5259
5260
5261static void gen_dcbzep(DisasContext *ctx)
5262{
5263 TCGv tcgv_addr;
5264 TCGv_i32 tcgv_op;
5265
5266 gen_set_access_type(ctx, ACCESS_CACHE);
5267 tcgv_addr = tcg_temp_new();
5268 tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
5269 gen_addr_reg_index(ctx, tcgv_addr);
5270 gen_helper_dcbzep(cpu_env, tcgv_addr, tcgv_op);
5271 tcg_temp_free(tcgv_addr);
5272 tcg_temp_free_i32(tcgv_op);
5273}
5274
5275
5276static void gen_dst(DisasContext *ctx)
5277{
5278 if (rA(ctx->opcode) == 0) {
5279 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5280 } else {
5281
5282 }
5283}
5284
5285
5286static void gen_dstst(DisasContext *ctx)
5287{
5288 if (rA(ctx->opcode) == 0) {
5289 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5290 } else {
5291
5292 }
5293
5294}
5295
5296
5297static void gen_dss(DisasContext *ctx)
5298{
5299
5300}
5301
5302
5303static void gen_icbi(DisasContext *ctx)
5304{
5305 TCGv t0;
5306 gen_set_access_type(ctx, ACCESS_CACHE);
5307 t0 = tcg_temp_new();
5308 gen_addr_reg_index(ctx, t0);
5309 gen_helper_icbi(cpu_env, t0);
5310 tcg_temp_free(t0);
5311}
5312
5313
5314static void gen_icbiep(DisasContext *ctx)
5315{
5316 TCGv t0;
5317 gen_set_access_type(ctx, ACCESS_CACHE);
5318 t0 = tcg_temp_new();
5319 gen_addr_reg_index(ctx, t0);
5320 gen_helper_icbiep(cpu_env, t0);
5321 tcg_temp_free(t0);
5322}
5323
5324
5325
5326static void gen_dcba(DisasContext *ctx)
5327{
5328
5329
5330
5331
5332
5333}
5334
5335
5336
5337
5338
5339static void gen_mfsr(DisasContext *ctx)
5340{
5341#if defined(CONFIG_USER_ONLY)
5342 GEN_PRIV(ctx);
5343#else
5344 TCGv t0;
5345
5346 CHK_SV(ctx);
5347 t0 = tcg_const_tl(SR(ctx->opcode));
5348 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5349 tcg_temp_free(t0);
5350#endif
5351}
5352
5353
5354static void gen_mfsrin(DisasContext *ctx)
5355{
5356#if defined(CONFIG_USER_ONLY)
5357 GEN_PRIV(ctx);
5358#else
5359 TCGv t0;
5360
5361 CHK_SV(ctx);
5362 t0 = tcg_temp_new();
5363 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
5364 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5365 tcg_temp_free(t0);
5366#endif
5367}
5368
5369
5370static void gen_mtsr(DisasContext *ctx)
5371{
5372#if defined(CONFIG_USER_ONLY)
5373 GEN_PRIV(ctx);
5374#else
5375 TCGv t0;
5376
5377 CHK_SV(ctx);
5378 t0 = tcg_const_tl(SR(ctx->opcode));
5379 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
5380 tcg_temp_free(t0);
5381#endif
5382}
5383
5384
5385static void gen_mtsrin(DisasContext *ctx)
5386{
5387#if defined(CONFIG_USER_ONLY)
5388 GEN_PRIV(ctx);
5389#else
5390 TCGv t0;
5391 CHK_SV(ctx);
5392
5393 t0 = tcg_temp_new();
5394 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
5395 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
5396 tcg_temp_free(t0);
5397#endif
5398}
5399
5400#if defined(TARGET_PPC64)
5401
5402
5403
5404static void gen_mfsr_64b(DisasContext *ctx)
5405{
5406#if defined(CONFIG_USER_ONLY)
5407 GEN_PRIV(ctx);
5408#else
5409 TCGv t0;
5410
5411 CHK_SV(ctx);
5412 t0 = tcg_const_tl(SR(ctx->opcode));
5413 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5414 tcg_temp_free(t0);
5415#endif
5416}
5417
5418
5419static void gen_mfsrin_64b(DisasContext *ctx)
5420{
5421#if defined(CONFIG_USER_ONLY)
5422 GEN_PRIV(ctx);
5423#else
5424 TCGv t0;
5425
5426 CHK_SV(ctx);
5427 t0 = tcg_temp_new();
5428 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
5429 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5430 tcg_temp_free(t0);
5431#endif
5432}
5433
5434
5435static void gen_mtsr_64b(DisasContext *ctx)
5436{
5437#if defined(CONFIG_USER_ONLY)
5438 GEN_PRIV(ctx);
5439#else
5440 TCGv t0;
5441
5442 CHK_SV(ctx);
5443 t0 = tcg_const_tl(SR(ctx->opcode));
5444 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
5445 tcg_temp_free(t0);
5446#endif
5447}
5448
5449
5450static void gen_mtsrin_64b(DisasContext *ctx)
5451{
5452#if defined(CONFIG_USER_ONLY)
5453 GEN_PRIV(ctx);
5454#else
5455 TCGv t0;
5456
5457 CHK_SV(ctx);
5458 t0 = tcg_temp_new();
5459 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
5460 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
5461 tcg_temp_free(t0);
5462#endif
5463}
5464
5465#endif
5466
5467
5468
5469
5470
5471static void gen_tlbia(DisasContext *ctx)
5472{
5473#if defined(CONFIG_USER_ONLY)
5474 GEN_PRIV(ctx);
5475#else
5476 CHK_HV(ctx);
5477
5478 gen_helper_tlbia(cpu_env);
5479#endif
5480}
5481
5482
5483static void gen_tlbsync(DisasContext *ctx)
5484{
5485#if defined(CONFIG_USER_ONLY)
5486 GEN_PRIV(ctx);
5487#else
5488
5489 if (ctx->gtse) {
5490 CHK_SV(ctx);
5491 } else {
5492 CHK_HV(ctx);
5493 }
5494
5495
5496 if (ctx->insns_flags & PPC_BOOKE) {
5497 gen_check_tlb_flush(ctx, true);
5498 }
5499#endif
5500}
5501
5502
5503
5504
5505
5506static void gen_eciwx(DisasContext *ctx)
5507{
5508 TCGv t0;
5509
5510 gen_set_access_type(ctx, ACCESS_EXT);
5511 t0 = tcg_temp_new();
5512 gen_addr_reg_index(ctx, t0);
5513 tcg_gen_qemu_ld_tl(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx,
5514 DEF_MEMOP(MO_UL | MO_ALIGN));
5515 tcg_temp_free(t0);
5516}
5517
5518
5519static void gen_ecowx(DisasContext *ctx)
5520{
5521 TCGv t0;
5522
5523 gen_set_access_type(ctx, ACCESS_EXT);
5524 t0 = tcg_temp_new();
5525 gen_addr_reg_index(ctx, t0);
5526 tcg_gen_qemu_st_tl(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx,
5527 DEF_MEMOP(MO_UL | MO_ALIGN));
5528 tcg_temp_free(t0);
5529}
5530
5531
5532
5533
5534static void gen_tlbld_6xx(DisasContext *ctx)
5535{
5536#if defined(CONFIG_USER_ONLY)
5537 GEN_PRIV(ctx);
5538#else
5539 CHK_SV(ctx);
5540 gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5541#endif
5542}
5543
5544
5545static void gen_tlbli_6xx(DisasContext *ctx)
5546{
5547#if defined(CONFIG_USER_ONLY)
5548 GEN_PRIV(ctx);
5549#else
5550 CHK_SV(ctx);
5551 gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5552#endif
5553}
5554
5555
5556
5557
5558static void gen_mfapidi(DisasContext *ctx)
5559{
5560
5561 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5562}
5563
5564
5565static void gen_tlbiva(DisasContext *ctx)
5566{
5567#if defined(CONFIG_USER_ONLY)
5568 GEN_PRIV(ctx);
5569#else
5570 TCGv t0;
5571
5572 CHK_SV(ctx);
5573 t0 = tcg_temp_new();
5574 gen_addr_reg_index(ctx, t0);
5575 gen_helper_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5576 tcg_temp_free(t0);
5577#endif
5578}
5579
5580
5581static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
5582 int ra, int rb, int rt, int Rc)
5583{
5584 TCGv t0, t1;
5585
5586 t0 = tcg_temp_local_new();
5587 t1 = tcg_temp_local_new();
5588
5589 switch (opc3 & 0x0D) {
5590 case 0x05:
5591
5592
5593
5594
5595
5596 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5597 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5598 tcg_gen_ext16s_tl(t1, t1);
5599 break;
5600 case 0x04:
5601
5602
5603
5604 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5605 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5606 tcg_gen_ext16u_tl(t1, t1);
5607 break;
5608 case 0x01:
5609
5610
5611
5612
5613
5614 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5615 tcg_gen_ext16s_tl(t0, t0);
5616 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5617 tcg_gen_ext16s_tl(t1, t1);
5618 break;
5619 case 0x00:
5620
5621
5622
5623 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5624 tcg_gen_ext16u_tl(t0, t0);
5625 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5626 tcg_gen_ext16u_tl(t1, t1);
5627 break;
5628 case 0x0D:
5629
5630
5631
5632
5633
5634 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5635 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5636 break;
5637 case 0x0C:
5638
5639
5640
5641 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5642 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5643 break;
5644 }
5645 if (opc2 & 0x04) {
5646
5647 tcg_gen_mul_tl(t1, t0, t1);
5648 if (opc2 & 0x02) {
5649
5650 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5651 } else {
5652
5653 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5654 }
5655
5656 if (opc3 & 0x12) {
5657
5658 TCGLabel *l1 = gen_new_label();
5659
5660 if (opc3 & 0x10) {
5661
5662 tcg_gen_movi_tl(cpu_ov, 0);
5663 }
5664 if (opc3 & 0x01) {
5665
5666 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5667 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5668 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5669 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
5670 if (opc3 & 0x02) {
5671
5672 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5673 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5674 }
5675 } else {
5676
5677 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5678 if (opc3 & 0x02) {
5679
5680 tcg_gen_movi_tl(t0, UINT32_MAX);
5681 }
5682 }
5683 if (opc3 & 0x10) {
5684
5685 tcg_gen_movi_tl(cpu_ov, 1);
5686 tcg_gen_movi_tl(cpu_so, 1);
5687 }
5688 gen_set_label(l1);
5689 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5690 }
5691 } else {
5692 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5693 }
5694 tcg_temp_free(t0);
5695 tcg_temp_free(t1);
5696 if (unlikely(Rc) != 0) {
5697
5698 gen_set_Rc0(ctx, cpu_gpr[rt]);
5699 }
5700}
5701
5702#define GEN_MAC_HANDLER(name, opc2, opc3) \
5703static void glue(gen_, name)(DisasContext *ctx) \
5704{ \
5705 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5706 rD(ctx->opcode), Rc(ctx->opcode)); \
5707}
5708
5709
5710GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5711
5712GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5713
5714GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5715
5716GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5717
5718GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5719
5720GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5721
5722GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5723
5724GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5725
5726GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5727
5728GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5729
5730GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5731
5732GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5733
5734GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5735
5736GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5737
5738GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5739
5740GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5741
5742GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5743
5744GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5745
5746GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5747
5748GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5749
5750GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5751
5752GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5753
5754GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5755
5756GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5757
5758GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5759
5760GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5761
5762GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5763
5764GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5765
5766GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5767
5768GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5769
5770GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5771
5772GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5773
5774GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5775
5776GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5777
5778GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5779
5780GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5781
5782
5783GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5784
5785GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5786
5787GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5788
5789GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5790
5791GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5792
5793GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5794
5795
5796static void gen_mfdcr(DisasContext *ctx)
5797{
5798#if defined(CONFIG_USER_ONLY)
5799 GEN_PRIV(ctx);
5800#else
5801 TCGv dcrn;
5802
5803 CHK_SV(ctx);
5804 dcrn = tcg_const_tl(SPR(ctx->opcode));
5805 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
5806 tcg_temp_free(dcrn);
5807#endif
5808}
5809
5810
5811static void gen_mtdcr(DisasContext *ctx)
5812{
5813#if defined(CONFIG_USER_ONLY)
5814 GEN_PRIV(ctx);
5815#else
5816 TCGv dcrn;
5817
5818 CHK_SV(ctx);
5819 dcrn = tcg_const_tl(SPR(ctx->opcode));
5820 gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
5821 tcg_temp_free(dcrn);
5822#endif
5823}
5824
5825
5826
5827static void gen_mfdcrx(DisasContext *ctx)
5828{
5829#if defined(CONFIG_USER_ONLY)
5830 GEN_PRIV(ctx);
5831#else
5832 CHK_SV(ctx);
5833 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
5834 cpu_gpr[rA(ctx->opcode)]);
5835
5836#endif
5837}
5838
5839
5840
5841static void gen_mtdcrx(DisasContext *ctx)
5842{
5843#if defined(CONFIG_USER_ONLY)
5844 GEN_PRIV(ctx);
5845#else
5846 CHK_SV(ctx);
5847 gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5848 cpu_gpr[rS(ctx->opcode)]);
5849
5850#endif
5851}
5852
5853
5854static void gen_dccci(DisasContext *ctx)
5855{
5856 CHK_SV(ctx);
5857
5858}
5859
5860
5861static void gen_dcread(DisasContext *ctx)
5862{
5863#if defined(CONFIG_USER_ONLY)
5864 GEN_PRIV(ctx);
5865#else
5866 TCGv EA, val;
5867
5868 CHK_SV(ctx);
5869 gen_set_access_type(ctx, ACCESS_CACHE);
5870 EA = tcg_temp_new();
5871 gen_addr_reg_index(ctx, EA);
5872 val = tcg_temp_new();
5873 gen_qemu_ld32u(ctx, val, EA);
5874 tcg_temp_free(val);
5875 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5876 tcg_temp_free(EA);
5877#endif
5878}
5879
5880
5881static void gen_icbt_40x(DisasContext *ctx)
5882{
5883
5884
5885
5886
5887
5888}
5889
5890
5891static void gen_iccci(DisasContext *ctx)
5892{
5893 CHK_SV(ctx);
5894
5895}
5896
5897
5898static void gen_icread(DisasContext *ctx)
5899{
5900 CHK_SV(ctx);
5901
5902}
5903
5904
5905static void gen_rfci_40x(DisasContext *ctx)
5906{
5907#if defined(CONFIG_USER_ONLY)
5908 GEN_PRIV(ctx);
5909#else
5910 CHK_SV(ctx);
5911
5912 gen_helper_40x_rfci(cpu_env);
5913 ctx->base.is_jmp = DISAS_EXIT;
5914#endif
5915}
5916
5917static void gen_rfci(DisasContext *ctx)
5918{
5919#if defined(CONFIG_USER_ONLY)
5920 GEN_PRIV(ctx);
5921#else
5922 CHK_SV(ctx);
5923
5924 gen_helper_rfci(cpu_env);
5925 ctx->base.is_jmp = DISAS_EXIT;
5926#endif
5927}
5928
5929
5930
5931
5932static void gen_rfdi(DisasContext *ctx)
5933{
5934#if defined(CONFIG_USER_ONLY)
5935 GEN_PRIV(ctx);
5936#else
5937 CHK_SV(ctx);
5938
5939 gen_helper_rfdi(cpu_env);
5940 ctx->base.is_jmp = DISAS_EXIT;
5941#endif
5942}
5943
5944
5945static void gen_rfmci(DisasContext *ctx)
5946{
5947#if defined(CONFIG_USER_ONLY)
5948 GEN_PRIV(ctx);
5949#else
5950 CHK_SV(ctx);
5951
5952 gen_helper_rfmci(cpu_env);
5953 ctx->base.is_jmp = DISAS_EXIT;
5954#endif
5955}
5956
5957
5958
5959
5960static void gen_tlbre_40x(DisasContext *ctx)
5961{
5962#if defined(CONFIG_USER_ONLY)
5963 GEN_PRIV(ctx);
5964#else
5965 CHK_SV(ctx);
5966 switch (rB(ctx->opcode)) {
5967 case 0:
5968 gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
5969 cpu_gpr[rA(ctx->opcode)]);
5970 break;
5971 case 1:
5972 gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
5973 cpu_gpr[rA(ctx->opcode)]);
5974 break;
5975 default:
5976 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5977 break;
5978 }
5979#endif
5980}
5981
5982
5983static void gen_tlbsx_40x(DisasContext *ctx)
5984{
5985#if defined(CONFIG_USER_ONLY)
5986 GEN_PRIV(ctx);
5987#else
5988 TCGv t0;
5989
5990 CHK_SV(ctx);
5991 t0 = tcg_temp_new();
5992 gen_addr_reg_index(ctx, t0);
5993 gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5994 tcg_temp_free(t0);
5995 if (Rc(ctx->opcode)) {
5996 TCGLabel *l1 = gen_new_label();
5997 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
5998 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5999 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6000 gen_set_label(l1);
6001 }
6002#endif
6003}
6004
6005
6006static void gen_tlbwe_40x(DisasContext *ctx)
6007{
6008#if defined(CONFIG_USER_ONLY)
6009 GEN_PRIV(ctx);
6010#else
6011 CHK_SV(ctx);
6012
6013 switch (rB(ctx->opcode)) {
6014 case 0:
6015 gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
6016 cpu_gpr[rS(ctx->opcode)]);
6017 break;
6018 case 1:
6019 gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
6020 cpu_gpr[rS(ctx->opcode)]);
6021 break;
6022 default:
6023 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6024 break;
6025 }
6026#endif
6027}
6028
6029
6030
6031
6032static void gen_tlbre_440(DisasContext *ctx)
6033{
6034#if defined(CONFIG_USER_ONLY)
6035 GEN_PRIV(ctx);
6036#else
6037 CHK_SV(ctx);
6038
6039 switch (rB(ctx->opcode)) {
6040 case 0:
6041 case 1:
6042 case 2:
6043 {
6044 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6045 gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
6046 t0, cpu_gpr[rA(ctx->opcode)]);
6047 tcg_temp_free_i32(t0);
6048 }
6049 break;
6050 default:
6051 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6052 break;
6053 }
6054#endif
6055}
6056
6057
6058static void gen_tlbsx_440(DisasContext *ctx)
6059{
6060#if defined(CONFIG_USER_ONLY)
6061 GEN_PRIV(ctx);
6062#else
6063 TCGv t0;
6064
6065 CHK_SV(ctx);
6066 t0 = tcg_temp_new();
6067 gen_addr_reg_index(ctx, t0);
6068 gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6069 tcg_temp_free(t0);
6070 if (Rc(ctx->opcode)) {
6071 TCGLabel *l1 = gen_new_label();
6072 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6073 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6074 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6075 gen_set_label(l1);
6076 }
6077#endif
6078}
6079
6080
6081static void gen_tlbwe_440(DisasContext *ctx)
6082{
6083#if defined(CONFIG_USER_ONLY)
6084 GEN_PRIV(ctx);
6085#else
6086 CHK_SV(ctx);
6087 switch (rB(ctx->opcode)) {
6088 case 0:
6089 case 1:
6090 case 2:
6091 {
6092 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6093 gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
6094 cpu_gpr[rS(ctx->opcode)]);
6095 tcg_temp_free_i32(t0);
6096 }
6097 break;
6098 default:
6099 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6100 break;
6101 }
6102#endif
6103}
6104
6105
6106
6107
6108static void gen_tlbre_booke206(DisasContext *ctx)
6109{
6110 #if defined(CONFIG_USER_ONLY)
6111 GEN_PRIV(ctx);
6112#else
6113 CHK_SV(ctx);
6114 gen_helper_booke206_tlbre(cpu_env);
6115#endif
6116}
6117
6118
6119static void gen_tlbsx_booke206(DisasContext *ctx)
6120{
6121#if defined(CONFIG_USER_ONLY)
6122 GEN_PRIV(ctx);
6123#else
6124 TCGv t0;
6125
6126 CHK_SV(ctx);
6127 if (rA(ctx->opcode)) {
6128 t0 = tcg_temp_new();
6129 tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6130 } else {
6131 t0 = tcg_const_tl(0);
6132 }
6133
6134 tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
6135 gen_helper_booke206_tlbsx(cpu_env, t0);
6136 tcg_temp_free(t0);
6137#endif
6138}
6139
6140
6141static void gen_tlbwe_booke206(DisasContext *ctx)
6142{
6143#if defined(CONFIG_USER_ONLY)
6144 GEN_PRIV(ctx);
6145#else
6146 CHK_SV(ctx);
6147 gen_helper_booke206_tlbwe(cpu_env);
6148#endif
6149}
6150
6151static void gen_tlbivax_booke206(DisasContext *ctx)
6152{
6153#if defined(CONFIG_USER_ONLY)
6154 GEN_PRIV(ctx);
6155#else
6156 TCGv t0;
6157
6158 CHK_SV(ctx);
6159 t0 = tcg_temp_new();
6160 gen_addr_reg_index(ctx, t0);
6161 gen_helper_booke206_tlbivax(cpu_env, t0);
6162 tcg_temp_free(t0);
6163#endif
6164}
6165
6166static void gen_tlbilx_booke206(DisasContext *ctx)
6167{
6168#if defined(CONFIG_USER_ONLY)
6169 GEN_PRIV(ctx);
6170#else
6171 TCGv t0;
6172
6173 CHK_SV(ctx);
6174 t0 = tcg_temp_new();
6175 gen_addr_reg_index(ctx, t0);
6176
6177 switch ((ctx->opcode >> 21) & 0x3) {
6178 case 0:
6179 gen_helper_booke206_tlbilx0(cpu_env, t0);
6180 break;
6181 case 1:
6182 gen_helper_booke206_tlbilx1(cpu_env, t0);
6183 break;
6184 case 3:
6185 gen_helper_booke206_tlbilx3(cpu_env, t0);
6186 break;
6187 default:
6188 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6189 break;
6190 }
6191
6192 tcg_temp_free(t0);
6193#endif
6194}
6195
6196
6197static void gen_wrtee(DisasContext *ctx)
6198{
6199#if defined(CONFIG_USER_ONLY)
6200 GEN_PRIV(ctx);
6201#else
6202 TCGv t0;
6203
6204 CHK_SV(ctx);
6205 t0 = tcg_temp_new();
6206 tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6207 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6208 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6209 gen_ppc_maybe_interrupt(ctx);
6210 tcg_temp_free(t0);
6211
6212
6213
6214
6215 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
6216#endif
6217}
6218
6219
6220static void gen_wrteei(DisasContext *ctx)
6221{
6222#if defined(CONFIG_USER_ONLY)
6223 GEN_PRIV(ctx);
6224#else
6225 CHK_SV(ctx);
6226 if (ctx->opcode & 0x00008000) {
6227 tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6228 gen_ppc_maybe_interrupt(ctx);
6229
6230 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
6231 } else {
6232 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6233 }
6234#endif
6235}
6236
6237
6238
6239
6240static void gen_dlmzb(DisasContext *ctx)
6241{
6242 TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6243 gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
6244 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6245 tcg_temp_free_i32(t0);
6246}
6247
6248
6249static void gen_mbar(DisasContext *ctx)
6250{
6251
6252}
6253
6254
6255static void gen_msync_4xx(DisasContext *ctx)
6256{
6257
6258 if ((ctx->insns_flags2 & PPC2_BOOKE206) &&
6259 (ctx->opcode & 0x03FFF801)) {
6260 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6261 }
6262
6263}
6264
6265
6266static void gen_icbt_440(DisasContext *ctx)
6267{
6268
6269
6270
6271
6272
6273}
6274
6275#if defined(TARGET_PPC64)
6276static void gen_maddld(DisasContext *ctx)
6277{
6278 TCGv_i64 t1 = tcg_temp_new_i64();
6279
6280 tcg_gen_mul_i64(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6281 tcg_gen_add_i64(cpu_gpr[rD(ctx->opcode)], t1, cpu_gpr[rC(ctx->opcode)]);
6282 tcg_temp_free_i64(t1);
6283}
6284
6285
6286static void gen_maddhd_maddhdu(DisasContext *ctx)
6287{
6288 TCGv_i64 lo = tcg_temp_new_i64();
6289 TCGv_i64 hi = tcg_temp_new_i64();
6290 TCGv_i64 t1 = tcg_temp_new_i64();
6291
6292 if (Rc(ctx->opcode)) {
6293 tcg_gen_mulu2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
6294 cpu_gpr[rB(ctx->opcode)]);
6295 tcg_gen_movi_i64(t1, 0);
6296 } else {
6297 tcg_gen_muls2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
6298 cpu_gpr[rB(ctx->opcode)]);
6299 tcg_gen_sari_i64(t1, cpu_gpr[rC(ctx->opcode)], 63);
6300 }
6301 tcg_gen_add2_i64(t1, cpu_gpr[rD(ctx->opcode)], lo, hi,
6302 cpu_gpr[rC(ctx->opcode)], t1);
6303 tcg_temp_free_i64(lo);
6304 tcg_temp_free_i64(hi);
6305 tcg_temp_free_i64(t1);
6306}
6307#endif
6308
6309static void gen_tbegin(DisasContext *ctx)
6310{
6311 if (unlikely(!ctx->tm_enabled)) {
6312 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
6313 return;
6314 }
6315 gen_helper_tbegin(cpu_env);
6316}
6317
6318#define GEN_TM_NOOP(name) \
6319static inline void gen_##name(DisasContext *ctx) \
6320{ \
6321 if (unlikely(!ctx->tm_enabled)) { \
6322 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
6323 return; \
6324 } \
6325
6326
6327
6328
6329
6330
6331 \
6332 tcg_gen_movi_i32(cpu_crf[0], 0); \
6333}
6334
6335GEN_TM_NOOP(tend);
6336GEN_TM_NOOP(tabort);
6337GEN_TM_NOOP(tabortwc);
6338GEN_TM_NOOP(tabortwci);
6339GEN_TM_NOOP(tabortdc);
6340GEN_TM_NOOP(tabortdci);
6341GEN_TM_NOOP(tsr);
6342
6343static inline void gen_cp_abort(DisasContext *ctx)
6344{
6345
6346}
6347
6348#define GEN_CP_PASTE_NOOP(name) \
6349static inline void gen_##name(DisasContext *ctx) \
6350{ \
6351
6352
6353
6354 \
6355 gen_invalid(ctx); \
6356}
6357
6358GEN_CP_PASTE_NOOP(copy)
6359GEN_CP_PASTE_NOOP(paste)
6360
6361static void gen_tcheck(DisasContext *ctx)
6362{
6363 if (unlikely(!ctx->tm_enabled)) {
6364 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
6365 return;
6366 }
6367
6368
6369
6370
6371
6372
6373
6374 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8);
6375}
6376
6377#if defined(CONFIG_USER_ONLY)
6378#define GEN_TM_PRIV_NOOP(name) \
6379static inline void gen_##name(DisasContext *ctx) \
6380{ \
6381 gen_priv_opc(ctx); \
6382}
6383
6384#else
6385
6386#define GEN_TM_PRIV_NOOP(name) \
6387static inline void gen_##name(DisasContext *ctx) \
6388{ \
6389 CHK_SV(ctx); \
6390 if (unlikely(!ctx->tm_enabled)) { \
6391 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
6392 return; \
6393 } \
6394
6395
6396
6397
6398
6399
6400 \
6401 tcg_gen_movi_i32(cpu_crf[0], 0); \
6402}
6403
6404#endif
6405
6406GEN_TM_PRIV_NOOP(treclaim);
6407GEN_TM_PRIV_NOOP(trechkpt);
6408
6409static inline void get_fpr(TCGv_i64 dst, int regno)
6410{
6411 tcg_gen_ld_i64(dst, cpu_env, fpr_offset(regno));
6412}
6413
6414static inline void set_fpr(int regno, TCGv_i64 src)
6415{
6416 tcg_gen_st_i64(src, cpu_env, fpr_offset(regno));
6417
6418
6419
6420
6421
6422
6423
6424 tcg_gen_st_i64(tcg_constant_i64(0), cpu_env, vsr64_offset(regno, false));
6425}
6426
6427static inline void get_avr64(TCGv_i64 dst, int regno, bool high)
6428{
6429 tcg_gen_ld_i64(dst, cpu_env, avr64_offset(regno, high));
6430}
6431
6432static inline void set_avr64(int regno, TCGv_i64 src, bool high)
6433{
6434 tcg_gen_st_i64(src, cpu_env, avr64_offset(regno, high));
6435}
6436
6437
6438
6439
6440static int times_2(DisasContext *ctx, int x)
6441{
6442 return x * 2;
6443}
6444
6445static int times_4(DisasContext *ctx, int x)
6446{
6447 return x * 4;
6448}
6449
6450static int times_16(DisasContext *ctx, int x)
6451{
6452 return x * 16;
6453}
6454
6455static int64_t dw_compose_ea(DisasContext *ctx, int x)
6456{
6457 return deposit64(0xfffffffffffffe00, 3, 6, x);
6458}
6459
6460
6461
6462
6463
6464
6465#define REQUIRE_INSNS_FLAGS(CTX, NAME) \
6466 do { \
6467 if (((CTX)->insns_flags & PPC_##NAME) == 0) { \
6468 return false; \
6469 } \
6470 } while (0)
6471
6472#define REQUIRE_INSNS_FLAGS2(CTX, NAME) \
6473 do { \
6474 if (((CTX)->insns_flags2 & PPC2_##NAME) == 0) { \
6475 return false; \
6476 } \
6477 } while (0)
6478
6479
6480#if TARGET_LONG_BITS == 32
6481# define REQUIRE_64BIT(CTX) return false
6482#else
6483# define REQUIRE_64BIT(CTX) REQUIRE_INSNS_FLAGS(CTX, 64B)
6484#endif
6485
6486#define REQUIRE_VECTOR(CTX) \
6487 do { \
6488 if (unlikely(!(CTX)->altivec_enabled)) { \
6489 gen_exception((CTX), POWERPC_EXCP_VPU); \
6490 return true; \
6491 } \
6492 } while (0)
6493
6494#define REQUIRE_VSX(CTX) \
6495 do { \
6496 if (unlikely(!(CTX)->vsx_enabled)) { \
6497 gen_exception((CTX), POWERPC_EXCP_VSXU); \
6498 return true; \
6499 } \
6500 } while (0)
6501
6502#define REQUIRE_FPU(ctx) \
6503 do { \
6504 if (unlikely(!(ctx)->fpu_enabled)) { \
6505 gen_exception((ctx), POWERPC_EXCP_FPU); \
6506 return true; \
6507 } \
6508 } while (0)
6509
6510#if !defined(CONFIG_USER_ONLY)
6511#define REQUIRE_SV(CTX) \
6512 do { \
6513 if (unlikely((CTX)->pr)) { \
6514 gen_priv_opc(CTX); \
6515 return true; \
6516 } \
6517 } while (0)
6518
6519#define REQUIRE_HV(CTX) \
6520 do { \
6521 if (unlikely((CTX)->pr || !(CTX)->hv)) { \
6522 gen_priv_opc(CTX); \
6523 return true; \
6524 } \
6525 } while (0)
6526#else
6527#define REQUIRE_SV(CTX) do { gen_priv_opc(CTX); return true; } while (0)
6528#define REQUIRE_HV(CTX) do { gen_priv_opc(CTX); return true; } while (0)
6529#endif
6530
6531
6532
6533
6534
6535#define TRANS(NAME, FUNC, ...) \
6536 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6537 { return FUNC(ctx, a, __VA_ARGS__); }
6538#define TRANS_FLAGS(FLAGS, NAME, FUNC, ...) \
6539 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6540 { \
6541 REQUIRE_INSNS_FLAGS(ctx, FLAGS); \
6542 return FUNC(ctx, a, __VA_ARGS__); \
6543 }
6544#define TRANS_FLAGS2(FLAGS2, NAME, FUNC, ...) \
6545 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6546 { \
6547 REQUIRE_INSNS_FLAGS2(ctx, FLAGS2); \
6548 return FUNC(ctx, a, __VA_ARGS__); \
6549 }
6550
6551#define TRANS64(NAME, FUNC, ...) \
6552 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6553 { REQUIRE_64BIT(ctx); return FUNC(ctx, a, __VA_ARGS__); }
6554#define TRANS64_FLAGS2(FLAGS2, NAME, FUNC, ...) \
6555 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6556 { \
6557 REQUIRE_64BIT(ctx); \
6558 REQUIRE_INSNS_FLAGS2(ctx, FLAGS2); \
6559 return FUNC(ctx, a, __VA_ARGS__); \
6560 }
6561
6562
6563
6564
6565#include "decode-insn32.c.inc"
6566#include "decode-insn64.c.inc"
6567#include "power8-pmu-regs.c.inc"
6568
6569
6570
6571
6572
6573static bool resolve_PLS_D(DisasContext *ctx, arg_D *d, arg_PLS_D *a)
6574{
6575 d->rt = a->rt;
6576 d->ra = a->ra;
6577 d->si = a->si;
6578 if (a->r) {
6579 if (unlikely(a->ra != 0)) {
6580 gen_invalid(ctx);
6581 return false;
6582 }
6583 d->si += ctx->cia;
6584 }
6585 return true;
6586}
6587
6588#include "translate/fixedpoint-impl.c.inc"
6589
6590#include "translate/fp-impl.c.inc"
6591
6592#include "translate/vmx-impl.c.inc"
6593
6594#include "translate/vsx-impl.c.inc"
6595
6596#include "translate/dfp-impl.c.inc"
6597
6598#include "translate/spe-impl.c.inc"
6599
6600#include "translate/branch-impl.c.inc"
6601
6602#include "translate/processor-ctrl-impl.c.inc"
6603
6604#include "translate/storage-ctrl-impl.c.inc"
6605
6606
6607static void gen_dform39(DisasContext *ctx)
6608{
6609 if ((ctx->opcode & 0x3) == 0) {
6610 if (ctx->insns_flags2 & PPC2_ISA205) {
6611 return gen_lfdp(ctx);
6612 }
6613 }
6614 return gen_invalid(ctx);
6615}
6616
6617
6618static void gen_dform3D(DisasContext *ctx)
6619{
6620 if ((ctx->opcode & 3) == 0) {
6621
6622 if (ctx->insns_flags2 & PPC2_ISA205) {
6623 return gen_stfdp(ctx);
6624 }
6625 }
6626 return gen_invalid(ctx);
6627}
6628
6629#if defined(TARGET_PPC64)
6630
6631static void gen_brd(DisasContext *ctx)
6632{
6633 tcg_gen_bswap64_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
6634}
6635
6636
6637static void gen_brw(DisasContext *ctx)
6638{
6639 tcg_gen_bswap64_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
6640 tcg_gen_rotli_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 32);
6641
6642}
6643
6644
6645static void gen_brh(DisasContext *ctx)
6646{
6647 TCGv_i64 mask = tcg_constant_i64(0x00ff00ff00ff00ffull);
6648 TCGv_i64 t1 = tcg_temp_new_i64();
6649 TCGv_i64 t2 = tcg_temp_new_i64();
6650
6651 tcg_gen_shri_i64(t1, cpu_gpr[rS(ctx->opcode)], 8);
6652 tcg_gen_and_i64(t2, t1, mask);
6653 tcg_gen_and_i64(t1, cpu_gpr[rS(ctx->opcode)], mask);
6654 tcg_gen_shli_i64(t1, t1, 8);
6655 tcg_gen_or_i64(cpu_gpr[rA(ctx->opcode)], t1, t2);
6656
6657 tcg_temp_free_i64(t1);
6658 tcg_temp_free_i64(t2);
6659}
6660#endif
6661
6662static opcode_t opcodes[] = {
6663#if defined(TARGET_PPC64)
6664GEN_HANDLER_E(brd, 0x1F, 0x1B, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA310),
6665GEN_HANDLER_E(brw, 0x1F, 0x1B, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA310),
6666GEN_HANDLER_E(brh, 0x1F, 0x1B, 0x06, 0x0000F801, PPC_NONE, PPC2_ISA310),
6667#endif
6668GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
6669#if defined(TARGET_PPC64)
6670GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
6671#endif
6672GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
6673GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300),
6674GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
6675GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6676GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6677GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
6678GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
6679GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
6680GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
6681GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6682#if defined(TARGET_PPC64)
6683GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
6684#endif
6685GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
6686GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
6687GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6688GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6689GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6690GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
6691GEN_HANDLER_E(cnttzw, 0x1F, 0x1A, 0x10, 0x00000000, PPC_NONE, PPC2_ISA300),
6692GEN_HANDLER_E(copy, 0x1F, 0x06, 0x18, 0x03C00001, PPC_NONE, PPC2_ISA300),
6693GEN_HANDLER_E(cp_abort, 0x1F, 0x06, 0x1A, 0x03FFF801, PPC_NONE, PPC2_ISA300),
6694GEN_HANDLER_E(paste, 0x1F, 0x06, 0x1C, 0x03C00000, PPC_NONE, PPC2_ISA300),
6695GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
6696GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
6697GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6698GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6699GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6700GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6701GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB),
6702GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
6703GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
6704#if defined(TARGET_PPC64)
6705GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
6706GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
6707GEN_HANDLER_E(cnttzd, 0x1F, 0x1A, 0x11, 0x00000000, PPC_NONE, PPC2_ISA300),
6708GEN_HANDLER_E(darn, 0x1F, 0x13, 0x17, 0x001CF801, PPC_NONE, PPC2_ISA300),
6709GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
6710GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206),
6711#endif
6712GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6713GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6714GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6715GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
6716GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
6717GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
6718GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
6719#if defined(TARGET_PPC64)
6720GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
6721GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
6722GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
6723GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
6724GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
6725GEN_HANDLER2_E(extswsli0, "extswsli", 0x1F, 0x1A, 0x1B, 0x00000000,
6726 PPC_NONE, PPC2_ISA300),
6727GEN_HANDLER2_E(extswsli1, "extswsli", 0x1F, 0x1B, 0x1B, 0x00000000,
6728 PPC_NONE, PPC2_ISA300),
6729#endif
6730
6731GEN_HANDLER_E(dform39, 0x39, 0xFF, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA205),
6732
6733GEN_HANDLER_E(dform3D, 0x3D, 0xFF, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA205),
6734GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6735GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6736GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
6737GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
6738GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
6739GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
6740GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x01FFF801, PPC_MEM_EIEIO),
6741GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
6742GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6743GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6744GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
6745GEN_HANDLER_E(lwat, 0x1F, 0x06, 0x12, 0x00000001, PPC_NONE, PPC2_ISA300),
6746GEN_HANDLER_E(stwat, 0x1F, 0x06, 0x16, 0x00000001, PPC_NONE, PPC2_ISA300),
6747GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6748GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6749GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
6750#if defined(TARGET_PPC64)
6751GEN_HANDLER_E(ldat, 0x1F, 0x06, 0x13, 0x00000001, PPC_NONE, PPC2_ISA300),
6752GEN_HANDLER_E(stdat, 0x1F, 0x06, 0x17, 0x00000001, PPC_NONE, PPC2_ISA300),
6753GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
6754GEN_HANDLER_E(lqarx, 0x1F, 0x14, 0x08, 0, PPC_NONE, PPC2_LSQ_ISA207),
6755GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
6756GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
6757#endif
6758GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
6759
6760GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x039FF801, PPC_WAIT),
6761GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039CF801, PPC_NONE, PPC2_ISA300),
6762GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
6763GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
6764GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
6765GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
6766GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0x0000E000, PPC_NONE, PPC2_BCTAR_ISA207),
6767GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
6768GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
6769#if defined(TARGET_PPC64)
6770GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
6771#if !defined(CONFIG_USER_ONLY)
6772
6773GEN_HANDLER_E(scv, 0x11, 0x10, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
6774GEN_HANDLER_E(scv, 0x11, 0x00, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
6775GEN_HANDLER_E(rfscv, 0x13, 0x12, 0x02, 0x03FF8001, PPC_NONE, PPC2_ISA300),
6776#endif
6777GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300),
6778GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6779GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6780GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6781GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6782GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
6783#endif
6784
6785GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW),
6786GEN_HANDLER(sc, 0x11, 0x01, 0xFF, 0x03FFF01D, PPC_FLOW),
6787GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
6788GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
6789#if defined(TARGET_PPC64)
6790GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
6791GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
6792#endif
6793GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
6794GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
6795GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
6796GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
6797GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
6798GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
6799#if defined(TARGET_PPC64)
6800GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
6801GEN_HANDLER_E(setb, 0x1F, 0x00, 0x04, 0x0003F801, PPC_NONE, PPC2_ISA300),
6802GEN_HANDLER_E(mcrxrx, 0x1F, 0x00, 0x12, 0x007FF801, PPC_NONE, PPC2_ISA300),
6803#endif
6804GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC),
6805GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
6806GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
6807GEN_HANDLER_E(dcbfep, 0x1F, 0x1F, 0x03, 0x03C00001, PPC_NONE, PPC2_BOOKE206),
6808GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
6809GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
6810GEN_HANDLER_E(dcbstep, 0x1F, 0x1F, 0x01, 0x03E00001, PPC_NONE, PPC2_BOOKE206),
6811GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
6812GEN_HANDLER_E(dcbtep, 0x1F, 0x1F, 0x09, 0x00000001, PPC_NONE, PPC2_BOOKE206),
6813GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
6814GEN_HANDLER_E(dcbtstep, 0x1F, 0x1F, 0x07, 0x00000001, PPC_NONE, PPC2_BOOKE206),
6815GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
6816GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
6817GEN_HANDLER_E(dcbzep, 0x1F, 0x1F, 0x1F, 0x03C00001, PPC_NONE, PPC2_BOOKE206),
6818GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
6819GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x01800001, PPC_ALTIVEC),
6820GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
6821GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
6822GEN_HANDLER_E(icbiep, 0x1F, 0x1F, 0x1E, 0x03E00001, PPC_NONE, PPC2_BOOKE206),
6823GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
6824GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
6825GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
6826GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
6827GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
6828#if defined(TARGET_PPC64)
6829GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
6830GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
6831 PPC_SEGMENT_64B),
6832GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
6833GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
6834 PPC_SEGMENT_64B),
6835#endif
6836GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
6837
6838
6839
6840
6841GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
6842GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
6843GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
6844GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
6845GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
6846GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
6847GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
6848GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
6849GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
6850GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
6851GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
6852GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
6853GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
6854GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
6855GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
6856GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
6857GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
6858GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
6859GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
6860GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
6861GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
6862GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
6863GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
6864GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
6865GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
6866GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
6867GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
6868 PPC_NONE, PPC2_BOOKE206),
6869GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
6870 PPC_NONE, PPC2_BOOKE206),
6871GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
6872 PPC_NONE, PPC2_BOOKE206),
6873GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
6874 PPC_NONE, PPC2_BOOKE206),
6875GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
6876 PPC_NONE, PPC2_BOOKE206),
6877GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
6878GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
6879GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
6880GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
6881 PPC_BOOKE, PPC2_BOOKE206),
6882GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x039FF801, PPC_BOOKE),
6883GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
6884 PPC_BOOKE, PPC2_BOOKE206),
6885GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x06, 0x08, 0x03E00001,
6886 PPC_440_SPEC),
6887GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
6888GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
6889GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
6890GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
6891#if defined(TARGET_PPC64)
6892GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE,
6893 PPC2_ISA300),
6894GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
6895#endif
6896
6897#undef GEN_INT_ARITH_ADD
6898#undef GEN_INT_ARITH_ADD_CONST
6899#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
6900GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
6901#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
6902 add_ca, compute_ca, compute_ov) \
6903GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
6904GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
6905GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
6906GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
6907GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
6908GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
6909GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
6910GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
6911GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
6912GEN_HANDLER_E(addex, 0x1F, 0x0A, 0x05, 0x00000000, PPC_NONE, PPC2_ISA300),
6913GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
6914GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
6915
6916#undef GEN_INT_ARITH_DIVW
6917#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
6918GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
6919GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
6920GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
6921GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
6922GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
6923GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6924GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6925GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6926GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6927GEN_HANDLER_E(modsw, 0x1F, 0x0B, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
6928GEN_HANDLER_E(moduw, 0x1F, 0x0B, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
6929
6930#if defined(TARGET_PPC64)
6931#undef GEN_INT_ARITH_DIVD
6932#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
6933GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
6934GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
6935GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
6936GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
6937GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
6938
6939GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6940GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6941GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6942GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6943GEN_HANDLER_E(modsd, 0x1F, 0x09, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
6944GEN_HANDLER_E(modud, 0x1F, 0x09, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
6945
6946#undef GEN_INT_ARITH_MUL_HELPER
6947#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
6948GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
6949GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
6950GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
6951GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
6952#endif
6953
6954#undef GEN_INT_ARITH_SUBF
6955#undef GEN_INT_ARITH_SUBF_CONST
6956#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
6957GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
6958#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
6959 add_ca, compute_ca, compute_ov) \
6960GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
6961GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
6962GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
6963GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
6964GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
6965GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
6966GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
6967GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
6968GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
6969GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
6970GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
6971
6972#undef GEN_LOGICAL1
6973#undef GEN_LOGICAL2
6974#define GEN_LOGICAL2(name, tcg_op, opc, type) \
6975GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
6976#define GEN_LOGICAL1(name, tcg_op, opc, type) \
6977GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
6978GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
6979GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
6980GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
6981GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
6982GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
6983GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
6984GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
6985GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
6986#if defined(TARGET_PPC64)
6987GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
6988#endif
6989
6990#if defined(TARGET_PPC64)
6991#undef GEN_PPC64_R2
6992#undef GEN_PPC64_R4
6993#define GEN_PPC64_R2(name, opc1, opc2) \
6994GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
6995GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
6996 PPC_64B)
6997#define GEN_PPC64_R4(name, opc1, opc2) \
6998GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
6999GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
7000 PPC_64B), \
7001GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
7002 PPC_64B), \
7003GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
7004 PPC_64B)
7005GEN_PPC64_R4(rldicl, 0x1E, 0x00),
7006GEN_PPC64_R4(rldicr, 0x1E, 0x02),
7007GEN_PPC64_R4(rldic, 0x1E, 0x04),
7008GEN_PPC64_R2(rldcl, 0x1E, 0x08),
7009GEN_PPC64_R2(rldcr, 0x1E, 0x09),
7010GEN_PPC64_R4(rldimi, 0x1E, 0x06),
7011#endif
7012
7013#undef GEN_LDX_E
7014#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \
7015GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
7016
7017#if defined(TARGET_PPC64)
7018GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE)
7019
7020
7021GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
7022GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x18, PPC_CILDST)
7023GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
7024GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
7025#endif
7026GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
7027GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
7028
7029
7030#undef GEN_LDEPX
7031#define GEN_LDEPX(name, ldop, opc2, opc3) \
7032GEN_HANDLER_E(name##epx, 0x1F, opc2, opc3, \
7033 0x00000001, PPC_NONE, PPC2_BOOKE206),
7034
7035GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
7036GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
7037GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
7038#if defined(TARGET_PPC64)
7039GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00)
7040#endif
7041
7042#undef GEN_STX_E
7043#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk) \
7044GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000000, type, type2),
7045
7046#if defined(TARGET_PPC64)
7047GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE)
7048GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
7049GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
7050GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
7051GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
7052#endif
7053GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
7054GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
7055
7056#undef GEN_STEPX
7057#define GEN_STEPX(name, ldop, opc2, opc3) \
7058GEN_HANDLER_E(name##epx, 0x1F, opc2, opc3, \
7059 0x00000001, PPC_NONE, PPC2_BOOKE206),
7060
7061GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
7062GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
7063GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
7064#if defined(TARGET_PPC64)
7065GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1D, 0x04)
7066#endif
7067
7068#undef GEN_CRLOGIC
7069#define GEN_CRLOGIC(name, tcg_op, opc) \
7070GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
7071GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
7072GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
7073GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
7074GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
7075GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
7076GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
7077GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
7078GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
7079
7080#undef GEN_MAC_HANDLER
7081#define GEN_MAC_HANDLER(name, opc2, opc3) \
7082GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
7083GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
7084GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
7085GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
7086GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
7087GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
7088GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
7089GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
7090GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
7091GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
7092GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
7093GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
7094GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
7095GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
7096GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
7097GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
7098GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
7099GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
7100GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
7101GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
7102GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
7103GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
7104GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
7105GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
7106GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
7107GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
7108GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
7109GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
7110GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
7111GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
7112GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
7113GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
7114GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
7115GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
7116GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
7117GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
7118GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
7119GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
7120GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
7121GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
7122GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
7123GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
7124GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
7125
7126GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \
7127 PPC_NONE, PPC2_TM),
7128GEN_HANDLER2_E(tend, "tend", 0x1F, 0x0E, 0x15, 0x01FFF800, \
7129 PPC_NONE, PPC2_TM),
7130GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \
7131 PPC_NONE, PPC2_TM),
7132GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \
7133 PPC_NONE, PPC2_TM),
7134GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \
7135 PPC_NONE, PPC2_TM),
7136GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \
7137 PPC_NONE, PPC2_TM),
7138GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \
7139 PPC_NONE, PPC2_TM),
7140GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \
7141 PPC_NONE, PPC2_TM),
7142GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \
7143 PPC_NONE, PPC2_TM),
7144GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \
7145 PPC_NONE, PPC2_TM),
7146GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
7147 PPC_NONE, PPC2_TM),
7148
7149#include "translate/fp-ops.c.inc"
7150
7151#include "translate/vmx-ops.c.inc"
7152
7153#include "translate/vsx-ops.c.inc"
7154
7155#include "translate/spe-ops.c.inc"
7156};
7157
7158
7159
7160enum {
7161 PPC_DIRECT = 0,
7162 PPC_INDIRECT = 1,
7163};
7164
7165#define PPC_OPCODE_MASK 0x3
7166
7167static inline int is_indirect_opcode(void *handler)
7168{
7169 return ((uintptr_t)handler & PPC_OPCODE_MASK) == PPC_INDIRECT;
7170}
7171
7172static inline opc_handler_t **ind_table(void *handler)
7173{
7174 return (opc_handler_t **)((uintptr_t)handler & ~PPC_OPCODE_MASK);
7175}
7176
7177
7178
7179static void fill_new_table(opc_handler_t **table, int len)
7180{
7181 int i;
7182
7183 for (i = 0; i < len; i++) {
7184 table[i] = &invalid_handler;
7185 }
7186}
7187
7188static int create_new_table(opc_handler_t **table, unsigned char idx)
7189{
7190 opc_handler_t **tmp;
7191
7192 tmp = g_new(opc_handler_t *, PPC_CPU_INDIRECT_OPCODES_LEN);
7193 fill_new_table(tmp, PPC_CPU_INDIRECT_OPCODES_LEN);
7194 table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
7195
7196 return 0;
7197}
7198
7199static int insert_in_table(opc_handler_t **table, unsigned char idx,
7200 opc_handler_t *handler)
7201{
7202 if (table[idx] != &invalid_handler) {
7203 return -1;
7204 }
7205 table[idx] = handler;
7206
7207 return 0;
7208}
7209
7210static int register_direct_insn(opc_handler_t **ppc_opcodes,
7211 unsigned char idx, opc_handler_t *handler)
7212{
7213 if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
7214 printf("*** ERROR: opcode %02x already assigned in main "
7215 "opcode table\n", idx);
7216 return -1;
7217 }
7218
7219 return 0;
7220}
7221
7222static int register_ind_in_table(opc_handler_t **table,
7223 unsigned char idx1, unsigned char idx2,
7224 opc_handler_t *handler)
7225{
7226 if (table[idx1] == &invalid_handler) {
7227 if (create_new_table(table, idx1) < 0) {
7228 printf("*** ERROR: unable to create indirect table "
7229 "idx=%02x\n", idx1);
7230 return -1;
7231 }
7232 } else {
7233 if (!is_indirect_opcode(table[idx1])) {
7234 printf("*** ERROR: idx %02x already assigned to a direct "
7235 "opcode\n", idx1);
7236 return -1;
7237 }
7238 }
7239 if (handler != NULL &&
7240 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
7241 printf("*** ERROR: opcode %02x already assigned in "
7242 "opcode table %02x\n", idx2, idx1);
7243 return -1;
7244 }
7245
7246 return 0;
7247}
7248
7249static int register_ind_insn(opc_handler_t **ppc_opcodes,
7250 unsigned char idx1, unsigned char idx2,
7251 opc_handler_t *handler)
7252{
7253 return register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
7254}
7255
7256static int register_dblind_insn(opc_handler_t **ppc_opcodes,
7257 unsigned char idx1, unsigned char idx2,
7258 unsigned char idx3, opc_handler_t *handler)
7259{
7260 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
7261 printf("*** ERROR: unable to join indirect table idx "
7262 "[%02x-%02x]\n", idx1, idx2);
7263 return -1;
7264 }
7265 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
7266 handler) < 0) {
7267 printf("*** ERROR: unable to insert opcode "
7268 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
7269 return -1;
7270 }
7271
7272 return 0;
7273}
7274
7275static int register_trplind_insn(opc_handler_t **ppc_opcodes,
7276 unsigned char idx1, unsigned char idx2,
7277 unsigned char idx3, unsigned char idx4,
7278 opc_handler_t *handler)
7279{
7280 opc_handler_t **table;
7281
7282 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
7283 printf("*** ERROR: unable to join indirect table idx "
7284 "[%02x-%02x]\n", idx1, idx2);
7285 return -1;
7286 }
7287 table = ind_table(ppc_opcodes[idx1]);
7288 if (register_ind_in_table(table, idx2, idx3, NULL) < 0) {
7289 printf("*** ERROR: unable to join 2nd-level indirect table idx "
7290 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
7291 return -1;
7292 }
7293 table = ind_table(table[idx2]);
7294 if (register_ind_in_table(table, idx3, idx4, handler) < 0) {
7295 printf("*** ERROR: unable to insert opcode "
7296 "[%02x-%02x-%02x-%02x]\n", idx1, idx2, idx3, idx4);
7297 return -1;
7298 }
7299 return 0;
7300}
7301static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn)
7302{
7303 if (insn->opc2 != 0xFF) {
7304 if (insn->opc3 != 0xFF) {
7305 if (insn->opc4 != 0xFF) {
7306 if (register_trplind_insn(ppc_opcodes, insn->opc1, insn->opc2,
7307 insn->opc3, insn->opc4,
7308 &insn->handler) < 0) {
7309 return -1;
7310 }
7311 } else {
7312 if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
7313 insn->opc3, &insn->handler) < 0) {
7314 return -1;
7315 }
7316 }
7317 } else {
7318 if (register_ind_insn(ppc_opcodes, insn->opc1,
7319 insn->opc2, &insn->handler) < 0) {
7320 return -1;
7321 }
7322 }
7323 } else {
7324 if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
7325 return -1;
7326 }
7327 }
7328
7329 return 0;
7330}
7331
7332static int test_opcode_table(opc_handler_t **table, int len)
7333{
7334 int i, count, tmp;
7335
7336 for (i = 0, count = 0; i < len; i++) {
7337
7338 if (table[i] == NULL) {
7339 table[i] = &invalid_handler;
7340 }
7341 if (table[i] != &invalid_handler) {
7342 if (is_indirect_opcode(table[i])) {
7343 tmp = test_opcode_table(ind_table(table[i]),
7344 PPC_CPU_INDIRECT_OPCODES_LEN);
7345 if (tmp == 0) {
7346 free(table[i]);
7347 table[i] = &invalid_handler;
7348 } else {
7349 count++;
7350 }
7351 } else {
7352 count++;
7353 }
7354 }
7355 }
7356
7357 return count;
7358}
7359
7360static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
7361{
7362 if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
7363 printf("*** WARNING: no opcode defined !\n");
7364 }
7365}
7366
7367
7368void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
7369{
7370 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
7371 opcode_t *opc;
7372
7373 fill_new_table(cpu->opcodes, PPC_CPU_OPCODES_LEN);
7374 for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
7375 if (((opc->handler.type & pcc->insns_flags) != 0) ||
7376 ((opc->handler.type2 & pcc->insns_flags2) != 0)) {
7377 if (register_insn(cpu->opcodes, opc) < 0) {
7378 error_setg(errp, "ERROR initializing PowerPC instruction "
7379 "0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
7380 opc->opc3);
7381 return;
7382 }
7383 }
7384 }
7385 fix_opcode_tables(cpu->opcodes);
7386 fflush(stdout);
7387 fflush(stderr);
7388}
7389
7390void destroy_ppc_opcodes(PowerPCCPU *cpu)
7391{
7392 opc_handler_t **table, **table_2;
7393 int i, j, k;
7394
7395 for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
7396 if (cpu->opcodes[i] == &invalid_handler) {
7397 continue;
7398 }
7399 if (is_indirect_opcode(cpu->opcodes[i])) {
7400 table = ind_table(cpu->opcodes[i]);
7401 for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
7402 if (table[j] == &invalid_handler) {
7403 continue;
7404 }
7405 if (is_indirect_opcode(table[j])) {
7406 table_2 = ind_table(table[j]);
7407 for (k = 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) {
7408 if (table_2[k] != &invalid_handler &&
7409 is_indirect_opcode(table_2[k])) {
7410 g_free((opc_handler_t *)((uintptr_t)table_2[k] &
7411 ~PPC_INDIRECT));
7412 }
7413 }
7414 g_free((opc_handler_t *)((uintptr_t)table[j] &
7415 ~PPC_INDIRECT));
7416 }
7417 }
7418 g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] &
7419 ~PPC_INDIRECT));
7420 }
7421 }
7422}
7423
7424int ppc_fixup_cpu(PowerPCCPU *cpu)
7425{
7426 CPUPPCState *env = &cpu->env;
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437 if ((env->insns_flags & ~PPC_TCG_INSNS)
7438 || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
7439 warn_report("Disabling some instructions which are not "
7440 "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")",
7441 env->insns_flags & ~PPC_TCG_INSNS,
7442 env->insns_flags2 & ~PPC_TCG_INSNS2);
7443 }
7444 env->insns_flags &= PPC_TCG_INSNS;
7445 env->insns_flags2 &= PPC_TCG_INSNS2;
7446 return 0;
7447}
7448
7449static bool decode_legacy(PowerPCCPU *cpu, DisasContext *ctx, uint32_t insn)
7450{
7451 opc_handler_t **table, *handler;
7452 uint32_t inval;
7453
7454 ctx->opcode = insn;
7455
7456 LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
7457 insn, opc1(insn), opc2(insn), opc3(insn), opc4(insn),
7458 ctx->le_mode ? "little" : "big");
7459
7460 table = cpu->opcodes;
7461 handler = table[opc1(insn)];
7462 if (is_indirect_opcode(handler)) {
7463 table = ind_table(handler);
7464 handler = table[opc2(insn)];
7465 if (is_indirect_opcode(handler)) {
7466 table = ind_table(handler);
7467 handler = table[opc3(insn)];
7468 if (is_indirect_opcode(handler)) {
7469 table = ind_table(handler);
7470 handler = table[opc4(insn)];
7471 }
7472 }
7473 }
7474
7475
7476 if (unlikely(handler->handler == &gen_invalid)) {
7477 qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
7478 "%02x - %02x - %02x - %02x (%08x) "
7479 TARGET_FMT_lx "\n",
7480 opc1(insn), opc2(insn), opc3(insn), opc4(insn),
7481 insn, ctx->cia);
7482 return false;
7483 }
7484
7485 if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE)
7486 && Rc(insn))) {
7487 inval = handler->inval2;
7488 } else {
7489 inval = handler->inval1;
7490 }
7491
7492 if (unlikely((insn & inval) != 0)) {
7493 qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
7494 "%02x - %02x - %02x - %02x (%08x) "
7495 TARGET_FMT_lx "\n", insn & inval,
7496 opc1(insn), opc2(insn), opc3(insn), opc4(insn),
7497 insn, ctx->cia);
7498 return false;
7499 }
7500
7501 handler->handler(ctx);
7502 return true;
7503}
7504
7505static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
7506{
7507 DisasContext *ctx = container_of(dcbase, DisasContext, base);
7508 CPUPPCState *env = cs->env_ptr;
7509 uint32_t hflags = ctx->base.tb->flags;
7510
7511 ctx->spr_cb = env->spr_cb;
7512 ctx->pr = (hflags >> HFLAGS_PR) & 1;
7513 ctx->mem_idx = (hflags >> HFLAGS_DMMU_IDX) & 7;
7514 ctx->dr = (hflags >> HFLAGS_DR) & 1;
7515 ctx->hv = (hflags >> HFLAGS_HV) & 1;
7516 ctx->insns_flags = env->insns_flags;
7517 ctx->insns_flags2 = env->insns_flags2;
7518 ctx->access_type = -1;
7519 ctx->need_access_type = !mmu_is_64bit(env->mmu_model);
7520 ctx->le_mode = (hflags >> HFLAGS_LE) & 1;
7521 ctx->default_tcg_memop_mask = ctx->le_mode ? MO_LE : MO_BE;
7522 ctx->flags = env->flags;
7523#if defined(TARGET_PPC64)
7524 ctx->sf_mode = (hflags >> HFLAGS_64) & 1;
7525 ctx->has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
7526#endif
7527 ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B
7528 || env->mmu_model & POWERPC_MMU_64;
7529
7530 ctx->fpu_enabled = (hflags >> HFLAGS_FP) & 1;
7531 ctx->spe_enabled = (hflags >> HFLAGS_SPE) & 1;
7532 ctx->altivec_enabled = (hflags >> HFLAGS_VR) & 1;
7533 ctx->vsx_enabled = (hflags >> HFLAGS_VSX) & 1;
7534 ctx->tm_enabled = (hflags >> HFLAGS_TM) & 1;
7535 ctx->gtse = (hflags >> HFLAGS_GTSE) & 1;
7536 ctx->hr = (hflags >> HFLAGS_HR) & 1;
7537 ctx->mmcr0_pmcc0 = (hflags >> HFLAGS_PMCC0) & 1;
7538 ctx->mmcr0_pmcc1 = (hflags >> HFLAGS_PMCC1) & 1;
7539 ctx->mmcr0_pmcjce = (hflags >> HFLAGS_PMCJCE) & 1;
7540 ctx->pmc_other = (hflags >> HFLAGS_PMC_OTHER) & 1;
7541 ctx->pmu_insn_cnt = (hflags >> HFLAGS_INSN_CNT) & 1;
7542
7543 ctx->singlestep_enabled = 0;
7544 if ((hflags >> HFLAGS_SE) & 1) {
7545 ctx->singlestep_enabled |= CPU_SINGLE_STEP;
7546 ctx->base.max_insns = 1;
7547 }
7548 if ((hflags >> HFLAGS_BE) & 1) {
7549 ctx->singlestep_enabled |= CPU_BRANCH_STEP;
7550 }
7551}
7552
7553static void ppc_tr_tb_start(DisasContextBase *db, CPUState *cs)
7554{
7555}
7556
7557static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
7558{
7559 tcg_gen_insn_start(dcbase->pc_next);
7560}
7561
7562static bool is_prefix_insn(DisasContext *ctx, uint32_t insn)
7563{
7564 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
7565 return opc1(insn) == 1;
7566}
7567
7568static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
7569{
7570 DisasContext *ctx = container_of(dcbase, DisasContext, base);
7571 PowerPCCPU *cpu = POWERPC_CPU(cs);
7572 CPUPPCState *env = cs->env_ptr;
7573 target_ulong pc;
7574 uint32_t insn;
7575 bool ok;
7576
7577 LOG_DISAS("----------------\n");
7578 LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
7579 ctx->base.pc_next, ctx->mem_idx, (int)msr_ir);
7580
7581 ctx->cia = pc = ctx->base.pc_next;
7582 insn = translator_ldl_swap(env, dcbase, pc, need_byteswap(ctx));
7583 ctx->base.pc_next = pc += 4;
7584
7585 if (!is_prefix_insn(ctx, insn)) {
7586 ok = (decode_insn32(ctx, insn) ||
7587 decode_legacy(cpu, ctx, insn));
7588 } else if ((pc & 63) == 0) {
7589
7590
7591
7592
7593
7594 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_INSN);
7595 ok = true;
7596 } else {
7597 uint32_t insn2 = translator_ldl_swap(env, dcbase, pc,
7598 need_byteswap(ctx));
7599 ctx->base.pc_next = pc += 4;
7600 ok = decode_insn64(ctx, deposit64(insn2, 32, 32, insn));
7601 }
7602 if (!ok) {
7603 gen_invalid(ctx);
7604 }
7605
7606
7607 if (ctx->base.is_jmp == DISAS_NEXT && !(pc & ~TARGET_PAGE_MASK)) {
7608 ctx->base.is_jmp = DISAS_TOO_MANY;
7609 }
7610
7611 translator_loop_temp_check(&ctx->base);
7612}
7613
7614static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
7615{
7616 DisasContext *ctx = container_of(dcbase, DisasContext, base);
7617 DisasJumpType is_jmp = ctx->base.is_jmp;
7618 target_ulong nip = ctx->base.pc_next;
7619
7620 if (is_jmp == DISAS_NORETURN) {
7621
7622 return;
7623 }
7624
7625
7626 if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP)
7627 && (nip <= 0x100 || nip > 0xf00)) {
7628 switch (is_jmp) {
7629 case DISAS_TOO_MANY:
7630 case DISAS_EXIT_UPDATE:
7631 case DISAS_CHAIN_UPDATE:
7632 gen_update_nip(ctx, nip);
7633 break;
7634 case DISAS_EXIT:
7635 case DISAS_CHAIN:
7636 break;
7637 default:
7638 g_assert_not_reached();
7639 }
7640
7641 gen_debug_exception(ctx);
7642 return;
7643 }
7644
7645 switch (is_jmp) {
7646 case DISAS_TOO_MANY:
7647 if (use_goto_tb(ctx, nip)) {
7648 pmu_count_insns(ctx);
7649 tcg_gen_goto_tb(0);
7650 gen_update_nip(ctx, nip);
7651 tcg_gen_exit_tb(ctx->base.tb, 0);
7652 break;
7653 }
7654
7655 case DISAS_CHAIN_UPDATE:
7656 gen_update_nip(ctx, nip);
7657
7658 case DISAS_CHAIN:
7659
7660
7661
7662
7663 if (ctx->base.tb->flags & CF_NO_GOTO_PTR) {
7664 pmu_count_insns(ctx);
7665 }
7666
7667 tcg_gen_lookup_and_goto_ptr();
7668 break;
7669
7670 case DISAS_EXIT_UPDATE:
7671 gen_update_nip(ctx, nip);
7672
7673 case DISAS_EXIT:
7674 pmu_count_insns(ctx);
7675 tcg_gen_exit_tb(NULL, 0);
7676 break;
7677
7678 default:
7679 g_assert_not_reached();
7680 }
7681}
7682
7683static void ppc_tr_disas_log(const DisasContextBase *dcbase,
7684 CPUState *cs, FILE *logfile)
7685{
7686 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
7687 target_disas(logfile, cs, dcbase->pc_first, dcbase->tb->size);
7688}
7689
7690static const TranslatorOps ppc_tr_ops = {
7691 .init_disas_context = ppc_tr_init_disas_context,
7692 .tb_start = ppc_tr_tb_start,
7693 .insn_start = ppc_tr_insn_start,
7694 .translate_insn = ppc_tr_translate_insn,
7695 .tb_stop = ppc_tr_tb_stop,
7696 .disas_log = ppc_tr_disas_log,
7697};
7698
7699void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
7700 target_ulong pc, void *host_pc)
7701{
7702 DisasContext ctx;
7703
7704 translator_loop(cs, tb, max_insns, pc, host_pc, &ppc_tr_ops, &ctx.base);
7705}
7706