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