xref: /illumos-kvm-cmd/target-ppc/translate.c (revision 68396ea9)
1 /*
2  *  PowerPC emulation for qemu: main translation routines.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 
25 #include "cpu.h"
26 #include "exec-all.h"
27 #include "disas.h"
28 #include "tcg-op.h"
29 #include "qemu-common.h"
30 #include "host-utils.h"
31 
32 #include "helper.h"
33 #define GEN_HELPER 1
34 #include "helper.h"
35 
36 #define CPU_SINGLE_STEP 0x1
37 #define CPU_BRANCH_STEP 0x2
38 #define GDBSTUB_SINGLE_STEP 0x4
39 
40 /* Include definitions for instructions classes and implementations flags */
41 //#define PPC_DEBUG_DISAS
42 //#define DO_PPC_STATISTICS
43 
44 #ifdef PPC_DEBUG_DISAS
45 #  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
46 #else
47 #  define LOG_DISAS(...) do { } while (0)
48 #endif
49 /*****************************************************************************/
50 /* Code translation helpers                                                  */
51 
52 /* global register indexes */
53 static TCGv_ptr cpu_env;
54 static char cpu_reg_names[10*3 + 22*4 /* GPR */
55 #if !defined(TARGET_PPC64)
56     + 10*4 + 22*5 /* SPE GPRh */
57 #endif
58     + 10*4 + 22*5 /* FPR */
59     + 2*(10*6 + 22*7) /* AVRh, AVRl */
60     + 8*5 /* CRF */];
61 static TCGv cpu_gpr[32];
62 #if !defined(TARGET_PPC64)
63 static TCGv cpu_gprh[32];
64 #endif
65 static TCGv_i64 cpu_fpr[32];
66 static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
67 static TCGv_i32 cpu_crf[8];
68 static TCGv cpu_nip;
69 static TCGv cpu_msr;
70 static TCGv cpu_ctr;
71 static TCGv cpu_lr;
72 static TCGv cpu_xer;
73 static TCGv cpu_reserve;
74 static TCGv_i32 cpu_fpscr;
75 static TCGv_i32 cpu_access_type;
76 
77 #include "gen-icount.h"
78 
ppc_translate_init(void)79 void ppc_translate_init(void)
80 {
81     int i;
82     char* p;
83     size_t cpu_reg_names_size;
84     static int done_init = 0;
85 
86     if (done_init)
87         return;
88 
89     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
90 
91     p = cpu_reg_names;
92     cpu_reg_names_size = sizeof(cpu_reg_names);
93 
94     for (i = 0; i < 8; i++) {
95         snprintf(p, cpu_reg_names_size, "crf%d", i);
96         cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
97                                             offsetof(CPUState, crf[i]), p);
98         p += 5;
99         cpu_reg_names_size -= 5;
100     }
101 
102     for (i = 0; i < 32; i++) {
103         snprintf(p, cpu_reg_names_size, "r%d", i);
104         cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
105                                         offsetof(CPUState, gpr[i]), p);
106         p += (i < 10) ? 3 : 4;
107         cpu_reg_names_size -= (i < 10) ? 3 : 4;
108 #if !defined(TARGET_PPC64)
109         snprintf(p, cpu_reg_names_size, "r%dH", i);
110         cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
111                                              offsetof(CPUState, gprh[i]), p);
112         p += (i < 10) ? 4 : 5;
113         cpu_reg_names_size -= (i < 10) ? 4 : 5;
114 #endif
115 
116         snprintf(p, cpu_reg_names_size, "fp%d", i);
117         cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
118                                             offsetof(CPUState, fpr[i]), p);
119         p += (i < 10) ? 4 : 5;
120         cpu_reg_names_size -= (i < 10) ? 4 : 5;
121 
122         snprintf(p, cpu_reg_names_size, "avr%dH", i);
123 #ifdef HOST_WORDS_BIGENDIAN
124         cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
125                                              offsetof(CPUState, avr[i].u64[0]), p);
126 #else
127         cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
128                                              offsetof(CPUState, avr[i].u64[1]), p);
129 #endif
130         p += (i < 10) ? 6 : 7;
131         cpu_reg_names_size -= (i < 10) ? 6 : 7;
132 
133         snprintf(p, cpu_reg_names_size, "avr%dL", i);
134 #ifdef HOST_WORDS_BIGENDIAN
135         cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
136                                              offsetof(CPUState, avr[i].u64[1]), p);
137 #else
138         cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
139                                              offsetof(CPUState, avr[i].u64[0]), p);
140 #endif
141         p += (i < 10) ? 6 : 7;
142         cpu_reg_names_size -= (i < 10) ? 6 : 7;
143     }
144 
145     cpu_nip = tcg_global_mem_new(TCG_AREG0,
146                                  offsetof(CPUState, nip), "nip");
147 
148     cpu_msr = tcg_global_mem_new(TCG_AREG0,
149                                  offsetof(CPUState, msr), "msr");
150 
151     cpu_ctr = tcg_global_mem_new(TCG_AREG0,
152                                  offsetof(CPUState, ctr), "ctr");
153 
154     cpu_lr = tcg_global_mem_new(TCG_AREG0,
155                                 offsetof(CPUState, lr), "lr");
156 
157     cpu_xer = tcg_global_mem_new(TCG_AREG0,
158                                  offsetof(CPUState, xer), "xer");
159 
160     cpu_reserve = tcg_global_mem_new(TCG_AREG0,
161                                      offsetof(CPUState, reserve_addr),
162                                      "reserve_addr");
163 
164     cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
165                                        offsetof(CPUState, fpscr), "fpscr");
166 
167     cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
168                                              offsetof(CPUState, access_type), "access_type");
169 
170     /* register helpers */
171 #define GEN_HELPER 2
172 #include "helper.h"
173 
174     done_init = 1;
175 }
176 
177 /* internal defines */
178 typedef struct DisasContext {
179     struct TranslationBlock *tb;
180     target_ulong nip;
181     uint32_t opcode;
182     uint32_t exception;
183     /* Routine used to access memory */
184     int mem_idx;
185     int access_type;
186     /* Translation flags */
187     int le_mode;
188 #if defined(TARGET_PPC64)
189     int sf_mode;
190 #endif
191     int fpu_enabled;
192     int altivec_enabled;
193     int spe_enabled;
194     ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
195     int singlestep_enabled;
196 } DisasContext;
197 
198 struct opc_handler_t {
199     /* invalid bits */
200     uint32_t inval;
201     /* instruction type */
202     uint64_t type;
203     /* handler */
204     void (*handler)(DisasContext *ctx);
205 #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
206     const char *oname;
207 #endif
208 #if defined(DO_PPC_STATISTICS)
209     uint64_t count;
210 #endif
211 };
212 
gen_reset_fpstatus(void)213 static inline void gen_reset_fpstatus(void)
214 {
215 #ifdef CONFIG_SOFTFLOAT
216     gen_helper_reset_fpstatus();
217 #endif
218 }
219 
gen_compute_fprf(TCGv_i64 arg,int set_fprf,int set_rc)220 static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
221 {
222     TCGv_i32 t0 = tcg_temp_new_i32();
223 
224     if (set_fprf != 0) {
225         /* This case might be optimized later */
226         tcg_gen_movi_i32(t0, 1);
227         gen_helper_compute_fprf(t0, arg, t0);
228         if (unlikely(set_rc)) {
229             tcg_gen_mov_i32(cpu_crf[1], t0);
230         }
231         gen_helper_float_check_status();
232     } else if (unlikely(set_rc)) {
233         /* We always need to compute fpcc */
234         tcg_gen_movi_i32(t0, 0);
235         gen_helper_compute_fprf(t0, arg, t0);
236         tcg_gen_mov_i32(cpu_crf[1], t0);
237     }
238 
239     tcg_temp_free_i32(t0);
240 }
241 
gen_set_access_type(DisasContext * ctx,int access_type)242 static inline void gen_set_access_type(DisasContext *ctx, int access_type)
243 {
244     if (ctx->access_type != access_type) {
245         tcg_gen_movi_i32(cpu_access_type, access_type);
246         ctx->access_type = access_type;
247     }
248 }
249 
gen_update_nip(DisasContext * ctx,target_ulong nip)250 static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
251 {
252 #if defined(TARGET_PPC64)
253     if (ctx->sf_mode)
254         tcg_gen_movi_tl(cpu_nip, nip);
255     else
256 #endif
257         tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
258 }
259 
gen_exception_err(DisasContext * ctx,uint32_t excp,uint32_t error)260 static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
261 {
262     TCGv_i32 t0, t1;
263     if (ctx->exception == POWERPC_EXCP_NONE) {
264         gen_update_nip(ctx, ctx->nip);
265     }
266     t0 = tcg_const_i32(excp);
267     t1 = tcg_const_i32(error);
268     gen_helper_raise_exception_err(t0, t1);
269     tcg_temp_free_i32(t0);
270     tcg_temp_free_i32(t1);
271     ctx->exception = (excp);
272 }
273 
gen_exception(DisasContext * ctx,uint32_t excp)274 static inline void gen_exception(DisasContext *ctx, uint32_t excp)
275 {
276     TCGv_i32 t0;
277     if (ctx->exception == POWERPC_EXCP_NONE) {
278         gen_update_nip(ctx, ctx->nip);
279     }
280     t0 = tcg_const_i32(excp);
281     gen_helper_raise_exception(t0);
282     tcg_temp_free_i32(t0);
283     ctx->exception = (excp);
284 }
285 
gen_debug_exception(DisasContext * ctx)286 static inline void gen_debug_exception(DisasContext *ctx)
287 {
288     TCGv_i32 t0;
289 
290     if (ctx->exception != POWERPC_EXCP_BRANCH)
291         gen_update_nip(ctx, ctx->nip);
292     t0 = tcg_const_i32(EXCP_DEBUG);
293     gen_helper_raise_exception(t0);
294     tcg_temp_free_i32(t0);
295 }
296 
gen_inval_exception(DisasContext * ctx,uint32_t error)297 static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
298 {
299     gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
300 }
301 
302 /* Stop translation */
gen_stop_exception(DisasContext * ctx)303 static inline void gen_stop_exception(DisasContext *ctx)
304 {
305     gen_update_nip(ctx, ctx->nip);
306     ctx->exception = POWERPC_EXCP_STOP;
307 }
308 
309 /* No need to update nip here, as execution flow will change */
gen_sync_exception(DisasContext * ctx)310 static inline void gen_sync_exception(DisasContext *ctx)
311 {
312     ctx->exception = POWERPC_EXCP_SYNC;
313 }
314 
315 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
316 GEN_OPCODE(name, opc1, opc2, opc3, inval, type)
317 
318 #define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
319 GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type)
320 
321 typedef struct opcode_t {
322     unsigned char opc1, opc2, opc3;
323 #if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
324     unsigned char pad[5];
325 #else
326     unsigned char pad[1];
327 #endif
328     opc_handler_t handler;
329     const char *oname;
330 } opcode_t;
331 
332 /*****************************************************************************/
333 /***                           Instruction decoding                        ***/
334 #define EXTRACT_HELPER(name, shift, nb)                                       \
335 static inline uint32_t name(uint32_t opcode)                                  \
336 {                                                                             \
337     return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
338 }
339 
340 #define EXTRACT_SHELPER(name, shift, nb)                                      \
341 static inline int32_t name(uint32_t opcode)                                   \
342 {                                                                             \
343     return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
344 }
345 
346 /* Opcode part 1 */
347 EXTRACT_HELPER(opc1, 26, 6);
348 /* Opcode part 2 */
349 EXTRACT_HELPER(opc2, 1, 5);
350 /* Opcode part 3 */
351 EXTRACT_HELPER(opc3, 6, 5);
352 /* Update Cr0 flags */
353 EXTRACT_HELPER(Rc, 0, 1);
354 /* Destination */
355 EXTRACT_HELPER(rD, 21, 5);
356 /* Source */
357 EXTRACT_HELPER(rS, 21, 5);
358 /* First operand */
359 EXTRACT_HELPER(rA, 16, 5);
360 /* Second operand */
361 EXTRACT_HELPER(rB, 11, 5);
362 /* Third operand */
363 EXTRACT_HELPER(rC, 6, 5);
364 /***                               Get CRn                                 ***/
365 EXTRACT_HELPER(crfD, 23, 3);
366 EXTRACT_HELPER(crfS, 18, 3);
367 EXTRACT_HELPER(crbD, 21, 5);
368 EXTRACT_HELPER(crbA, 16, 5);
369 EXTRACT_HELPER(crbB, 11, 5);
370 /* SPR / TBL */
371 EXTRACT_HELPER(_SPR, 11, 10);
SPR(uint32_t opcode)372 static inline uint32_t SPR(uint32_t opcode)
373 {
374     uint32_t sprn = _SPR(opcode);
375 
376     return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
377 }
378 /***                              Get constants                            ***/
379 EXTRACT_HELPER(IMM, 12, 8);
380 /* 16 bits signed immediate value */
381 EXTRACT_SHELPER(SIMM, 0, 16);
382 /* 16 bits unsigned immediate value */
383 EXTRACT_HELPER(UIMM, 0, 16);
384 /* 5 bits signed immediate value */
385 EXTRACT_HELPER(SIMM5, 16, 5);
386 /* 5 bits signed immediate value */
387 EXTRACT_HELPER(UIMM5, 16, 5);
388 /* Bit count */
389 EXTRACT_HELPER(NB, 11, 5);
390 /* Shift count */
391 EXTRACT_HELPER(SH, 11, 5);
392 /* Vector shift count */
393 EXTRACT_HELPER(VSH, 6, 4);
394 /* Mask start */
395 EXTRACT_HELPER(MB, 6, 5);
396 /* Mask end */
397 EXTRACT_HELPER(ME, 1, 5);
398 /* Trap operand */
399 EXTRACT_HELPER(TO, 21, 5);
400 
401 EXTRACT_HELPER(CRM, 12, 8);
402 EXTRACT_HELPER(FM, 17, 8);
403 EXTRACT_HELPER(SR, 16, 4);
404 EXTRACT_HELPER(FPIMM, 12, 4);
405 
406 /***                            Jump target decoding                       ***/
407 /* Displacement */
408 EXTRACT_SHELPER(d, 0, 16);
409 /* Immediate address */
LI(uint32_t opcode)410 static inline target_ulong LI(uint32_t opcode)
411 {
412     return (opcode >> 0) & 0x03FFFFFC;
413 }
414 
BD(uint32_t opcode)415 static inline uint32_t BD(uint32_t opcode)
416 {
417     return (opcode >> 0) & 0xFFFC;
418 }
419 
420 EXTRACT_HELPER(BO, 21, 5);
421 EXTRACT_HELPER(BI, 16, 5);
422 /* Absolute/relative address */
423 EXTRACT_HELPER(AA, 1, 1);
424 /* Link */
425 EXTRACT_HELPER(LK, 0, 1);
426 
427 /* Create a mask between <start> and <end> bits */
MASK(uint32_t start,uint32_t end)428 static inline target_ulong MASK(uint32_t start, uint32_t end)
429 {
430     target_ulong ret;
431 
432 #if defined(TARGET_PPC64)
433     if (likely(start == 0)) {
434         ret = UINT64_MAX << (63 - end);
435     } else if (likely(end == 63)) {
436         ret = UINT64_MAX >> start;
437     }
438 #else
439     if (likely(start == 0)) {
440         ret = UINT32_MAX << (31  - end);
441     } else if (likely(end == 31)) {
442         ret = UINT32_MAX >> start;
443     }
444 #endif
445     else {
446         ret = (((target_ulong)(-1ULL)) >> (start)) ^
447             (((target_ulong)(-1ULL) >> (end)) >> 1);
448         if (unlikely(start > end))
449             return ~ret;
450     }
451 
452     return ret;
453 }
454 
455 /*****************************************************************************/
456 /* PowerPC instructions table                                                */
457 
458 #if defined(DO_PPC_STATISTICS)
459 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
460 {                                                                             \
461     .opc1 = op1,                                                              \
462     .opc2 = op2,                                                              \
463     .opc3 = op3,                                                              \
464     .pad  = { 0, },                                                           \
465     .handler = {                                                              \
466         .inval   = invl,                                                      \
467         .type = _typ,                                                         \
468         .handler = &gen_##name,                                               \
469         .oname = stringify(name),                                             \
470     },                                                                        \
471     .oname = stringify(name),                                                 \
472 }
473 #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
474 {                                                                             \
475     .opc1 = op1,                                                              \
476     .opc2 = op2,                                                              \
477     .opc3 = op3,                                                              \
478     .pad  = { 0, },                                                           \
479     .handler = {                                                              \
480         .inval   = invl,                                                      \
481         .type = _typ,                                                         \
482         .handler = &gen_##name,                                               \
483         .oname = onam,                                                        \
484     },                                                                        \
485     .oname = onam,                                                            \
486 }
487 #else
488 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
489 {                                                                             \
490     .opc1 = op1,                                                              \
491     .opc2 = op2,                                                              \
492     .opc3 = op3,                                                              \
493     .pad  = { 0, },                                                           \
494     .handler = {                                                              \
495         .inval   = invl,                                                      \
496         .type = _typ,                                                         \
497         .handler = &gen_##name,                                               \
498     },                                                                        \
499     .oname = stringify(name),                                                 \
500 }
501 #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
502 {                                                                             \
503     .opc1 = op1,                                                              \
504     .opc2 = op2,                                                              \
505     .opc3 = op3,                                                              \
506     .pad  = { 0, },                                                           \
507     .handler = {                                                              \
508         .inval   = invl,                                                      \
509         .type = _typ,                                                         \
510         .handler = &gen_##name,                                               \
511     },                                                                        \
512     .oname = onam,                                                            \
513 }
514 #endif
515 
516 /* SPR load/store helpers */
gen_load_spr(TCGv t,int reg)517 static inline void gen_load_spr(TCGv t, int reg)
518 {
519     tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
520 }
521 
gen_store_spr(int reg,TCGv t)522 static inline void gen_store_spr(int reg, TCGv t)
523 {
524     tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
525 }
526 
527 /* Invalid instruction */
gen_invalid(DisasContext * ctx)528 static void gen_invalid(DisasContext *ctx)
529 {
530     gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
531 }
532 
533 static opc_handler_t invalid_handler = {
534     .inval   = 0xFFFFFFFF,
535     .type    = PPC_NONE,
536     .handler = gen_invalid,
537 };
538 
539 /***                           Integer comparison                          ***/
540 
gen_op_cmp(TCGv arg0,TCGv arg1,int s,int crf)541 static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
542 {
543     int l1, l2, l3;
544 
545     tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
546     tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
547     tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
548 
549     l1 = gen_new_label();
550     l2 = gen_new_label();
551     l3 = gen_new_label();
552     if (s) {
553         tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
554         tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
555     } else {
556         tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
557         tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
558     }
559     tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
560     tcg_gen_br(l3);
561     gen_set_label(l1);
562     tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
563     tcg_gen_br(l3);
564     gen_set_label(l2);
565     tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
566     gen_set_label(l3);
567 }
568 
gen_op_cmpi(TCGv arg0,target_ulong arg1,int s,int crf)569 static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
570 {
571     TCGv t0 = tcg_const_local_tl(arg1);
572     gen_op_cmp(arg0, t0, s, crf);
573     tcg_temp_free(t0);
574 }
575 
576 #if defined(TARGET_PPC64)
gen_op_cmp32(TCGv arg0,TCGv arg1,int s,int crf)577 static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
578 {
579     TCGv t0, t1;
580     t0 = tcg_temp_local_new();
581     t1 = tcg_temp_local_new();
582     if (s) {
583         tcg_gen_ext32s_tl(t0, arg0);
584         tcg_gen_ext32s_tl(t1, arg1);
585     } else {
586         tcg_gen_ext32u_tl(t0, arg0);
587         tcg_gen_ext32u_tl(t1, arg1);
588     }
589     gen_op_cmp(t0, t1, s, crf);
590     tcg_temp_free(t1);
591     tcg_temp_free(t0);
592 }
593 
gen_op_cmpi32(TCGv arg0,target_ulong arg1,int s,int crf)594 static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
595 {
596     TCGv t0 = tcg_const_local_tl(arg1);
597     gen_op_cmp32(arg0, t0, s, crf);
598     tcg_temp_free(t0);
599 }
600 #endif
601 
gen_set_Rc0(DisasContext * ctx,TCGv reg)602 static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
603 {
604 #if defined(TARGET_PPC64)
605     if (!(ctx->sf_mode))
606         gen_op_cmpi32(reg, 0, 1, 0);
607     else
608 #endif
609         gen_op_cmpi(reg, 0, 1, 0);
610 }
611 
612 /* cmp */
gen_cmp(DisasContext * ctx)613 static void gen_cmp(DisasContext *ctx)
614 {
615 #if defined(TARGET_PPC64)
616     if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
617         gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
618                      1, crfD(ctx->opcode));
619     else
620 #endif
621         gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
622                    1, crfD(ctx->opcode));
623 }
624 
625 /* cmpi */
gen_cmpi(DisasContext * ctx)626 static void gen_cmpi(DisasContext *ctx)
627 {
628 #if defined(TARGET_PPC64)
629     if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
630         gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
631                       1, crfD(ctx->opcode));
632     else
633 #endif
634         gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
635                     1, crfD(ctx->opcode));
636 }
637 
638 /* cmpl */
gen_cmpl(DisasContext * ctx)639 static void gen_cmpl(DisasContext *ctx)
640 {
641 #if defined(TARGET_PPC64)
642     if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
643         gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
644                      0, crfD(ctx->opcode));
645     else
646 #endif
647         gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
648                    0, crfD(ctx->opcode));
649 }
650 
651 /* cmpli */
gen_cmpli(DisasContext * ctx)652 static void gen_cmpli(DisasContext *ctx)
653 {
654 #if defined(TARGET_PPC64)
655     if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
656         gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
657                       0, crfD(ctx->opcode));
658     else
659 #endif
660         gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
661                     0, crfD(ctx->opcode));
662 }
663 
664 /* isel (PowerPC 2.03 specification) */
gen_isel(DisasContext * ctx)665 static void gen_isel(DisasContext *ctx)
666 {
667     int l1, l2;
668     uint32_t bi = rC(ctx->opcode);
669     uint32_t mask;
670     TCGv_i32 t0;
671 
672     l1 = gen_new_label();
673     l2 = gen_new_label();
674 
675     mask = 1 << (3 - (bi & 0x03));
676     t0 = tcg_temp_new_i32();
677     tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
678     tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
679     if (rA(ctx->opcode) == 0)
680         tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
681     else
682         tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
683     tcg_gen_br(l2);
684     gen_set_label(l1);
685     tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
686     gen_set_label(l2);
687     tcg_temp_free_i32(t0);
688 }
689 
690 /***                           Integer arithmetic                          ***/
691 
gen_op_arith_compute_ov(DisasContext * ctx,TCGv arg0,TCGv arg1,TCGv arg2,int sub)692 static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
693                                            TCGv arg1, TCGv arg2, int sub)
694 {
695     int l1;
696     TCGv t0;
697 
698     l1 = gen_new_label();
699     /* Start with XER OV disabled, the most likely case */
700     tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
701     t0 = tcg_temp_local_new();
702     tcg_gen_xor_tl(t0, arg0, arg1);
703 #if defined(TARGET_PPC64)
704     if (!ctx->sf_mode)
705         tcg_gen_ext32s_tl(t0, t0);
706 #endif
707     if (sub)
708         tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
709     else
710         tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
711     tcg_gen_xor_tl(t0, arg1, arg2);
712 #if defined(TARGET_PPC64)
713     if (!ctx->sf_mode)
714         tcg_gen_ext32s_tl(t0, t0);
715 #endif
716     if (sub)
717         tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
718     else
719         tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
720     tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
721     gen_set_label(l1);
722     tcg_temp_free(t0);
723 }
724 
gen_op_arith_compute_ca(DisasContext * ctx,TCGv arg1,TCGv arg2,int sub)725 static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
726                                            TCGv arg2, int sub)
727 {
728     int l1 = gen_new_label();
729 
730 #if defined(TARGET_PPC64)
731     if (!(ctx->sf_mode)) {
732         TCGv t0, t1;
733         t0 = tcg_temp_new();
734         t1 = tcg_temp_new();
735 
736         tcg_gen_ext32u_tl(t0, arg1);
737         tcg_gen_ext32u_tl(t1, arg2);
738         if (sub) {
739             tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
740         } else {
741             tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
742         }
743         tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
744         gen_set_label(l1);
745         tcg_temp_free(t0);
746         tcg_temp_free(t1);
747     } else
748 #endif
749     {
750         if (sub) {
751             tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
752         } else {
753             tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
754         }
755         tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
756         gen_set_label(l1);
757     }
758 }
759 
760 /* Common add function */
gen_op_arith_add(DisasContext * ctx,TCGv ret,TCGv arg1,TCGv arg2,int add_ca,int compute_ca,int compute_ov)761 static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
762                                     TCGv arg2, int add_ca, int compute_ca,
763                                     int compute_ov)
764 {
765     TCGv t0, t1;
766 
767     if ((!compute_ca && !compute_ov) ||
768         (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
769         t0 = ret;
770     } else {
771         t0 = tcg_temp_local_new();
772     }
773 
774     if (add_ca) {
775         t1 = tcg_temp_local_new();
776         tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
777         tcg_gen_shri_tl(t1, t1, XER_CA);
778     } else {
779         TCGV_UNUSED(t1);
780     }
781 
782     if (compute_ca && compute_ov) {
783         /* Start with XER CA and OV disabled, the most likely case */
784         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
785     } else if (compute_ca) {
786         /* Start with XER CA disabled, the most likely case */
787         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
788     } else if (compute_ov) {
789         /* Start with XER OV disabled, the most likely case */
790         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
791     }
792 
793     tcg_gen_add_tl(t0, arg1, arg2);
794 
795     if (compute_ca) {
796         gen_op_arith_compute_ca(ctx, t0, arg1, 0);
797     }
798     if (add_ca) {
799         tcg_gen_add_tl(t0, t0, t1);
800         gen_op_arith_compute_ca(ctx, t0, t1, 0);
801         tcg_temp_free(t1);
802     }
803     if (compute_ov) {
804         gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
805     }
806 
807     if (unlikely(Rc(ctx->opcode) != 0))
808         gen_set_Rc0(ctx, t0);
809 
810     if (!TCGV_EQUAL(t0, ret)) {
811         tcg_gen_mov_tl(ret, t0);
812         tcg_temp_free(t0);
813     }
814 }
815 /* Add functions with two operands */
816 #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
817 static void glue(gen_, name)(DisasContext *ctx)                                       \
818 {                                                                             \
819     gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
820                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
821                      add_ca, compute_ca, compute_ov);                         \
822 }
823 /* Add functions with one operand and one immediate */
824 #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
825                                 add_ca, compute_ca, compute_ov)               \
826 static void glue(gen_, name)(DisasContext *ctx)                                       \
827 {                                                                             \
828     TCGv t0 = tcg_const_local_tl(const_val);                                  \
829     gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
830                      cpu_gpr[rA(ctx->opcode)], t0,                            \
831                      add_ca, compute_ca, compute_ov);                         \
832     tcg_temp_free(t0);                                                        \
833 }
834 
835 /* add  add.  addo  addo. */
836 GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
837 GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
838 /* addc  addc.  addco  addco. */
839 GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
840 GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
841 /* adde  adde.  addeo  addeo. */
842 GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
843 GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
844 /* addme  addme.  addmeo  addmeo.  */
845 GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
846 GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
847 /* addze  addze.  addzeo  addzeo.*/
848 GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
849 GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
850 /* addi */
851 static void gen_addi(DisasContext *ctx)
852 {
853     target_long simm = SIMM(ctx->opcode);
854 
855     if (rA(ctx->opcode) == 0) {
856         /* li case */
857         tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
858     } else {
859         tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
860     }
861 }
862 /* addic  addic.*/
gen_op_addic(DisasContext * ctx,TCGv ret,TCGv arg1,int compute_Rc0)863 static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
864                                 int compute_Rc0)
865 {
866     target_long simm = SIMM(ctx->opcode);
867 
868     /* Start with XER CA and OV disabled, the most likely case */
869     tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
870 
871     if (likely(simm != 0)) {
872         TCGv t0 = tcg_temp_local_new();
873         tcg_gen_addi_tl(t0, arg1, simm);
874         gen_op_arith_compute_ca(ctx, t0, arg1, 0);
875         tcg_gen_mov_tl(ret, t0);
876         tcg_temp_free(t0);
877     } else {
878         tcg_gen_mov_tl(ret, arg1);
879     }
880     if (compute_Rc0) {
881         gen_set_Rc0(ctx, ret);
882     }
883 }
884 
gen_addic(DisasContext * ctx)885 static void gen_addic(DisasContext *ctx)
886 {
887     gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
888 }
889 
gen_addic_(DisasContext * ctx)890 static void gen_addic_(DisasContext *ctx)
891 {
892     gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
893 }
894 
895 /* addis */
gen_addis(DisasContext * ctx)896 static void gen_addis(DisasContext *ctx)
897 {
898     target_long simm = SIMM(ctx->opcode);
899 
900     if (rA(ctx->opcode) == 0) {
901         /* lis case */
902         tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
903     } else {
904         tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
905     }
906 }
907 
gen_op_arith_divw(DisasContext * ctx,TCGv ret,TCGv arg1,TCGv arg2,int sign,int compute_ov)908 static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
909                                      TCGv arg2, int sign, int compute_ov)
910 {
911     int l1 = gen_new_label();
912     int l2 = gen_new_label();
913     TCGv_i32 t0 = tcg_temp_local_new_i32();
914     TCGv_i32 t1 = tcg_temp_local_new_i32();
915 
916     tcg_gen_trunc_tl_i32(t0, arg1);
917     tcg_gen_trunc_tl_i32(t1, arg2);
918     tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
919     if (sign) {
920         int l3 = gen_new_label();
921         tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
922         tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
923         gen_set_label(l3);
924         tcg_gen_div_i32(t0, t0, t1);
925     } else {
926         tcg_gen_divu_i32(t0, t0, t1);
927     }
928     if (compute_ov) {
929         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
930     }
931     tcg_gen_br(l2);
932     gen_set_label(l1);
933     if (sign) {
934         tcg_gen_sari_i32(t0, t0, 31);
935     } else {
936         tcg_gen_movi_i32(t0, 0);
937     }
938     if (compute_ov) {
939         tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
940     }
941     gen_set_label(l2);
942     tcg_gen_extu_i32_tl(ret, t0);
943     tcg_temp_free_i32(t0);
944     tcg_temp_free_i32(t1);
945     if (unlikely(Rc(ctx->opcode) != 0))
946         gen_set_Rc0(ctx, ret);
947 }
948 /* Div functions */
949 #define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
950 static void glue(gen_, name)(DisasContext *ctx)                                       \
951 {                                                                             \
952     gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
953                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
954                      sign, compute_ov);                                       \
955 }
956 /* divwu  divwu.  divwuo  divwuo.   */
957 GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
958 GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
959 /* divw  divw.  divwo  divwo.   */
960 GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
961 GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
962 #if defined(TARGET_PPC64)
gen_op_arith_divd(DisasContext * ctx,TCGv ret,TCGv arg1,TCGv arg2,int sign,int compute_ov)963 static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
964                                      TCGv arg2, int sign, int compute_ov)
965 {
966     int l1 = gen_new_label();
967     int l2 = gen_new_label();
968 
969     tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
970     if (sign) {
971         int l3 = gen_new_label();
972         tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
973         tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
974         gen_set_label(l3);
975         tcg_gen_div_i64(ret, arg1, arg2);
976     } else {
977         tcg_gen_divu_i64(ret, arg1, arg2);
978     }
979     if (compute_ov) {
980         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
981     }
982     tcg_gen_br(l2);
983     gen_set_label(l1);
984     if (sign) {
985         tcg_gen_sari_i64(ret, arg1, 63);
986     } else {
987         tcg_gen_movi_i64(ret, 0);
988     }
989     if (compute_ov) {
990         tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
991     }
992     gen_set_label(l2);
993     if (unlikely(Rc(ctx->opcode) != 0))
994         gen_set_Rc0(ctx, ret);
995 }
996 #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
997 static void glue(gen_, name)(DisasContext *ctx)                                       \
998 {                                                                             \
999     gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1000                       cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1001                       sign, compute_ov);                                      \
1002 }
1003 /* divwu  divwu.  divwuo  divwuo.   */
1004 GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1005 GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1006 /* divw  divw.  divwo  divwo.   */
1007 GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1008 GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1009 #endif
1010 
1011 /* mulhw  mulhw. */
gen_mulhw(DisasContext * ctx)1012 static void gen_mulhw(DisasContext *ctx)
1013 {
1014     TCGv_i64 t0, t1;
1015 
1016     t0 = tcg_temp_new_i64();
1017     t1 = tcg_temp_new_i64();
1018 #if defined(TARGET_PPC64)
1019     tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1020     tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1021     tcg_gen_mul_i64(t0, t0, t1);
1022     tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1023 #else
1024     tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1025     tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1026     tcg_gen_mul_i64(t0, t0, t1);
1027     tcg_gen_shri_i64(t0, t0, 32);
1028     tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1029 #endif
1030     tcg_temp_free_i64(t0);
1031     tcg_temp_free_i64(t1);
1032     if (unlikely(Rc(ctx->opcode) != 0))
1033         gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1034 }
1035 
1036 /* mulhwu  mulhwu.  */
gen_mulhwu(DisasContext * ctx)1037 static void gen_mulhwu(DisasContext *ctx)
1038 {
1039     TCGv_i64 t0, t1;
1040 
1041     t0 = tcg_temp_new_i64();
1042     t1 = tcg_temp_new_i64();
1043 #if defined(TARGET_PPC64)
1044     tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1045     tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1046     tcg_gen_mul_i64(t0, t0, t1);
1047     tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1048 #else
1049     tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1050     tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1051     tcg_gen_mul_i64(t0, t0, t1);
1052     tcg_gen_shri_i64(t0, t0, 32);
1053     tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1054 #endif
1055     tcg_temp_free_i64(t0);
1056     tcg_temp_free_i64(t1);
1057     if (unlikely(Rc(ctx->opcode) != 0))
1058         gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1059 }
1060 
1061 /* mullw  mullw. */
gen_mullw(DisasContext * ctx)1062 static void gen_mullw(DisasContext *ctx)
1063 {
1064     tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1065                    cpu_gpr[rB(ctx->opcode)]);
1066     tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1067     if (unlikely(Rc(ctx->opcode) != 0))
1068         gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1069 }
1070 
1071 /* mullwo  mullwo. */
gen_mullwo(DisasContext * ctx)1072 static void gen_mullwo(DisasContext *ctx)
1073 {
1074     int l1;
1075     TCGv_i64 t0, t1;
1076 
1077     t0 = tcg_temp_new_i64();
1078     t1 = tcg_temp_new_i64();
1079     l1 = gen_new_label();
1080     /* Start with XER OV disabled, the most likely case */
1081     tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1082 #if defined(TARGET_PPC64)
1083     tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1084     tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1085 #else
1086     tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1087     tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1088 #endif
1089     tcg_gen_mul_i64(t0, t0, t1);
1090 #if defined(TARGET_PPC64)
1091     tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
1092     tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
1093 #else
1094     tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1095     tcg_gen_ext32s_i64(t1, t0);
1096     tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
1097 #endif
1098     tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1099     gen_set_label(l1);
1100     tcg_temp_free_i64(t0);
1101     tcg_temp_free_i64(t1);
1102     if (unlikely(Rc(ctx->opcode) != 0))
1103         gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1104 }
1105 
1106 /* mulli */
gen_mulli(DisasContext * ctx)1107 static void gen_mulli(DisasContext *ctx)
1108 {
1109     tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1110                     SIMM(ctx->opcode));
1111 }
1112 #if defined(TARGET_PPC64)
1113 #define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
1114 static void glue(gen_, name)(DisasContext *ctx)                                       \
1115 {                                                                             \
1116     gen_helper_##name (cpu_gpr[rD(ctx->opcode)],                              \
1117                        cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);   \
1118     if (unlikely(Rc(ctx->opcode) != 0))                                       \
1119         gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
1120 }
1121 /* mulhd  mulhd. */
1122 GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
1123 /* mulhdu  mulhdu. */
1124 GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
1125 
1126 /* mulld  mulld. */
gen_mulld(DisasContext * ctx)1127 static void gen_mulld(DisasContext *ctx)
1128 {
1129     tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1130                    cpu_gpr[rB(ctx->opcode)]);
1131     if (unlikely(Rc(ctx->opcode) != 0))
1132         gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1133 }
1134 /* mulldo  mulldo. */
1135 GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1136 #endif
1137 
1138 /* neg neg. nego nego. */
gen_op_arith_neg(DisasContext * ctx,TCGv ret,TCGv arg1,int ov_check)1139 static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
1140                                     int ov_check)
1141 {
1142     int l1 = gen_new_label();
1143     int l2 = gen_new_label();
1144     TCGv t0 = tcg_temp_local_new();
1145 #if defined(TARGET_PPC64)
1146     if (ctx->sf_mode) {
1147         tcg_gen_mov_tl(t0, arg1);
1148         tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
1149     } else
1150 #endif
1151     {
1152         tcg_gen_ext32s_tl(t0, arg1);
1153         tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
1154     }
1155     tcg_gen_neg_tl(ret, arg1);
1156     if (ov_check) {
1157         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1158     }
1159     tcg_gen_br(l2);
1160     gen_set_label(l1);
1161     tcg_gen_mov_tl(ret, t0);
1162     if (ov_check) {
1163         tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1164     }
1165     gen_set_label(l2);
1166     tcg_temp_free(t0);
1167     if (unlikely(Rc(ctx->opcode) != 0))
1168         gen_set_Rc0(ctx, ret);
1169 }
1170 
gen_neg(DisasContext * ctx)1171 static void gen_neg(DisasContext *ctx)
1172 {
1173     gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1174 }
1175 
gen_nego(DisasContext * ctx)1176 static void gen_nego(DisasContext *ctx)
1177 {
1178     gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1179 }
1180 
1181 /* Common subf function */
gen_op_arith_subf(DisasContext * ctx,TCGv ret,TCGv arg1,TCGv arg2,int add_ca,int compute_ca,int compute_ov)1182 static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1183                                      TCGv arg2, int add_ca, int compute_ca,
1184                                      int compute_ov)
1185 {
1186     TCGv t0, t1;
1187 
1188     if ((!compute_ca && !compute_ov) ||
1189         (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1190         t0 = ret;
1191     } else {
1192         t0 = tcg_temp_local_new();
1193     }
1194 
1195     if (add_ca) {
1196         t1 = tcg_temp_local_new();
1197         tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1198         tcg_gen_shri_tl(t1, t1, XER_CA);
1199     } else {
1200         TCGV_UNUSED(t1);
1201     }
1202 
1203     if (compute_ca && compute_ov) {
1204         /* Start with XER CA and OV disabled, the most likely case */
1205         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
1206     } else if (compute_ca) {
1207         /* Start with XER CA disabled, the most likely case */
1208         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1209     } else if (compute_ov) {
1210         /* Start with XER OV disabled, the most likely case */
1211         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1212     }
1213 
1214     if (add_ca) {
1215         tcg_gen_not_tl(t0, arg1);
1216         tcg_gen_add_tl(t0, t0, arg2);
1217         gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1218         tcg_gen_add_tl(t0, t0, t1);
1219         gen_op_arith_compute_ca(ctx, t0, t1, 0);
1220         tcg_temp_free(t1);
1221     } else {
1222         tcg_gen_sub_tl(t0, arg2, arg1);
1223         if (compute_ca) {
1224             gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1225         }
1226     }
1227     if (compute_ov) {
1228         gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1229     }
1230 
1231     if (unlikely(Rc(ctx->opcode) != 0))
1232         gen_set_Rc0(ctx, t0);
1233 
1234     if (!TCGV_EQUAL(t0, ret)) {
1235         tcg_gen_mov_tl(ret, t0);
1236         tcg_temp_free(t0);
1237     }
1238 }
1239 /* Sub functions with Two operands functions */
1240 #define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1241 static void glue(gen_, name)(DisasContext *ctx)                                       \
1242 {                                                                             \
1243     gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1244                       cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1245                       add_ca, compute_ca, compute_ov);                        \
1246 }
1247 /* Sub functions with one operand and one immediate */
1248 #define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
1249                                 add_ca, compute_ca, compute_ov)               \
1250 static void glue(gen_, name)(DisasContext *ctx)                                       \
1251 {                                                                             \
1252     TCGv t0 = tcg_const_local_tl(const_val);                                  \
1253     gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1254                       cpu_gpr[rA(ctx->opcode)], t0,                           \
1255                       add_ca, compute_ca, compute_ov);                        \
1256     tcg_temp_free(t0);                                                        \
1257 }
1258 /* subf  subf.  subfo  subfo. */
1259 GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1260 GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1261 /* subfc  subfc.  subfco  subfco. */
1262 GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1263 GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1264 /* subfe  subfe.  subfeo  subfo. */
1265 GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1266 GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1267 /* subfme  subfme.  subfmeo  subfmeo.  */
1268 GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1269 GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1270 /* subfze  subfze.  subfzeo  subfzeo.*/
1271 GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1272 GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
1273 
1274 /* subfic */
1275 static void gen_subfic(DisasContext *ctx)
1276 {
1277     /* Start with XER CA and OV disabled, the most likely case */
1278     tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1279     TCGv t0 = tcg_temp_local_new();
1280     TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
1281     tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
1282     gen_op_arith_compute_ca(ctx, t0, t1, 1);
1283     tcg_temp_free(t1);
1284     tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
1285     tcg_temp_free(t0);
1286 }
1287 
1288 /***                            Integer logical                            ***/
1289 #define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
1290 static void glue(gen_, name)(DisasContext *ctx)                                       \
1291 {                                                                             \
1292     tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
1293        cpu_gpr[rB(ctx->opcode)]);                                             \
1294     if (unlikely(Rc(ctx->opcode) != 0))                                       \
1295         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1296 }
1297 
1298 #define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1299 static void glue(gen_, name)(DisasContext *ctx)                                       \
1300 {                                                                             \
1301     tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1302     if (unlikely(Rc(ctx->opcode) != 0))                                       \
1303         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1304 }
1305 
1306 /* and & and. */
1307 GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1308 /* andc & andc. */
1309 GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1310 
1311 /* andi. */
gen_andi_(DisasContext * ctx)1312 static void gen_andi_(DisasContext *ctx)
1313 {
1314     tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1315     gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1316 }
1317 
1318 /* andis. */
gen_andis_(DisasContext * ctx)1319 static void gen_andis_(DisasContext *ctx)
1320 {
1321     tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1322     gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1323 }
1324 
1325 /* cntlzw */
gen_cntlzw(DisasContext * ctx)1326 static void gen_cntlzw(DisasContext *ctx)
1327 {
1328     gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1329     if (unlikely(Rc(ctx->opcode) != 0))
1330         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1331 }
1332 /* eqv & eqv. */
1333 GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1334 /* extsb & extsb. */
1335 GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1336 /* extsh & extsh. */
1337 GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1338 /* nand & nand. */
1339 GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1340 /* nor & nor. */
1341 GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1342 
1343 /* or & or. */
gen_or(DisasContext * ctx)1344 static void gen_or(DisasContext *ctx)
1345 {
1346     int rs, ra, rb;
1347 
1348     rs = rS(ctx->opcode);
1349     ra = rA(ctx->opcode);
1350     rb = rB(ctx->opcode);
1351     /* Optimisation for mr. ri case */
1352     if (rs != ra || rs != rb) {
1353         if (rs != rb)
1354             tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1355         else
1356             tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1357         if (unlikely(Rc(ctx->opcode) != 0))
1358             gen_set_Rc0(ctx, cpu_gpr[ra]);
1359     } else if (unlikely(Rc(ctx->opcode) != 0)) {
1360         gen_set_Rc0(ctx, cpu_gpr[rs]);
1361 #if defined(TARGET_PPC64)
1362     } else {
1363         int prio = 0;
1364 
1365         switch (rs) {
1366         case 1:
1367             /* Set process priority to low */
1368             prio = 2;
1369             break;
1370         case 6:
1371             /* Set process priority to medium-low */
1372             prio = 3;
1373             break;
1374         case 2:
1375             /* Set process priority to normal */
1376             prio = 4;
1377             break;
1378 #if !defined(CONFIG_USER_ONLY)
1379         case 31:
1380             if (ctx->mem_idx > 0) {
1381                 /* Set process priority to very low */
1382                 prio = 1;
1383             }
1384             break;
1385         case 5:
1386             if (ctx->mem_idx > 0) {
1387                 /* Set process priority to medium-hight */
1388                 prio = 5;
1389             }
1390             break;
1391         case 3:
1392             if (ctx->mem_idx > 0) {
1393                 /* Set process priority to high */
1394                 prio = 6;
1395             }
1396             break;
1397         case 7:
1398             if (ctx->mem_idx > 1) {
1399                 /* Set process priority to very high */
1400                 prio = 7;
1401             }
1402             break;
1403 #endif
1404         default:
1405             /* nop */
1406             break;
1407         }
1408         if (prio) {
1409             TCGv t0 = tcg_temp_new();
1410             gen_load_spr(t0, SPR_PPR);
1411             tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1412             tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1413             gen_store_spr(SPR_PPR, t0);
1414             tcg_temp_free(t0);
1415         }
1416 #endif
1417     }
1418 }
1419 /* orc & orc. */
1420 GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1421 
1422 /* xor & xor. */
gen_xor(DisasContext * ctx)1423 static void gen_xor(DisasContext *ctx)
1424 {
1425     /* Optimisation for "set to zero" case */
1426     if (rS(ctx->opcode) != rB(ctx->opcode))
1427         tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1428     else
1429         tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1430     if (unlikely(Rc(ctx->opcode) != 0))
1431         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1432 }
1433 
1434 /* ori */
gen_ori(DisasContext * ctx)1435 static void gen_ori(DisasContext *ctx)
1436 {
1437     target_ulong uimm = UIMM(ctx->opcode);
1438 
1439     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1440         /* NOP */
1441         /* XXX: should handle special NOPs for POWER series */
1442         return;
1443     }
1444     tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1445 }
1446 
1447 /* oris */
gen_oris(DisasContext * ctx)1448 static void gen_oris(DisasContext *ctx)
1449 {
1450     target_ulong uimm = UIMM(ctx->opcode);
1451 
1452     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1453         /* NOP */
1454         return;
1455     }
1456     tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1457 }
1458 
1459 /* xori */
gen_xori(DisasContext * ctx)1460 static void gen_xori(DisasContext *ctx)
1461 {
1462     target_ulong uimm = UIMM(ctx->opcode);
1463 
1464     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1465         /* NOP */
1466         return;
1467     }
1468     tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1469 }
1470 
1471 /* xoris */
gen_xoris(DisasContext * ctx)1472 static void gen_xoris(DisasContext *ctx)
1473 {
1474     target_ulong uimm = UIMM(ctx->opcode);
1475 
1476     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1477         /* NOP */
1478         return;
1479     }
1480     tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1481 }
1482 
1483 /* popcntb : PowerPC 2.03 specification */
gen_popcntb(DisasContext * ctx)1484 static void gen_popcntb(DisasContext *ctx)
1485 {
1486 #if defined(TARGET_PPC64)
1487     if (ctx->sf_mode)
1488         gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1489     else
1490 #endif
1491         gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1492 }
1493 
1494 #if defined(TARGET_PPC64)
1495 /* extsw & extsw. */
1496 GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1497 
1498 /* cntlzd */
gen_cntlzd(DisasContext * ctx)1499 static void gen_cntlzd(DisasContext *ctx)
1500 {
1501     gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1502     if (unlikely(Rc(ctx->opcode) != 0))
1503         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1504 }
1505 #endif
1506 
1507 /***                             Integer rotate                            ***/
1508 
1509 /* rlwimi & rlwimi. */
gen_rlwimi(DisasContext * ctx)1510 static void gen_rlwimi(DisasContext *ctx)
1511 {
1512     uint32_t mb, me, sh;
1513 
1514     mb = MB(ctx->opcode);
1515     me = ME(ctx->opcode);
1516     sh = SH(ctx->opcode);
1517     if (likely(sh == 0 && mb == 0 && me == 31)) {
1518         tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1519     } else {
1520         target_ulong mask;
1521         TCGv t1;
1522         TCGv t0 = tcg_temp_new();
1523 #if defined(TARGET_PPC64)
1524         TCGv_i32 t2 = tcg_temp_new_i32();
1525         tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1526         tcg_gen_rotli_i32(t2, t2, sh);
1527         tcg_gen_extu_i32_i64(t0, t2);
1528         tcg_temp_free_i32(t2);
1529 #else
1530         tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1531 #endif
1532 #if defined(TARGET_PPC64)
1533         mb += 32;
1534         me += 32;
1535 #endif
1536         mask = MASK(mb, me);
1537         t1 = tcg_temp_new();
1538         tcg_gen_andi_tl(t0, t0, mask);
1539         tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1540         tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1541         tcg_temp_free(t0);
1542         tcg_temp_free(t1);
1543     }
1544     if (unlikely(Rc(ctx->opcode) != 0))
1545         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1546 }
1547 
1548 /* rlwinm & rlwinm. */
gen_rlwinm(DisasContext * ctx)1549 static void gen_rlwinm(DisasContext *ctx)
1550 {
1551     uint32_t mb, me, sh;
1552 
1553     sh = SH(ctx->opcode);
1554     mb = MB(ctx->opcode);
1555     me = ME(ctx->opcode);
1556 
1557     if (likely(mb == 0 && me == (31 - sh))) {
1558         if (likely(sh == 0)) {
1559             tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1560         } else {
1561             TCGv t0 = tcg_temp_new();
1562             tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1563             tcg_gen_shli_tl(t0, t0, sh);
1564             tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1565             tcg_temp_free(t0);
1566         }
1567     } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
1568         TCGv t0 = tcg_temp_new();
1569         tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1570         tcg_gen_shri_tl(t0, t0, mb);
1571         tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1572         tcg_temp_free(t0);
1573     } else {
1574         TCGv t0 = tcg_temp_new();
1575 #if defined(TARGET_PPC64)
1576         TCGv_i32 t1 = tcg_temp_new_i32();
1577         tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1578         tcg_gen_rotli_i32(t1, t1, sh);
1579         tcg_gen_extu_i32_i64(t0, t1);
1580         tcg_temp_free_i32(t1);
1581 #else
1582         tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1583 #endif
1584 #if defined(TARGET_PPC64)
1585         mb += 32;
1586         me += 32;
1587 #endif
1588         tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1589         tcg_temp_free(t0);
1590     }
1591     if (unlikely(Rc(ctx->opcode) != 0))
1592         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1593 }
1594 
1595 /* rlwnm & rlwnm. */
gen_rlwnm(DisasContext * ctx)1596 static void gen_rlwnm(DisasContext *ctx)
1597 {
1598     uint32_t mb, me;
1599     TCGv t0;
1600 #if defined(TARGET_PPC64)
1601     TCGv_i32 t1, t2;
1602 #endif
1603 
1604     mb = MB(ctx->opcode);
1605     me = ME(ctx->opcode);
1606     t0 = tcg_temp_new();
1607     tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1608 #if defined(TARGET_PPC64)
1609     t1 = tcg_temp_new_i32();
1610     t2 = tcg_temp_new_i32();
1611     tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1612     tcg_gen_trunc_i64_i32(t2, t0);
1613     tcg_gen_rotl_i32(t1, t1, t2);
1614     tcg_gen_extu_i32_i64(t0, t1);
1615     tcg_temp_free_i32(t1);
1616     tcg_temp_free_i32(t2);
1617 #else
1618     tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1619 #endif
1620     if (unlikely(mb != 0 || me != 31)) {
1621 #if defined(TARGET_PPC64)
1622         mb += 32;
1623         me += 32;
1624 #endif
1625         tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1626     } else {
1627         tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1628     }
1629     tcg_temp_free(t0);
1630     if (unlikely(Rc(ctx->opcode) != 0))
1631         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1632 }
1633 
1634 #if defined(TARGET_PPC64)
1635 #define GEN_PPC64_R2(name, opc1, opc2)                                        \
1636 static void glue(gen_, name##0)(DisasContext *ctx)                            \
1637 {                                                                             \
1638     gen_##name(ctx, 0);                                                       \
1639 }                                                                             \
1640                                                                               \
1641 static void glue(gen_, name##1)(DisasContext *ctx)                            \
1642 {                                                                             \
1643     gen_##name(ctx, 1);                                                       \
1644 }
1645 #define GEN_PPC64_R4(name, opc1, opc2)                                        \
1646 static void glue(gen_, name##0)(DisasContext *ctx)                            \
1647 {                                                                             \
1648     gen_##name(ctx, 0, 0);                                                    \
1649 }                                                                             \
1650                                                                               \
1651 static void glue(gen_, name##1)(DisasContext *ctx)                            \
1652 {                                                                             \
1653     gen_##name(ctx, 0, 1);                                                    \
1654 }                                                                             \
1655                                                                               \
1656 static void glue(gen_, name##2)(DisasContext *ctx)                            \
1657 {                                                                             \
1658     gen_##name(ctx, 1, 0);                                                    \
1659 }                                                                             \
1660                                                                               \
1661 static void glue(gen_, name##3)(DisasContext *ctx)                            \
1662 {                                                                             \
1663     gen_##name(ctx, 1, 1);                                                    \
1664 }
1665 
gen_rldinm(DisasContext * ctx,uint32_t mb,uint32_t me,uint32_t sh)1666 static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
1667                               uint32_t sh)
1668 {
1669     if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1670         tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1671     } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1672         tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1673     } else {
1674         TCGv t0 = tcg_temp_new();
1675         tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1676         if (likely(mb == 0 && me == 63)) {
1677             tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1678         } else {
1679             tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1680         }
1681         tcg_temp_free(t0);
1682     }
1683     if (unlikely(Rc(ctx->opcode) != 0))
1684         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1685 }
1686 /* rldicl - rldicl. */
gen_rldicl(DisasContext * ctx,int mbn,int shn)1687 static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1688 {
1689     uint32_t sh, mb;
1690 
1691     sh = SH(ctx->opcode) | (shn << 5);
1692     mb = MB(ctx->opcode) | (mbn << 5);
1693     gen_rldinm(ctx, mb, 63, sh);
1694 }
1695 GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1696 /* rldicr - rldicr. */
gen_rldicr(DisasContext * ctx,int men,int shn)1697 static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1698 {
1699     uint32_t sh, me;
1700 
1701     sh = SH(ctx->opcode) | (shn << 5);
1702     me = MB(ctx->opcode) | (men << 5);
1703     gen_rldinm(ctx, 0, me, sh);
1704 }
1705 GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1706 /* rldic - rldic. */
gen_rldic(DisasContext * ctx,int mbn,int shn)1707 static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1708 {
1709     uint32_t sh, mb;
1710 
1711     sh = SH(ctx->opcode) | (shn << 5);
1712     mb = MB(ctx->opcode) | (mbn << 5);
1713     gen_rldinm(ctx, mb, 63 - sh, sh);
1714 }
1715 GEN_PPC64_R4(rldic, 0x1E, 0x04);
1716 
gen_rldnm(DisasContext * ctx,uint32_t mb,uint32_t me)1717 static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
1718 {
1719     TCGv t0;
1720 
1721     mb = MB(ctx->opcode);
1722     me = ME(ctx->opcode);
1723     t0 = tcg_temp_new();
1724     tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1725     tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1726     if (unlikely(mb != 0 || me != 63)) {
1727         tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1728     } else {
1729         tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1730     }
1731     tcg_temp_free(t0);
1732     if (unlikely(Rc(ctx->opcode) != 0))
1733         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1734 }
1735 
1736 /* rldcl - rldcl. */
gen_rldcl(DisasContext * ctx,int mbn)1737 static inline void gen_rldcl(DisasContext *ctx, int mbn)
1738 {
1739     uint32_t mb;
1740 
1741     mb = MB(ctx->opcode) | (mbn << 5);
1742     gen_rldnm(ctx, mb, 63);
1743 }
1744 GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1745 /* rldcr - rldcr. */
gen_rldcr(DisasContext * ctx,int men)1746 static inline void gen_rldcr(DisasContext *ctx, int men)
1747 {
1748     uint32_t me;
1749 
1750     me = MB(ctx->opcode) | (men << 5);
1751     gen_rldnm(ctx, 0, me);
1752 }
1753 GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1754 /* rldimi - rldimi. */
gen_rldimi(DisasContext * ctx,int mbn,int shn)1755 static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1756 {
1757     uint32_t sh, mb, me;
1758 
1759     sh = SH(ctx->opcode) | (shn << 5);
1760     mb = MB(ctx->opcode) | (mbn << 5);
1761     me = 63 - sh;
1762     if (unlikely(sh == 0 && mb == 0)) {
1763         tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1764     } else {
1765         TCGv t0, t1;
1766         target_ulong mask;
1767 
1768         t0 = tcg_temp_new();
1769         tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1770         t1 = tcg_temp_new();
1771         mask = MASK(mb, me);
1772         tcg_gen_andi_tl(t0, t0, mask);
1773         tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1774         tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1775         tcg_temp_free(t0);
1776         tcg_temp_free(t1);
1777     }
1778     if (unlikely(Rc(ctx->opcode) != 0))
1779         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1780 }
1781 GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1782 #endif
1783 
1784 /***                             Integer shift                             ***/
1785 
1786 /* slw & slw. */
gen_slw(DisasContext * ctx)1787 static void gen_slw(DisasContext *ctx)
1788 {
1789     TCGv t0, t1;
1790 
1791     t0 = tcg_temp_new();
1792     /* AND rS with a mask that is 0 when rB >= 0x20 */
1793 #if defined(TARGET_PPC64)
1794     tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1795     tcg_gen_sari_tl(t0, t0, 0x3f);
1796 #else
1797     tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1798     tcg_gen_sari_tl(t0, t0, 0x1f);
1799 #endif
1800     tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1801     t1 = tcg_temp_new();
1802     tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1803     tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1804     tcg_temp_free(t1);
1805     tcg_temp_free(t0);
1806     tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1807     if (unlikely(Rc(ctx->opcode) != 0))
1808         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1809 }
1810 
1811 /* sraw & sraw. */
gen_sraw(DisasContext * ctx)1812 static void gen_sraw(DisasContext *ctx)
1813 {
1814     gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
1815                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1816     if (unlikely(Rc(ctx->opcode) != 0))
1817         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1818 }
1819 
1820 /* srawi & srawi. */
gen_srawi(DisasContext * ctx)1821 static void gen_srawi(DisasContext *ctx)
1822 {
1823     int sh = SH(ctx->opcode);
1824     if (sh != 0) {
1825         int l1, l2;
1826         TCGv t0;
1827         l1 = gen_new_label();
1828         l2 = gen_new_label();
1829         t0 = tcg_temp_local_new();
1830         tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1831         tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
1832         tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1833         tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1834         tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1835         tcg_gen_br(l2);
1836         gen_set_label(l1);
1837         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1838         gen_set_label(l2);
1839         tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1840         tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
1841         tcg_temp_free(t0);
1842     } else {
1843         tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1844         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1845     }
1846     if (unlikely(Rc(ctx->opcode) != 0))
1847         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1848 }
1849 
1850 /* srw & srw. */
gen_srw(DisasContext * ctx)1851 static void gen_srw(DisasContext *ctx)
1852 {
1853     TCGv t0, t1;
1854 
1855     t0 = tcg_temp_new();
1856     /* AND rS with a mask that is 0 when rB >= 0x20 */
1857 #if defined(TARGET_PPC64)
1858     tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1859     tcg_gen_sari_tl(t0, t0, 0x3f);
1860 #else
1861     tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1862     tcg_gen_sari_tl(t0, t0, 0x1f);
1863 #endif
1864     tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1865     tcg_gen_ext32u_tl(t0, t0);
1866     t1 = tcg_temp_new();
1867     tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1868     tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1869     tcg_temp_free(t1);
1870     tcg_temp_free(t0);
1871     if (unlikely(Rc(ctx->opcode) != 0))
1872         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1873 }
1874 
1875 #if defined(TARGET_PPC64)
1876 /* sld & sld. */
gen_sld(DisasContext * ctx)1877 static void gen_sld(DisasContext *ctx)
1878 {
1879     TCGv t0, t1;
1880 
1881     t0 = tcg_temp_new();
1882     /* AND rS with a mask that is 0 when rB >= 0x40 */
1883     tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1884     tcg_gen_sari_tl(t0, t0, 0x3f);
1885     tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1886     t1 = tcg_temp_new();
1887     tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1888     tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1889     tcg_temp_free(t1);
1890     tcg_temp_free(t0);
1891     if (unlikely(Rc(ctx->opcode) != 0))
1892         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1893 }
1894 
1895 /* srad & srad. */
gen_srad(DisasContext * ctx)1896 static void gen_srad(DisasContext *ctx)
1897 {
1898     gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
1899                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1900     if (unlikely(Rc(ctx->opcode) != 0))
1901         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1902 }
1903 /* sradi & sradi. */
gen_sradi(DisasContext * ctx,int n)1904 static inline void gen_sradi(DisasContext *ctx, int n)
1905 {
1906     int sh = SH(ctx->opcode) + (n << 5);
1907     if (sh != 0) {
1908         int l1, l2;
1909         TCGv t0;
1910         l1 = gen_new_label();
1911         l2 = gen_new_label();
1912         t0 = tcg_temp_local_new();
1913         tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
1914         tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1915         tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1916         tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1917         tcg_gen_br(l2);
1918         gen_set_label(l1);
1919         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1920         gen_set_label(l2);
1921         tcg_temp_free(t0);
1922         tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1923     } else {
1924         tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1925         tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1926     }
1927     if (unlikely(Rc(ctx->opcode) != 0))
1928         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1929 }
1930 
gen_sradi0(DisasContext * ctx)1931 static void gen_sradi0(DisasContext *ctx)
1932 {
1933     gen_sradi(ctx, 0);
1934 }
1935 
gen_sradi1(DisasContext * ctx)1936 static void gen_sradi1(DisasContext *ctx)
1937 {
1938     gen_sradi(ctx, 1);
1939 }
1940 
1941 /* srd & srd. */
gen_srd(DisasContext * ctx)1942 static void gen_srd(DisasContext *ctx)
1943 {
1944     TCGv t0, t1;
1945 
1946     t0 = tcg_temp_new();
1947     /* AND rS with a mask that is 0 when rB >= 0x40 */
1948     tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1949     tcg_gen_sari_tl(t0, t0, 0x3f);
1950     tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1951     t1 = tcg_temp_new();
1952     tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1953     tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1954     tcg_temp_free(t1);
1955     tcg_temp_free(t0);
1956     if (unlikely(Rc(ctx->opcode) != 0))
1957         gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1958 }
1959 #endif
1960 
1961 /***                       Floating-Point arithmetic                       ***/
1962 #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
1963 static void gen_f##name(DisasContext *ctx)                                    \
1964 {                                                                             \
1965     if (unlikely(!ctx->fpu_enabled)) {                                        \
1966         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
1967         return;                                                               \
1968     }                                                                         \
1969     /* NIP cannot be restored if the memory exception comes from an helper */ \
1970     gen_update_nip(ctx, ctx->nip - 4);                                        \
1971     gen_reset_fpstatus();                                                     \
1972     gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
1973                      cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
1974     if (isfloat) {                                                            \
1975         gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
1976     }                                                                         \
1977     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
1978                      Rc(ctx->opcode) != 0);                                   \
1979 }
1980 
1981 #define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
1982 _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
1983 _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1984 
1985 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
1986 static void gen_f##name(DisasContext *ctx)                                    \
1987 {                                                                             \
1988     if (unlikely(!ctx->fpu_enabled)) {                                        \
1989         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
1990         return;                                                               \
1991     }                                                                         \
1992     /* NIP cannot be restored if the memory exception comes from an helper */ \
1993     gen_update_nip(ctx, ctx->nip - 4);                                        \
1994     gen_reset_fpstatus();                                                     \
1995     gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
1996                      cpu_fpr[rB(ctx->opcode)]);                               \
1997     if (isfloat) {                                                            \
1998         gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
1999     }                                                                         \
2000     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2001                      set_fprf, Rc(ctx->opcode) != 0);                         \
2002 }
2003 #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
2004 _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2005 _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2006 
2007 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2008 static void gen_f##name(DisasContext *ctx)                                    \
2009 {                                                                             \
2010     if (unlikely(!ctx->fpu_enabled)) {                                        \
2011         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2012         return;                                                               \
2013     }                                                                         \
2014     /* NIP cannot be restored if the memory exception comes from an helper */ \
2015     gen_update_nip(ctx, ctx->nip - 4);                                        \
2016     gen_reset_fpstatus();                                                     \
2017     gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2018                        cpu_fpr[rC(ctx->opcode)]);                             \
2019     if (isfloat) {                                                            \
2020         gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2021     }                                                                         \
2022     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2023                      set_fprf, Rc(ctx->opcode) != 0);                         \
2024 }
2025 #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
2026 _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2027 _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2028 
2029 #define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2030 static void gen_f##name(DisasContext *ctx)                                    \
2031 {                                                                             \
2032     if (unlikely(!ctx->fpu_enabled)) {                                        \
2033         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2034         return;                                                               \
2035     }                                                                         \
2036     /* NIP cannot be restored if the memory exception comes from an helper */ \
2037     gen_update_nip(ctx, ctx->nip - 4);                                        \
2038     gen_reset_fpstatus();                                                     \
2039     gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2040     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2041                      set_fprf, Rc(ctx->opcode) != 0);                         \
2042 }
2043 
2044 #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2045 static void gen_f##name(DisasContext *ctx)                                    \
2046 {                                                                             \
2047     if (unlikely(!ctx->fpu_enabled)) {                                        \
2048         gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2049         return;                                                               \
2050     }                                                                         \
2051     /* NIP cannot be restored if the memory exception comes from an helper */ \
2052     gen_update_nip(ctx, ctx->nip - 4);                                        \
2053     gen_reset_fpstatus();                                                     \
2054     gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2055     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2056                      set_fprf, Rc(ctx->opcode) != 0);                         \
2057 }
2058 
2059 /* fadd - fadds */
2060 GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2061 /* fdiv - fdivs */
2062 GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2063 /* fmul - fmuls */
2064 GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2065 
2066 /* fre */
2067 GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2068 
2069 /* fres */
2070 GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
2071 
2072 /* frsqrte */
2073 GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2074 
2075 /* frsqrtes */
gen_frsqrtes(DisasContext * ctx)2076 static void gen_frsqrtes(DisasContext *ctx)
2077 {
2078     if (unlikely(!ctx->fpu_enabled)) {
2079         gen_exception(ctx, POWERPC_EXCP_FPU);
2080         return;
2081     }
2082     /* NIP cannot be restored if the memory exception comes from an helper */
2083     gen_update_nip(ctx, ctx->nip - 4);
2084     gen_reset_fpstatus();
2085     gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2086     gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2087     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2088 }
2089 
2090 /* fsel */
2091 _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2092 /* fsub - fsubs */
2093 GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
2094 /* Optional: */
2095 
2096 /* fsqrt */
gen_fsqrt(DisasContext * ctx)2097 static void gen_fsqrt(DisasContext *ctx)
2098 {
2099     if (unlikely(!ctx->fpu_enabled)) {
2100         gen_exception(ctx, POWERPC_EXCP_FPU);
2101         return;
2102     }
2103     /* NIP cannot be restored if the memory exception comes from an helper */
2104     gen_update_nip(ctx, ctx->nip - 4);
2105     gen_reset_fpstatus();
2106     gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2107     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2108 }
2109 
gen_fsqrts(DisasContext * ctx)2110 static void gen_fsqrts(DisasContext *ctx)
2111 {
2112     if (unlikely(!ctx->fpu_enabled)) {
2113         gen_exception(ctx, POWERPC_EXCP_FPU);
2114         return;
2115     }
2116     /* NIP cannot be restored if the memory exception comes from an helper */
2117     gen_update_nip(ctx, ctx->nip - 4);
2118     gen_reset_fpstatus();
2119     gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2120     gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2121     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2122 }
2123 
2124 /***                     Floating-Point multiply-and-add                   ***/
2125 /* fmadd - fmadds */
2126 GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2127 /* fmsub - fmsubs */
2128 GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2129 /* fnmadd - fnmadds */
2130 GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2131 /* fnmsub - fnmsubs */
2132 GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
2133 
2134 /***                     Floating-Point round & convert                    ***/
2135 /* fctiw */
2136 GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
2137 /* fctiwz */
2138 GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
2139 /* frsp */
2140 GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2141 #if defined(TARGET_PPC64)
2142 /* fcfid */
2143 GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
2144 /* fctid */
2145 GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
2146 /* fctidz */
2147 GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
2148 #endif
2149 
2150 /* frin */
2151 GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2152 /* friz */
2153 GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2154 /* frip */
2155 GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2156 /* frim */
2157 GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2158 
2159 /***                         Floating-Point compare                        ***/
2160 
2161 /* fcmpo */
gen_fcmpo(DisasContext * ctx)2162 static void gen_fcmpo(DisasContext *ctx)
2163 {
2164     TCGv_i32 crf;
2165     if (unlikely(!ctx->fpu_enabled)) {
2166         gen_exception(ctx, POWERPC_EXCP_FPU);
2167         return;
2168     }
2169     /* NIP cannot be restored if the memory exception comes from an helper */
2170     gen_update_nip(ctx, ctx->nip - 4);
2171     gen_reset_fpstatus();
2172     crf = tcg_const_i32(crfD(ctx->opcode));
2173     gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2174     tcg_temp_free_i32(crf);
2175     gen_helper_float_check_status();
2176 }
2177 
2178 /* fcmpu */
gen_fcmpu(DisasContext * ctx)2179 static void gen_fcmpu(DisasContext *ctx)
2180 {
2181     TCGv_i32 crf;
2182     if (unlikely(!ctx->fpu_enabled)) {
2183         gen_exception(ctx, POWERPC_EXCP_FPU);
2184         return;
2185     }
2186     /* NIP cannot be restored if the memory exception comes from an helper */
2187     gen_update_nip(ctx, ctx->nip - 4);
2188     gen_reset_fpstatus();
2189     crf = tcg_const_i32(crfD(ctx->opcode));
2190     gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2191     tcg_temp_free_i32(crf);
2192     gen_helper_float_check_status();
2193 }
2194 
2195 /***                         Floating-point move                           ***/
2196 /* fabs */
2197 /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2198 GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2199 
2200 /* fmr  - fmr. */
2201 /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
gen_fmr(DisasContext * ctx)2202 static void gen_fmr(DisasContext *ctx)
2203 {
2204     if (unlikely(!ctx->fpu_enabled)) {
2205         gen_exception(ctx, POWERPC_EXCP_FPU);
2206         return;
2207     }
2208     tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2209     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2210 }
2211 
2212 /* fnabs */
2213 /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2214 GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2215 /* fneg */
2216 /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2217 GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2218 
2219 /***                  Floating-Point status & ctrl register                ***/
2220 
2221 /* mcrfs */
gen_mcrfs(DisasContext * ctx)2222 static void gen_mcrfs(DisasContext *ctx)
2223 {
2224     int bfa;
2225 
2226     if (unlikely(!ctx->fpu_enabled)) {
2227         gen_exception(ctx, POWERPC_EXCP_FPU);
2228         return;
2229     }
2230     bfa = 4 * (7 - crfS(ctx->opcode));
2231     tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2232     tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2233     tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
2234 }
2235 
2236 /* mffs */
gen_mffs(DisasContext * ctx)2237 static void gen_mffs(DisasContext *ctx)
2238 {
2239     if (unlikely(!ctx->fpu_enabled)) {
2240         gen_exception(ctx, POWERPC_EXCP_FPU);
2241         return;
2242     }
2243     gen_reset_fpstatus();
2244     tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2245     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2246 }
2247 
2248 /* mtfsb0 */
gen_mtfsb0(DisasContext * ctx)2249 static void gen_mtfsb0(DisasContext *ctx)
2250 {
2251     uint8_t crb;
2252 
2253     if (unlikely(!ctx->fpu_enabled)) {
2254         gen_exception(ctx, POWERPC_EXCP_FPU);
2255         return;
2256     }
2257     crb = 31 - crbD(ctx->opcode);
2258     gen_reset_fpstatus();
2259     if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2260         TCGv_i32 t0;
2261         /* NIP cannot be restored if the memory exception comes from an helper */
2262         gen_update_nip(ctx, ctx->nip - 4);
2263         t0 = tcg_const_i32(crb);
2264         gen_helper_fpscr_clrbit(t0);
2265         tcg_temp_free_i32(t0);
2266     }
2267     if (unlikely(Rc(ctx->opcode) != 0)) {
2268         tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2269     }
2270 }
2271 
2272 /* mtfsb1 */
gen_mtfsb1(DisasContext * ctx)2273 static void gen_mtfsb1(DisasContext *ctx)
2274 {
2275     uint8_t crb;
2276 
2277     if (unlikely(!ctx->fpu_enabled)) {
2278         gen_exception(ctx, POWERPC_EXCP_FPU);
2279         return;
2280     }
2281     crb = 31 - crbD(ctx->opcode);
2282     gen_reset_fpstatus();
2283     /* XXX: we pretend we can only do IEEE floating-point computations */
2284     if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2285         TCGv_i32 t0;
2286         /* NIP cannot be restored if the memory exception comes from an helper */
2287         gen_update_nip(ctx, ctx->nip - 4);
2288         t0 = tcg_const_i32(crb);
2289         gen_helper_fpscr_setbit(t0);
2290         tcg_temp_free_i32(t0);
2291     }
2292     if (unlikely(Rc(ctx->opcode) != 0)) {
2293         tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2294     }
2295     /* We can raise a differed exception */
2296     gen_helper_float_check_status();
2297 }
2298 
2299 /* mtfsf */
gen_mtfsf(DisasContext * ctx)2300 static void gen_mtfsf(DisasContext *ctx)
2301 {
2302     TCGv_i32 t0;
2303     int L = ctx->opcode & 0x02000000;
2304 
2305     if (unlikely(!ctx->fpu_enabled)) {
2306         gen_exception(ctx, POWERPC_EXCP_FPU);
2307         return;
2308     }
2309     /* NIP cannot be restored if the memory exception comes from an helper */
2310     gen_update_nip(ctx, ctx->nip - 4);
2311     gen_reset_fpstatus();
2312     if (L)
2313         t0 = tcg_const_i32(0xff);
2314     else
2315         t0 = tcg_const_i32(FM(ctx->opcode));
2316     gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2317     tcg_temp_free_i32(t0);
2318     if (unlikely(Rc(ctx->opcode) != 0)) {
2319         tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2320     }
2321     /* We can raise a differed exception */
2322     gen_helper_float_check_status();
2323 }
2324 
2325 /* mtfsfi */
gen_mtfsfi(DisasContext * ctx)2326 static void gen_mtfsfi(DisasContext *ctx)
2327 {
2328     int bf, sh;
2329     TCGv_i64 t0;
2330     TCGv_i32 t1;
2331 
2332     if (unlikely(!ctx->fpu_enabled)) {
2333         gen_exception(ctx, POWERPC_EXCP_FPU);
2334         return;
2335     }
2336     bf = crbD(ctx->opcode) >> 2;
2337     sh = 7 - bf;
2338     /* NIP cannot be restored if the memory exception comes from an helper */
2339     gen_update_nip(ctx, ctx->nip - 4);
2340     gen_reset_fpstatus();
2341     t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
2342     t1 = tcg_const_i32(1 << sh);
2343     gen_helper_store_fpscr(t0, t1);
2344     tcg_temp_free_i64(t0);
2345     tcg_temp_free_i32(t1);
2346     if (unlikely(Rc(ctx->opcode) != 0)) {
2347         tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2348     }
2349     /* We can raise a differed exception */
2350     gen_helper_float_check_status();
2351 }
2352 
2353 /***                           Addressing modes                            ***/
2354 /* Register indirect with immediate index : EA = (rA|0) + SIMM */
gen_addr_imm_index(DisasContext * ctx,TCGv EA,target_long maskl)2355 static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2356                                       target_long maskl)
2357 {
2358     target_long simm = SIMM(ctx->opcode);
2359 
2360     simm &= ~maskl;
2361     if (rA(ctx->opcode) == 0) {
2362 #if defined(TARGET_PPC64)
2363         if (!ctx->sf_mode) {
2364             tcg_gen_movi_tl(EA, (uint32_t)simm);
2365         } else
2366 #endif
2367         tcg_gen_movi_tl(EA, simm);
2368     } else if (likely(simm != 0)) {
2369         tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2370 #if defined(TARGET_PPC64)
2371         if (!ctx->sf_mode) {
2372             tcg_gen_ext32u_tl(EA, EA);
2373         }
2374 #endif
2375     } else {
2376 #if defined(TARGET_PPC64)
2377         if (!ctx->sf_mode) {
2378             tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2379         } else
2380 #endif
2381         tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2382     }
2383 }
2384 
gen_addr_reg_index(DisasContext * ctx,TCGv EA)2385 static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2386 {
2387     if (rA(ctx->opcode) == 0) {
2388 #if defined(TARGET_PPC64)
2389         if (!ctx->sf_mode) {
2390             tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2391         } else
2392 #endif
2393         tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2394     } else {
2395         tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2396 #if defined(TARGET_PPC64)
2397         if (!ctx->sf_mode) {
2398             tcg_gen_ext32u_tl(EA, EA);
2399         }
2400 #endif
2401     }
2402 }
2403 
gen_addr_register(DisasContext * ctx,TCGv EA)2404 static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2405 {
2406     if (rA(ctx->opcode) == 0) {
2407         tcg_gen_movi_tl(EA, 0);
2408     } else {
2409 #if defined(TARGET_PPC64)
2410         if (!ctx->sf_mode) {
2411             tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2412         } else
2413 #endif
2414             tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2415     }
2416 }
2417 
gen_addr_add(DisasContext * ctx,TCGv ret,TCGv arg1,target_long val)2418 static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2419                                 target_long val)
2420 {
2421     tcg_gen_addi_tl(ret, arg1, val);
2422 #if defined(TARGET_PPC64)
2423     if (!ctx->sf_mode) {
2424         tcg_gen_ext32u_tl(ret, ret);
2425     }
2426 #endif
2427 }
2428 
gen_check_align(DisasContext * ctx,TCGv EA,int mask)2429 static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2430 {
2431     int l1 = gen_new_label();
2432     TCGv t0 = tcg_temp_new();
2433     TCGv_i32 t1, t2;
2434     /* NIP cannot be restored if the memory exception comes from an helper */