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