|
|
1.1 root 1: /*
2: * PowerPC emulation for qemu: main translation routines.
1.1.1.5 root 3: *
4: * Copyright (c) 2003-2007 Jocelyn Mayer
1.1 root 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
1.1.1.7 root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 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"
1.1.1.6 root 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
1.1 root 39:
1.1.1.5 root 40: /* Include definitions for instructions classes and implementations flags */
1.1 root 41: //#define PPC_DEBUG_DISAS
1.1.1.5 root 42: //#define DO_PPC_STATISTICS
1.1 root 43:
1.1.1.6 root 44: #ifdef PPC_DEBUG_DISAS
45: # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
1.1.1.2 root 46: #else
1.1.1.6 root 47: # define LOG_DISAS(...) do { } while (0)
1.1.1.2 root 48: #endif
1.1.1.6 root 49: /*****************************************************************************/
50: /* Code translation helpers */
1.1.1.2 root 51:
1.1.1.6 root 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 */
1.1.1.5 root 57: #endif
1.1.1.6 root 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;
1.1 root 76:
1.1.1.6 root 77: #include "gen-icount.h"
1.1 root 78:
1.1.1.6 root 79: void ppc_translate_init(void)
1.1.1.5 root 80: {
1.1.1.6 root 81: int i;
82: char* p;
1.1.1.7 root 83: size_t cpu_reg_names_size;
1.1.1.6 root 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;
1.1.1.7 root 92: cpu_reg_names_size = sizeof(cpu_reg_names);
1.1.1.6 root 93:
94: for (i = 0; i < 8; i++) {
1.1.1.7 root 95: snprintf(p, cpu_reg_names_size, "crf%d", i);
1.1.1.6 root 96: cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
97: offsetof(CPUState, crf[i]), p);
98: p += 5;
1.1.1.7 root 99: cpu_reg_names_size -= 5;
1.1.1.6 root 100: }
101:
102: for (i = 0; i < 32; i++) {
1.1.1.7 root 103: snprintf(p, cpu_reg_names_size, "r%d", i);
1.1.1.6 root 104: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
105: offsetof(CPUState, gpr[i]), p);
106: p += (i < 10) ? 3 : 4;
1.1.1.7 root 107: cpu_reg_names_size -= (i < 10) ? 3 : 4;
1.1.1.6 root 108: #if !defined(TARGET_PPC64)
1.1.1.7 root 109: snprintf(p, cpu_reg_names_size, "r%dH", i);
1.1.1.6 root 110: cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
111: offsetof(CPUState, gprh[i]), p);
112: p += (i < 10) ? 4 : 5;
1.1.1.7 root 113: cpu_reg_names_size -= (i < 10) ? 4 : 5;
1.1.1.5 root 114: #endif
115:
1.1.1.7 root 116: snprintf(p, cpu_reg_names_size, "fp%d", i);
1.1.1.6 root 117: cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
118: offsetof(CPUState, fpr[i]), p);
119: p += (i < 10) ? 4 : 5;
1.1.1.7 root 120: cpu_reg_names_size -= (i < 10) ? 4 : 5;
1.1.1.6 root 121:
1.1.1.7 root 122: snprintf(p, cpu_reg_names_size, "avr%dH", i);
1.1.1.8 ! root 123: #ifdef HOST_WORDS_BIGENDIAN
1.1.1.6 root 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);
1.1.1.5 root 129: #endif
1.1.1.6 root 130: p += (i < 10) ? 6 : 7;
1.1.1.7 root 131: cpu_reg_names_size -= (i < 10) ? 6 : 7;
1.1.1.5 root 132:
1.1.1.7 root 133: snprintf(p, cpu_reg_names_size, "avr%dL", i);
1.1.1.8 ! root 134: #ifdef HOST_WORDS_BIGENDIAN
1.1.1.6 root 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);
1.1.1.5 root 140: #endif
1.1.1.6 root 141: p += (i < 10) ? 6 : 7;
1.1.1.7 root 142: cpu_reg_names_size -= (i < 10) ? 6 : 7;
1.1.1.6 root 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,
1.1.1.8 ! root 161: offsetof(CPUState, reserve_addr),
! 162: "reserve_addr");
1.1.1.6 root 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: }
1.1 root 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;
1.1.1.6 root 185: int access_type;
1.1 root 186: /* Translation flags */
1.1.1.6 root 187: int le_mode;
1.1.1.5 root 188: #if defined(TARGET_PPC64)
189: int sf_mode;
190: #endif
1.1 root 191: int fpu_enabled;
1.1.1.5 root 192: int altivec_enabled;
193: int spe_enabled;
1.1 root 194: ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
1.1.1.3 root 195: int singlestep_enabled;
1.1 root 196: } DisasContext;
197:
198: struct opc_handler_t {
199: /* invalid bits */
200: uint32_t inval;
201: /* instruction type */
1.1.1.5 root 202: uint64_t type;
1.1 root 203: /* handler */
204: void (*handler)(DisasContext *ctx);
1.1.1.5 root 205: #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
1.1.1.6 root 206: const char *oname;
1.1.1.5 root 207: #endif
208: #if defined(DO_PPC_STATISTICS)
209: uint64_t count;
210: #endif
1.1 root 211: };
212:
1.1.1.8 ! root 213: static inline void gen_reset_fpstatus(void)
1.1.1.5 root 214: {
215: #ifdef CONFIG_SOFTFLOAT
1.1.1.6 root 216: gen_helper_reset_fpstatus();
1.1.1.5 root 217: #endif
218: }
219:
1.1.1.8 ! root 220: static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
1.1.1.5 root 221: {
1.1.1.6 root 222: TCGv_i32 t0 = tcg_temp_new_i32();
223:
1.1.1.5 root 224: if (set_fprf != 0) {
225: /* This case might be optimized later */
1.1.1.6 root 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();
1.1.1.5 root 232: } else if (unlikely(set_rc)) {
233: /* We always need to compute fpcc */
1.1.1.6 root 234: tcg_gen_movi_i32(t0, 0);
235: gen_helper_compute_fprf(t0, arg, t0);
236: tcg_gen_mov_i32(cpu_crf[1], t0);
1.1.1.5 root 237: }
1.1.1.6 root 238:
239: tcg_temp_free_i32(t0);
1.1.1.5 root 240: }
241:
1.1.1.8 ! root 242: static inline void gen_set_access_type(DisasContext *ctx, int access_type)
1.1.1.5 root 243: {
1.1.1.6 root 244: if (ctx->access_type != access_type) {
245: tcg_gen_movi_i32(cpu_access_type, access_type);
246: ctx->access_type = access_type;
247: }
1.1.1.5 root 248: }
249:
1.1.1.8 ! root 250: static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
1.1.1.5 root 251: {
252: #if defined(TARGET_PPC64)
253: if (ctx->sf_mode)
1.1.1.6 root 254: tcg_gen_movi_tl(cpu_nip, nip);
1.1.1.5 root 255: else
256: #endif
1.1.1.6 root 257: tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
1.1.1.5 root 258: }
259:
1.1.1.8 ! root 260: static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
1.1.1.6 root 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: }
1.1.1.5 root 273:
1.1.1.8 ! root 274: static inline void gen_exception(DisasContext *ctx, uint32_t excp)
1.1.1.6 root 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: }
1.1.1.5 root 285:
1.1.1.8 ! root 286: static inline void gen_debug_exception(DisasContext *ctx)
1.1.1.6 root 287: {
288: TCGv_i32 t0;
1.1 root 289:
1.1.1.6 root 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: }
1.1 root 296:
1.1.1.8 ! root 297: static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
1.1.1.6 root 298: {
299: gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
300: }
1.1 root 301:
1.1.1.2 root 302: /* Stop translation */
1.1.1.8 ! root 303: static inline void gen_stop_exception(DisasContext *ctx)
1.1 root 304: {
1.1.1.5 root 305: gen_update_nip(ctx, ctx->nip);
306: ctx->exception = POWERPC_EXCP_STOP;
1.1 root 307: }
308:
1.1.1.2 root 309: /* No need to update nip here, as execution flow will change */
1.1.1.8 ! root 310: static inline void gen_sync_exception(DisasContext *ctx)
1.1 root 311: {
1.1.1.5 root 312: ctx->exception = POWERPC_EXCP_SYNC;
1.1 root 313: }
314:
315: #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
1.1.1.7 root 316: GEN_OPCODE(name, opc1, opc2, opc3, inval, type)
1.1 root 317:
1.1.1.5 root 318: #define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
1.1.1.7 root 319: GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type)
1.1.1.5 root 320:
1.1 root 321: typedef struct opcode_t {
322: unsigned char opc1, opc2, opc3;
1.1.1.6 root 323: #if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
1.1 root 324: unsigned char pad[5];
325: #else
326: unsigned char pad[1];
327: #endif
328: opc_handler_t handler;
1.1.1.6 root 329: const char *oname;
1.1 root 330: } opcode_t;
331:
1.1.1.5 root 332: /*****************************************************************************/
1.1 root 333: /*** Instruction decoding ***/
334: #define EXTRACT_HELPER(name, shift, nb) \
1.1.1.8 ! root 335: static inline uint32_t name(uint32_t opcode) \
1.1 root 336: { \
337: return (opcode >> (shift)) & ((1 << (nb)) - 1); \
338: }
339:
340: #define EXTRACT_SHELPER(name, shift, nb) \
1.1.1.8 ! root 341: static inline int32_t name(uint32_t opcode) \
1.1 root 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);
1.1.1.8 ! root 372: static inline uint32_t SPR(uint32_t opcode)
1.1 root 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);
1.1.1.6 root 384: /* 5 bits signed immediate value */
385: EXTRACT_HELPER(SIMM5, 16, 5);
386: /* 5 bits signed immediate value */
387: EXTRACT_HELPER(UIMM5, 16, 5);
1.1 root 388: /* Bit count */
389: EXTRACT_HELPER(NB, 11, 5);
390: /* Shift count */
391: EXTRACT_HELPER(SH, 11, 5);
1.1.1.6 root 392: /* Vector shift count */
393: EXTRACT_HELPER(VSH, 6, 4);
1.1 root 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);
1.1.1.6 root 404: EXTRACT_HELPER(FPIMM, 12, 4);
1.1 root 405:
406: /*** Jump target decoding ***/
407: /* Displacement */
408: EXTRACT_SHELPER(d, 0, 16);
409: /* Immediate address */
1.1.1.8 ! root 410: static inline target_ulong LI(uint32_t opcode)
1.1 root 411: {
412: return (opcode >> 0) & 0x03FFFFFC;
413: }
414:
1.1.1.8 ! root 415: static inline uint32_t BD(uint32_t opcode)
1.1 root 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 */
1.1.1.8 ! root 428: static inline target_ulong MASK(uint32_t start, uint32_t end)
1.1 root 429: {
1.1.1.5 root 430: target_ulong ret;
1.1 root 431:
1.1.1.5 root 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: }
1.1 root 451:
452: return ret;
453: }
454:
1.1.1.5 root 455: /*****************************************************************************/
456: /* PowerPC instructions table */
1.1 root 457:
1.1.1.5 root 458: #if defined(DO_PPC_STATISTICS)
459: #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
1.1.1.7 root 460: { \
1.1.1.5 root 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) \
1.1.1.7 root 474: { \
1.1.1.5 root 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
1.1 root 488: #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
1.1.1.7 root 489: { \
1.1 root 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: }
1.1.1.5 root 501: #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
1.1.1.7 root 502: { \
1.1.1.5 root 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
1.1 root 515:
1.1.1.6 root 516: /* SPR load/store helpers */
1.1.1.8 ! root 517: static inline void gen_load_spr(TCGv t, int reg)
1.1.1.6 root 518: {
519: tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
520: }
521:
1.1.1.8 ! root 522: static inline void gen_store_spr(int reg, TCGv t)
1.1.1.6 root 523: {
524: tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
525: }
526:
1.1 root 527: /* Invalid instruction */
1.1.1.7 root 528: static void gen_invalid(DisasContext *ctx)
1.1 root 529: {
1.1.1.6 root 530: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1 root 531: }
532:
533: static opc_handler_t invalid_handler = {
534: .inval = 0xFFFFFFFF,
535: .type = PPC_NONE,
536: .handler = gen_invalid,
537: };
538:
1.1.1.6 root 539: /*** Integer comparison ***/
1.1 root 540:
1.1.1.8 ! root 541: static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
1.1.1.6 root 542: {
543: int l1, l2, l3;
1.1 root 544:
1.1.1.6 root 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);
1.1.1.5 root 567: }
568:
1.1.1.8 ! root 569: static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
1.1.1.6 root 570: {
571: TCGv t0 = tcg_const_local_tl(arg1);
572: gen_op_cmp(arg0, t0, s, crf);
573: tcg_temp_free(t0);
1.1.1.5 root 574: }
575:
1.1.1.6 root 576: #if defined(TARGET_PPC64)
1.1.1.8 ! root 577: static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
1.1.1.6 root 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);
1.1.1.5 root 592: }
593:
1.1.1.8 ! root 594: static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
1.1.1.6 root 595: {
596: TCGv t0 = tcg_const_local_tl(arg1);
597: gen_op_cmp32(arg0, t0, s, crf);
598: tcg_temp_free(t0);
1.1 root 599: }
1.1.1.5 root 600: #endif
1.1 root 601:
1.1.1.8 ! root 602: static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
1.1.1.5 root 603: {
604: #if defined(TARGET_PPC64)
1.1.1.6 root 605: if (!(ctx->sf_mode))
606: gen_op_cmpi32(reg, 0, 1, 0);
607: else
1.1.1.5 root 608: #endif
1.1.1.6 root 609: gen_op_cmpi(reg, 0, 1, 0);
1.1.1.5 root 610: }
1.1.1.6 root 611:
612: /* cmp */
1.1.1.7 root 613: static void gen_cmp(DisasContext *ctx)
1.1.1.5 root 614: {
615: #if defined(TARGET_PPC64)
1.1.1.6 root 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
1.1.1.5 root 620: #endif
1.1.1.6 root 621: gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
622: 1, crfD(ctx->opcode));
1.1.1.5 root 623: }
1.1.1.6 root 624:
625: /* cmpi */
1.1.1.7 root 626: static void gen_cmpi(DisasContext *ctx)
1.1.1.5 root 627: {
1.1.1.6 root 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
1.1.1.5 root 633: #endif
1.1.1.6 root 634: gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
635: 1, crfD(ctx->opcode));
1.1.1.5 root 636: }
1.1.1.6 root 637:
638: /* cmpl */
1.1.1.7 root 639: static void gen_cmpl(DisasContext *ctx)
1.1.1.5 root 640: {
1.1.1.6 root 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
1.1.1.5 root 646: #endif
1.1.1.6 root 647: gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
648: 0, crfD(ctx->opcode));
1.1.1.5 root 649: }
1.1.1.6 root 650:
651: /* cmpli */
1.1.1.7 root 652: static void gen_cmpli(DisasContext *ctx)
1.1.1.5 root 653: {
654: #if defined(TARGET_PPC64)
1.1.1.6 root 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));
1.1.1.5 root 662: }
1.1.1.6 root 663:
664: /* isel (PowerPC 2.03 specification) */
1.1.1.7 root 665: static void gen_isel(DisasContext *ctx)
1.1.1.5 root 666: {
1.1.1.6 root 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);
1.1.1.5 root 688: }
1.1.1.6 root 689:
690: /*** Integer arithmetic ***/
691:
1.1.1.8 ! root 692: static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
! 693: TCGv arg1, TCGv arg2, int sub)
1.1.1.5 root 694: {
1.1.1.6 root 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);
1.1.1.5 root 703: #if defined(TARGET_PPC64)
1.1.1.6 root 704: if (!ctx->sf_mode)
705: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 706: #endif
1.1.1.6 root 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);
1.1.1.5 root 723: }
1.1.1.6 root 724:
1.1.1.8 ! root 725: static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
! 726: TCGv arg2, int sub)
1.1.1.5 root 727: {
1.1.1.6 root 728: int l1 = gen_new_label();
729:
1.1.1.5 root 730: #if defined(TARGET_PPC64)
1.1.1.6 root 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: }
1.1.1.5 root 758: }
1.1.1.6 root 759:
760: /* Common add function */
1.1.1.8 ! root 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)
1.1.1.6 root 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);
1.1.1.7 root 778: } else {
779: TCGV_UNUSED(t1);
1.1.1.6 root 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: }
1.1.1.5 root 814: }
1.1.1.6 root 815: /* Add functions with two operands */
816: #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
1.1.1.7 root 817: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 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); \
1.1.1.5 root 822: }
1.1.1.6 root 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) \
1.1.1.7 root 826: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 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); \
1.1.1.5 root 833: }
1.1.1.6 root 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)
1.1 root 850: /* addi */
1.1.1.7 root 851: static void gen_addi(DisasContext *ctx)
1.1 root 852: {
1.1.1.5 root 853: target_long simm = SIMM(ctx->opcode);
1.1 root 854:
855: if (rA(ctx->opcode) == 0) {
1.1.1.5 root 856: /* li case */
1.1.1.6 root 857: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
1.1 root 858: } else {
1.1.1.6 root 859: tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
1.1 root 860: }
861: }
1.1.1.6 root 862: /* addic addic.*/
1.1.1.8 ! root 863: static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
! 864: int compute_Rc0)
1.1 root 865: {
1.1.1.5 root 866: target_long simm = SIMM(ctx->opcode);
867:
1.1.1.6 root 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:
1.1.1.5 root 871: if (likely(simm != 0)) {
1.1.1.6 root 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);
1.1.1.5 root 877: } else {
1.1.1.6 root 878: tcg_gen_mov_tl(ret, arg1);
879: }
880: if (compute_Rc0) {
881: gen_set_Rc0(ctx, ret);
1.1.1.5 root 882: }
1.1 root 883: }
1.1.1.7 root 884:
885: static void gen_addic(DisasContext *ctx)
1.1.1.6 root 886: {
887: gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
888: }
1.1.1.7 root 889:
890: static void gen_addic_(DisasContext *ctx)
1.1 root 891: {
1.1.1.6 root 892: gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1.1 root 893: }
1.1.1.7 root 894:
1.1 root 895: /* addis */
1.1.1.7 root 896: static void gen_addis(DisasContext *ctx)
1.1 root 897: {
1.1.1.5 root 898: target_long simm = SIMM(ctx->opcode);
1.1 root 899:
900: if (rA(ctx->opcode) == 0) {
1.1.1.5 root 901: /* lis case */
1.1.1.6 root 902: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
1.1 root 903: } else {
1.1.1.6 root 904: tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
1.1 root 905: }
906: }
907:
1.1.1.8 ! root 908: static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
! 909: TCGv arg2, int sign, int compute_ov)
1.1.1.6 root 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) \
1.1.1.7 root 950: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 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)
1.1.1.8 ! root 963: static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
! 964: TCGv arg2, int sign, int compute_ov)
1.1.1.6 root 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);
1.1.1.5 root 995: }
1.1.1.6 root 996: #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
1.1.1.7 root 997: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 998: { \
1.1.1.6 root 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); \
1.1 root 1002: }
1.1.1.6 root 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);
1.1.1.5 root 1009: #endif
1.1 root 1010:
1.1.1.6 root 1011: /* mulhw mulhw. */
1.1.1.7 root 1012: static void gen_mulhw(DisasContext *ctx)
1.1 root 1013: {
1.1.1.6 root 1014: TCGv_i64 t0, t1;
1015:
1016: t0 = tcg_temp_new_i64();
1017: t1 = tcg_temp_new_i64();
1.1.1.5 root 1018: #if defined(TARGET_PPC64)
1.1.1.6 root 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);
1.1.1.5 root 1029: #endif
1.1.1.6 root 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)]);
1.1 root 1034: }
1.1.1.7 root 1035:
1.1.1.6 root 1036: /* mulhwu mulhwu. */
1.1.1.7 root 1037: static void gen_mulhwu(DisasContext *ctx)
1.1 root 1038: {
1.1.1.6 root 1039: TCGv_i64 t0, t1;
1040:
1041: t0 = tcg_temp_new_i64();
1042: t1 = tcg_temp_new_i64();
1.1.1.5 root 1043: #if defined(TARGET_PPC64)
1.1.1.6 root 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);
1.1.1.5 root 1054: #endif
1.1.1.6 root 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: }
1.1.1.7 root 1060:
1.1.1.6 root 1061: /* mullw mullw. */
1.1.1.7 root 1062: static void gen_mullw(DisasContext *ctx)
1.1.1.6 root 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)]);
1.1 root 1069: }
1.1.1.7 root 1070:
1.1.1.6 root 1071: /* mullwo mullwo. */
1.1.1.7 root 1072: static void gen_mullwo(DisasContext *ctx)
1.1.1.6 root 1073: {
1074: int l1;
1075: TCGv_i64 t0, t1;
1.1 root 1076:
1.1.1.6 root 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: }
1.1.1.7 root 1105:
1.1.1.6 root 1106: /* mulli */
1.1.1.7 root 1107: static void gen_mulli(DisasContext *ctx)
1.1.1.5 root 1108: {
1.1.1.6 root 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) \
1.1.1.7 root 1114: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 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);
1.1.1.7 root 1125:
1.1.1.6 root 1126: /* mulld mulld. */
1.1.1.7 root 1127: static void gen_mulld(DisasContext *ctx)
1.1.1.6 root 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
1.1.1.5 root 1137:
1.1.1.6 root 1138: /* neg neg. nego nego. */
1.1.1.8 ! root 1139: static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
! 1140: int ov_check)
1.1.1.6 root 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: }
1.1.1.7 root 1170:
1171: static void gen_neg(DisasContext *ctx)
1.1.1.6 root 1172: {
1173: gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1174: }
1.1.1.7 root 1175:
1176: static void gen_nego(DisasContext *ctx)
1.1.1.6 root 1177: {
1178: gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1179: }
1180:
1181: /* Common subf function */
1.1.1.8 ! root 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)
1.1.1.6 root 1185: {
1186: TCGv t0, t1;
1187:
1188: if ((!compute_ca && !compute_ov) ||
1189: (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2))) {
1190: t0 = ret;
1.1.1.5 root 1191: } else {
1.1.1.6 root 1192: t0 = tcg_temp_local_new();
1.1.1.5 root 1193: }
1.1.1.6 root 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);
1.1.1.7 root 1199: } else {
1200: TCGV_UNUSED(t1);
1.1.1.6 root 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) \
1.1.1.7 root 1241: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 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) \
1.1.1.7 root 1250: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 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)
1.1.1.7 root 1273:
1.1.1.6 root 1274: /* subfic */
1.1.1.7 root 1275: static void gen_subfic(DisasContext *ctx)
1.1.1.6 root 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);
1.1.1.5 root 1286: }
1287:
1.1 root 1288: /*** Integer logical ***/
1.1.1.6 root 1289: #define GEN_LOGICAL2(name, tcg_op, opc, type) \
1.1.1.7 root 1290: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 1291: { \
1.1.1.6 root 1292: tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
1293: cpu_gpr[rB(ctx->opcode)]); \
1.1.1.5 root 1294: if (unlikely(Rc(ctx->opcode) != 0)) \
1.1.1.6 root 1295: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
1.1 root 1296: }
1297:
1.1.1.6 root 1298: #define GEN_LOGICAL1(name, tcg_op, opc, type) \
1.1.1.7 root 1299: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 1300: { \
1.1.1.6 root 1301: tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
1.1.1.5 root 1302: if (unlikely(Rc(ctx->opcode) != 0)) \
1.1.1.6 root 1303: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
1.1 root 1304: }
1305:
1306: /* and & and. */
1.1.1.6 root 1307: GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1.1 root 1308: /* andc & andc. */
1.1.1.6 root 1309: GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1.1.1.7 root 1310:
1.1 root 1311: /* andi. */
1.1.1.7 root 1312: static void gen_andi_(DisasContext *ctx)
1.1 root 1313: {
1.1.1.6 root 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)]);
1.1 root 1316: }
1.1.1.7 root 1317:
1.1 root 1318: /* andis. */
1.1.1.7 root 1319: static void gen_andis_(DisasContext *ctx)
1.1 root 1320: {
1.1.1.6 root 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)]);
1.1 root 1323: }
1.1.1.7 root 1324:
1.1 root 1325: /* cntlzw */
1.1.1.7 root 1326: static void gen_cntlzw(DisasContext *ctx)
1.1.1.6 root 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: }
1.1 root 1332: /* eqv & eqv. */
1.1.1.6 root 1333: GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1.1 root 1334: /* extsb & extsb. */
1.1.1.6 root 1335: GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1.1 root 1336: /* extsh & extsh. */
1.1.1.6 root 1337: GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1.1 root 1338: /* nand & nand. */
1.1.1.6 root 1339: GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1.1 root 1340: /* nor & nor. */
1.1.1.6 root 1341: GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1.1.1.7 root 1342:
1.1 root 1343: /* or & or. */
1.1.1.7 root 1344: static void gen_or(DisasContext *ctx)
1.1 root 1345: {
1.1.1.5 root 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) {
1.1.1.6 root 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]);
1.1.1.5 root 1357: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1358: gen_set_Rc0(ctx, cpu_gpr[ra]);
1.1.1.5 root 1359: } else if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 1360: gen_set_Rc0(ctx, cpu_gpr[rs]);
1.1.1.5 root 1361: #if defined(TARGET_PPC64)
1362: } else {
1.1.1.6 root 1363: int prio = 0;
1364:
1.1.1.5 root 1365: switch (rs) {
1366: case 1:
1367: /* Set process priority to low */
1.1.1.6 root 1368: prio = 2;
1.1.1.5 root 1369: break;
1370: case 6:
1371: /* Set process priority to medium-low */
1.1.1.6 root 1372: prio = 3;
1.1.1.5 root 1373: break;
1374: case 2:
1375: /* Set process priority to normal */
1.1.1.6 root 1376: prio = 4;
1.1.1.5 root 1377: break;
1378: #if !defined(CONFIG_USER_ONLY)
1379: case 31:
1.1.1.6 root 1380: if (ctx->mem_idx > 0) {
1.1.1.5 root 1381: /* Set process priority to very low */
1.1.1.6 root 1382: prio = 1;
1.1.1.5 root 1383: }
1384: break;
1385: case 5:
1.1.1.6 root 1386: if (ctx->mem_idx > 0) {
1.1.1.5 root 1387: /* Set process priority to medium-hight */
1.1.1.6 root 1388: prio = 5;
1.1.1.5 root 1389: }
1390: break;
1391: case 3:
1.1.1.6 root 1392: if (ctx->mem_idx > 0) {
1.1.1.5 root 1393: /* Set process priority to high */
1.1.1.6 root 1394: prio = 6;
1.1.1.5 root 1395: }
1396: break;
1397: case 7:
1.1.1.6 root 1398: if (ctx->mem_idx > 1) {
1.1.1.5 root 1399: /* Set process priority to very high */
1.1.1.6 root 1400: prio = 7;
1.1.1.5 root 1401: }
1402: break;
1403: #endif
1404: default:
1405: /* nop */
1406: break;
1407: }
1.1.1.6 root 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: }
1.1.1.5 root 1416: #endif
1.1 root 1417: }
1418: }
1419: /* orc & orc. */
1.1.1.6 root 1420: GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1.1.1.7 root 1421:
1.1 root 1422: /* xor & xor. */
1.1.1.7 root 1423: static void gen_xor(DisasContext *ctx)
1.1 root 1424: {
1425: /* Optimisation for "set to zero" case */
1.1.1.6 root 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);
1.1.1.5 root 1430: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1431: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1432: }
1.1.1.7 root 1433:
1.1 root 1434: /* ori */
1.1.1.7 root 1435: static void gen_ori(DisasContext *ctx)
1.1 root 1436: {
1.1.1.5 root 1437: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1438:
1439: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1440: /* NOP */
1.1.1.5 root 1441: /* XXX: should handle special NOPs for POWER series */
1.1 root 1442: return;
1.1.1.5 root 1443: }
1.1.1.6 root 1444: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1.1 root 1445: }
1.1.1.7 root 1446:
1.1 root 1447: /* oris */
1.1.1.7 root 1448: static void gen_oris(DisasContext *ctx)
1.1 root 1449: {
1.1.1.5 root 1450: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1451:
1452: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1453: /* NOP */
1454: return;
1.1.1.5 root 1455: }
1.1.1.6 root 1456: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1.1 root 1457: }
1.1.1.7 root 1458:
1.1 root 1459: /* xori */
1.1.1.7 root 1460: static void gen_xori(DisasContext *ctx)
1.1 root 1461: {
1.1.1.5 root 1462: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1463:
1464: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1465: /* NOP */
1466: return;
1467: }
1.1.1.6 root 1468: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1.1 root 1469: }
1.1.1.7 root 1470:
1.1 root 1471: /* xoris */
1.1.1.7 root 1472: static void gen_xoris(DisasContext *ctx)
1.1 root 1473: {
1.1.1.5 root 1474: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1475:
1476: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1477: /* NOP */
1478: return;
1479: }
1.1.1.6 root 1480: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1.1.1.5 root 1481: }
1.1.1.7 root 1482:
1.1.1.5 root 1483: /* popcntb : PowerPC 2.03 specification */
1.1.1.7 root 1484: static void gen_popcntb(DisasContext *ctx)
1.1.1.5 root 1485: {
1486: #if defined(TARGET_PPC64)
1487: if (ctx->sf_mode)
1.1.1.6 root 1488: gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 1489: else
1490: #endif
1.1.1.6 root 1491: gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1 root 1492: }
1493:
1.1.1.5 root 1494: #if defined(TARGET_PPC64)
1495: /* extsw & extsw. */
1.1.1.6 root 1496: GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1.1.1.7 root 1497:
1.1.1.5 root 1498: /* cntlzd */
1.1.1.7 root 1499: static void gen_cntlzd(DisasContext *ctx)
1.1.1.6 root 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: }
1.1.1.5 root 1505: #endif
1506:
1.1 root 1507: /*** Integer rotate ***/
1.1.1.7 root 1508:
1.1 root 1509: /* rlwimi & rlwimi. */
1.1.1.7 root 1510: static void gen_rlwimi(DisasContext *ctx)
1.1 root 1511: {
1.1.1.5 root 1512: uint32_t mb, me, sh;
1.1 root 1513:
1514: mb = MB(ctx->opcode);
1515: me = ME(ctx->opcode);
1.1.1.5 root 1516: sh = SH(ctx->opcode);
1.1.1.6 root 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: }
1.1.1.5 root 1544: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1545: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1546: }
1.1.1.7 root 1547:
1.1 root 1548: /* rlwinm & rlwinm. */
1.1.1.7 root 1549: static void gen_rlwinm(DisasContext *ctx)
1.1 root 1550: {
1551: uint32_t mb, me, sh;
1.1.1.5 root 1552:
1.1 root 1553: sh = SH(ctx->opcode);
1554: mb = MB(ctx->opcode);
1555: me = ME(ctx->opcode);
1.1.1.6 root 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);
1.1 root 1566: }
1.1.1.6 root 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
1.1.1.5 root 1584: #if defined(TARGET_PPC64)
1.1.1.6 root 1585: mb += 32;
1586: me += 32;
1.1.1.5 root 1587: #endif
1.1.1.6 root 1588: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1589: tcg_temp_free(t0);
1590: }
1.1.1.5 root 1591: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1592: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1593: }
1.1.1.7 root 1594:
1.1 root 1595: /* rlwnm & rlwnm. */
1.1.1.7 root 1596: static void gen_rlwnm(DisasContext *ctx)
1.1 root 1597: {
1598: uint32_t mb, me;
1.1.1.6 root 1599: TCGv t0;
1600: #if defined(TARGET_PPC64)
1601: TCGv_i32 t1, t2;
1602: #endif
1.1 root 1603:
1604: mb = MB(ctx->opcode);
1605: me = ME(ctx->opcode);
1.1.1.6 root 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
1.1.1.5 root 1620: if (unlikely(mb != 0 || me != 31)) {
1621: #if defined(TARGET_PPC64)
1622: mb += 32;
1623: me += 32;
1624: #endif
1.1.1.6 root 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);
1.1 root 1628: }
1.1.1.6 root 1629: tcg_temp_free(t0);
1.1.1.5 root 1630: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1631: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1632: }
1633:
1634: #if defined(TARGET_PPC64)
1635: #define GEN_PPC64_R2(name, opc1, opc2) \
1.1.1.7 root 1636: static void glue(gen_, name##0)(DisasContext *ctx) \
1.1.1.5 root 1637: { \
1638: gen_##name(ctx, 0); \
1639: } \
1.1.1.7 root 1640: \
1641: static void glue(gen_, name##1)(DisasContext *ctx) \
1.1.1.5 root 1642: { \
1643: gen_##name(ctx, 1); \
1644: }
1645: #define GEN_PPC64_R4(name, opc1, opc2) \
1.1.1.7 root 1646: static void glue(gen_, name##0)(DisasContext *ctx) \
1.1.1.5 root 1647: { \
1648: gen_##name(ctx, 0, 0); \
1649: } \
1.1.1.7 root 1650: \
1651: static void glue(gen_, name##1)(DisasContext *ctx) \
1.1.1.5 root 1652: { \
1653: gen_##name(ctx, 0, 1); \
1654: } \
1.1.1.7 root 1655: \
1656: static void glue(gen_, name##2)(DisasContext *ctx) \
1.1.1.5 root 1657: { \
1658: gen_##name(ctx, 1, 0); \
1659: } \
1.1.1.7 root 1660: \
1661: static void glue(gen_, name##3)(DisasContext *ctx) \
1.1.1.5 root 1662: { \
1663: gen_##name(ctx, 1, 1); \
1664: }
1665:
1.1.1.8 ! root 1666: static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
! 1667: uint32_t sh)
1.1.1.5 root 1668: {
1.1.1.6 root 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));
1.1.1.5 root 1680: }
1.1.1.6 root 1681: tcg_temp_free(t0);
1.1.1.5 root 1682: }
1683: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1684: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1685: }
1686: /* rldicl - rldicl. */
1.1.1.8 ! root 1687: static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1.1.1.5 root 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. */
1.1.1.8 ! root 1697: static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1.1.1.5 root 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. */
1.1.1.8 ! root 1707: static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1.1.1.5 root 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:
1.1.1.8 ! root 1717: static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
1.1.1.5 root 1718: {
1.1.1.6 root 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);
1.1.1.5 root 1726: if (unlikely(mb != 0 || me != 63)) {
1.1.1.6 root 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);
1.1.1.5 root 1730: }
1.1.1.6 root 1731: tcg_temp_free(t0);
1.1.1.5 root 1732: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1733: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1734: }
1735:
1736: /* rldcl - rldcl. */
1.1.1.8 ! root 1737: static inline void gen_rldcl(DisasContext *ctx, int mbn)
1.1.1.5 root 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. */
1.1.1.8 ! root 1746: static inline void gen_rldcr(DisasContext *ctx, int men)
1.1.1.5 root 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. */
1.1.1.8 ! root 1755: static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1.1.1.5 root 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;
1.1.1.6 root 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: }
1.1.1.5 root 1778: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1779: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1780: }
1.1.1.5 root 1781: GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1782: #endif
1.1 root 1783:
1784: /*** Integer shift ***/
1.1.1.7 root 1785:
1.1 root 1786: /* slw & slw. */
1.1.1.7 root 1787: static void gen_slw(DisasContext *ctx)
1.1.1.6 root 1788: {
1.1.1.8 ! root 1789: TCGv t0, t1;
1.1.1.6 root 1790:
1.1.1.8 ! root 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);
1.1.1.6 root 1805: tcg_temp_free(t0);
1.1.1.8 ! root 1806: tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.6 root 1807: if (unlikely(Rc(ctx->opcode) != 0))
1808: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1809: }
1.1.1.7 root 1810:
1.1 root 1811: /* sraw & sraw. */
1.1.1.7 root 1812: static void gen_sraw(DisasContext *ctx)
1.1.1.6 root 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: }
1.1.1.7 root 1819:
1.1 root 1820: /* srawi & srawi. */
1.1.1.7 root 1821: static void gen_srawi(DisasContext *ctx)
1.1 root 1822: {
1.1.1.6 root 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));
1.1.1.5 root 1845: }
1846: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1847: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1848: }
1.1.1.7 root 1849:
1.1 root 1850: /* srw & srw. */
1.1.1.7 root 1851: static void gen_srw(DisasContext *ctx)
1.1.1.6 root 1852: {
1853: TCGv t0, t1;
1854:
1.1.1.8 ! root 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);
1.1.1.6 root 1866: t1 = tcg_temp_new();
1.1.1.8 ! root 1867: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
! 1868: tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1.1.1.6 root 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: }
1.1.1.7 root 1874:
1.1.1.5 root 1875: #if defined(TARGET_PPC64)
1876: /* sld & sld. */
1.1.1.7 root 1877: static void gen_sld(DisasContext *ctx)
1.1.1.6 root 1878: {
1.1.1.8 ! root 1879: TCGv t0, t1;
1.1.1.6 root 1880:
1.1.1.8 ! root 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);
1.1.1.6 root 1890: tcg_temp_free(t0);
1891: if (unlikely(Rc(ctx->opcode) != 0))
1892: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1893: }
1.1.1.7 root 1894:
1.1.1.5 root 1895: /* srad & srad. */
1.1.1.7 root 1896: static void gen_srad(DisasContext *ctx)
1.1.1.6 root 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: }
1.1.1.5 root 1903: /* sradi & sradi. */
1.1.1.8 ! root 1904: static inline void gen_sradi(DisasContext *ctx, int n)
1.1.1.5 root 1905: {
1.1.1.6 root 1906: int sh = SH(ctx->opcode) + (n << 5);
1.1.1.5 root 1907: if (sh != 0) {
1.1.1.6 root 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));
1.1.1.5 root 1926: }
1927: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1928: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1929: }
1.1.1.7 root 1930:
1931: static void gen_sradi0(DisasContext *ctx)
1.1.1.5 root 1932: {
1933: gen_sradi(ctx, 0);
1934: }
1.1.1.7 root 1935:
1936: static void gen_sradi1(DisasContext *ctx)
1.1.1.5 root 1937: {
1938: gen_sradi(ctx, 1);
1939: }
1.1.1.7 root 1940:
1.1.1.5 root 1941: /* srd & srd. */
1.1.1.7 root 1942: static void gen_srd(DisasContext *ctx)
1.1.1.6 root 1943: {
1.1.1.8 ! root 1944: TCGv t0, t1;
1.1.1.6 root 1945:
1.1.1.8 ! root 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);
1.1.1.6 root 1955: tcg_temp_free(t0);
1956: if (unlikely(Rc(ctx->opcode) != 0))
1957: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1958: }
1.1.1.5 root 1959: #endif
1.1 root 1960:
1961: /*** Floating-Point arithmetic ***/
1.1.1.5 root 1962: #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
1.1.1.7 root 1963: static void gen_f##name(DisasContext *ctx) \
1.1 root 1964: { \
1.1.1.5 root 1965: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 1966: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 1967: return; \
1968: } \
1.1.1.6 root 1969: /* NIP cannot be restored if the memory exception comes from an helper */ \
1970: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 1971: gen_reset_fpstatus(); \
1.1.1.6 root 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)]); \
1.1 root 1974: if (isfloat) { \
1.1.1.6 root 1975: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
1.1 root 1976: } \
1.1.1.6 root 1977: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf, \
1978: Rc(ctx->opcode) != 0); \
1.1 root 1979: }
1980:
1.1.1.5 root 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);
1.1 root 1984:
1.1.1.5 root 1985: #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1.1.1.7 root 1986: static void gen_f##name(DisasContext *ctx) \
1.1 root 1987: { \
1.1.1.5 root 1988: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 1989: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 1990: return; \
1991: } \
1.1.1.6 root 1992: /* NIP cannot be restored if the memory exception comes from an helper */ \
1993: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 1994: gen_reset_fpstatus(); \
1.1.1.6 root 1995: gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
1996: cpu_fpr[rB(ctx->opcode)]); \
1.1 root 1997: if (isfloat) { \
1.1.1.6 root 1998: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
1.1 root 1999: } \
1.1.1.6 root 2000: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2001: set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 2002: }
1.1.1.5 root 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);
1.1 root 2006:
1.1.1.5 root 2007: #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1.1.1.7 root 2008: static void gen_f##name(DisasContext *ctx) \
1.1 root 2009: { \
1.1.1.5 root 2010: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2011: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2012: return; \
2013: } \
1.1.1.6 root 2014: /* NIP cannot be restored if the memory exception comes from an helper */ \
2015: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2016: gen_reset_fpstatus(); \
1.1.1.6 root 2017: gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2018: cpu_fpr[rC(ctx->opcode)]); \
1.1 root 2019: if (isfloat) { \
1.1.1.6 root 2020: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
1.1 root 2021: } \
1.1.1.6 root 2022: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2023: set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 2024: }
1.1.1.5 root 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);
1.1 root 2028:
1.1.1.5 root 2029: #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
1.1.1.7 root 2030: static void gen_f##name(DisasContext *ctx) \
1.1 root 2031: { \
1.1.1.5 root 2032: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2033: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2034: return; \
2035: } \
1.1.1.6 root 2036: /* NIP cannot be restored if the memory exception comes from an helper */ \
2037: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2038: gen_reset_fpstatus(); \
1.1.1.6 root 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); \
1.1 root 2042: }
2043:
1.1.1.5 root 2044: #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
1.1.1.7 root 2045: static void gen_f##name(DisasContext *ctx) \
1.1 root 2046: { \
1.1.1.5 root 2047: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2048: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2049: return; \
2050: } \
1.1.1.6 root 2051: /* NIP cannot be restored if the memory exception comes from an helper */ \
2052: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2053: gen_reset_fpstatus(); \
1.1.1.6 root 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); \
1.1 root 2057: }
2058:
2059: /* fadd - fadds */
1.1.1.5 root 2060: GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1.1 root 2061: /* fdiv - fdivs */
1.1.1.5 root 2062: GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1.1 root 2063: /* fmul - fmuls */
1.1.1.5 root 2064: GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2065:
2066: /* fre */
2067: GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1.1 root 2068:
2069: /* fres */
1.1.1.5 root 2070: GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
1.1 root 2071:
2072: /* frsqrte */
1.1.1.5 root 2073: GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2074:
2075: /* frsqrtes */
1.1.1.7 root 2076: static void gen_frsqrtes(DisasContext *ctx)
1.1.1.5 root 2077: {
1.1.1.6 root 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);
1.1.1.5 root 2088: }
1.1 root 2089:
2090: /* fsel */
1.1.1.5 root 2091: _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1.1 root 2092: /* fsub - fsubs */
1.1.1.5 root 2093: GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
1.1 root 2094: /* Optional: */
1.1.1.7 root 2095:
1.1 root 2096: /* fsqrt */
1.1.1.7 root 2097: static void gen_fsqrt(DisasContext *ctx)
1.1 root 2098: {
1.1.1.5 root 2099: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2100: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2101: return;
2102: }
1.1.1.6 root 2103: /* NIP cannot be restored if the memory exception comes from an helper */
2104: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2105: gen_reset_fpstatus();
1.1.1.6 root 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);
1.1 root 2108: }
2109:
1.1.1.7 root 2110: static void gen_fsqrts(DisasContext *ctx)
1.1 root 2111: {
1.1.1.5 root 2112: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2113: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2114: return;
2115: }
1.1.1.6 root 2116: /* NIP cannot be restored if the memory exception comes from an helper */
2117: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2118: gen_reset_fpstatus();
1.1.1.6 root 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);
1.1 root 2122: }
2123:
2124: /*** Floating-Point multiply-and-add ***/
2125: /* fmadd - fmadds */
1.1.1.5 root 2126: GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1.1 root 2127: /* fmsub - fmsubs */
1.1.1.5 root 2128: GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1.1 root 2129: /* fnmadd - fnmadds */
1.1.1.5 root 2130: GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1.1 root 2131: /* fnmsub - fnmsubs */
1.1.1.5 root 2132: GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
1.1 root 2133:
2134: /*** Floating-Point round & convert ***/
2135: /* fctiw */
1.1.1.5 root 2136: GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
1.1 root 2137: /* fctiwz */
1.1.1.5 root 2138: GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
1.1 root 2139: /* frsp */
1.1.1.5 root 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);
1.1 root 2158:
2159: /*** Floating-Point compare ***/
1.1.1.7 root 2160:
1.1 root 2161: /* fcmpo */
1.1.1.7 root 2162: static void gen_fcmpo(DisasContext *ctx)
1.1 root 2163: {
1.1.1.6 root 2164: TCGv_i32 crf;
1.1.1.5 root 2165: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2166: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2167: return;
2168: }
1.1.1.6 root 2169: /* NIP cannot be restored if the memory exception comes from an helper */
2170: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2171: gen_reset_fpstatus();
1.1.1.6 root 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();
1.1 root 2176: }
2177:
2178: /* fcmpu */
1.1.1.7 root 2179: static void gen_fcmpu(DisasContext *ctx)
1.1 root 2180: {
1.1.1.6 root 2181: TCGv_i32 crf;
1.1.1.5 root 2182: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2183: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2184: return;
2185: }
1.1.1.6 root 2186: /* NIP cannot be restored if the memory exception comes from an helper */
2187: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2188: gen_reset_fpstatus();
1.1.1.6 root 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();
1.1 root 2193: }
2194:
2195: /*** Floating-point move ***/
2196: /* fabs */
1.1.1.5 root 2197: /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2198: GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1.1 root 2199:
2200: /* fmr - fmr. */
1.1.1.5 root 2201: /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1.1.1.7 root 2202: static void gen_fmr(DisasContext *ctx)
1.1 root 2203: {
1.1.1.5 root 2204: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2205: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2206: return;
2207: }
1.1.1.6 root 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);
1.1 root 2210: }
2211:
2212: /* fnabs */
1.1.1.5 root 2213: /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2214: GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1.1 root 2215: /* fneg */
1.1.1.5 root 2216: /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2217: GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1.1 root 2218:
2219: /*** Floating-Point status & ctrl register ***/
1.1.1.7 root 2220:
1.1 root 2221: /* mcrfs */
1.1.1.7 root 2222: static void gen_mcrfs(DisasContext *ctx)
1.1 root 2223: {
1.1.1.5 root 2224: int bfa;
2225:
2226: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2227: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2228: return;
2229: }
1.1.1.5 root 2230: bfa = 4 * (7 - crfS(ctx->opcode));
1.1.1.6 root 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));
1.1 root 2234: }
2235:
2236: /* mffs */
1.1.1.7 root 2237: static void gen_mffs(DisasContext *ctx)
1.1 root 2238: {
1.1.1.5 root 2239: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2240: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2241: return;
2242: }
1.1.1.5 root 2243: gen_reset_fpstatus();
1.1.1.6 root 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);
1.1 root 2246: }
2247:
2248: /* mtfsb0 */
1.1.1.7 root 2249: static void gen_mtfsb0(DisasContext *ctx)
1.1 root 2250: {
2251: uint8_t crb;
1.1.1.5 root 2252:
2253: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2254: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2255: return;
2256: }
1.1.1.6 root 2257: crb = 31 - crbD(ctx->opcode);
1.1.1.5 root 2258: gen_reset_fpstatus();
1.1.1.6 root 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: }
1.1.1.5 root 2267: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2268: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2269: }
1.1 root 2270: }
2271:
2272: /* mtfsb1 */
1.1.1.7 root 2273: static void gen_mtfsb1(DisasContext *ctx)
1.1 root 2274: {
2275: uint8_t crb;
1.1.1.5 root 2276:
2277: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2278: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2279: return;
2280: }
1.1.1.6 root 2281: crb = 31 - crbD(ctx->opcode);
1.1.1.5 root 2282: gen_reset_fpstatus();
2283: /* XXX: we pretend we can only do IEEE floating-point computations */
1.1.1.6 root 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: }
1.1.1.5 root 2292: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2293: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2294: }
2295: /* We can raise a differed exception */
1.1.1.6 root 2296: gen_helper_float_check_status();
1.1 root 2297: }
2298:
2299: /* mtfsf */
1.1.1.7 root 2300: static void gen_mtfsf(DisasContext *ctx)
1.1 root 2301: {
1.1.1.6 root 2302: TCGv_i32 t0;
1.1.1.7 root 2303: int L = ctx->opcode & 0x02000000;
1.1.1.6 root 2304:
1.1.1.5 root 2305: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2306: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2307: return;
2308: }
1.1.1.6 root 2309: /* NIP cannot be restored if the memory exception comes from an helper */
2310: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2311: gen_reset_fpstatus();
1.1.1.7 root 2312: if (L)
2313: t0 = tcg_const_i32(0xff);
2314: else
2315: t0 = tcg_const_i32(FM(ctx->opcode));
1.1.1.6 root 2316: gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2317: tcg_temp_free_i32(t0);
1.1.1.5 root 2318: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2319: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2320: }
2321: /* We can raise a differed exception */
1.1.1.6 root 2322: gen_helper_float_check_status();
1.1 root 2323: }
2324:
2325: /* mtfsfi */
1.1.1.7 root 2326: static void gen_mtfsfi(DisasContext *ctx)
1.1 root 2327: {
1.1.1.5 root 2328: int bf, sh;
1.1.1.6 root 2329: TCGv_i64 t0;
2330: TCGv_i32 t1;
1.1.1.5 root 2331:
2332: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2333: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2334: return;
2335: }
1.1.1.5 root 2336: bf = crbD(ctx->opcode) >> 2;
2337: sh = 7 - bf;
1.1.1.6 root 2338: /* NIP cannot be restored if the memory exception comes from an helper */
2339: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2340: gen_reset_fpstatus();
1.1.1.6 root 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);
1.1.1.5 root 2346: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2347: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2348: }
2349: /* We can raise a differed exception */
1.1.1.6 root 2350: gen_helper_float_check_status();
1.1 root 2351: }
2352:
1.1.1.5 root 2353: /*** Addressing modes ***/
2354: /* Register indirect with immediate index : EA = (rA|0) + SIMM */
1.1.1.8 ! root 2355: static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
! 2356: target_long maskl)
1.1.1.5 root 2357: {
2358: target_long simm = SIMM(ctx->opcode);
2359:
2360: simm &= ~maskl;
2361: if (rA(ctx->opcode) == 0) {
1.1.1.6 root 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
1.1.1.5 root 2375: } else {
1.1.1.6 root 2376: #if defined(TARGET_PPC64)
2377: if (!ctx->sf_mode) {
2378: tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2379: } else
1.1.1.5 root 2380: #endif
1.1.1.6 root 2381: tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2382: }
1.1.1.5 root 2383: }
2384:
1.1.1.8 ! root 2385: static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
1.1.1.5 root 2386: {
2387: if (rA(ctx->opcode) == 0) {
1.1.1.6 root 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)]);
1.1.1.5 root 2394: } else {
1.1.1.6 root 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: }
1.1.1.5 root 2400: #endif
1.1.1.6 root 2401: }
1.1.1.5 root 2402: }
2403:
1.1.1.8 ! root 2404: static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
1.1.1.5 root 2405: {
2406: if (rA(ctx->opcode) == 0) {
1.1.1.6 root 2407: tcg_gen_movi_tl(EA, 0);
1.1.1.5 root 2408: } else {
1.1.1.6 root 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:
1.1.1.8 ! root 2418: static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
! 2419: target_long val)
1.1.1.6 root 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);
1.1.1.5 root 2425: }
2426: #endif
2427: }
2428:
1.1.1.8 ! root 2429: static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
1.1.1.6 root 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 */
2435: gen_update_nip(ctx, ctx->nip - 4);
2436: tcg_gen_andi_tl(t0, EA, mask);
2437: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2438: t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2439: t2 = tcg_const_i32(0);
2440: gen_helper_raise_exception_err(t1, t2);
2441: tcg_temp_free_i32(t1);
2442: tcg_temp_free_i32(t2);
2443: gen_set_label(l1);
2444: tcg_temp_free(t0);
2445: }
2446:
2447: /*** Integer load ***/
1.1.1.8 ! root 2448: static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2449: {
2450: tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2451: }
2452:
1.1.1.8 ! root 2453: static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2454: {
2455: tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2456: }
2457:
1.1.1.8 ! root 2458: static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2459: {
2460: tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2461: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2462: tcg_gen_bswap16_tl(arg1, arg1);
1.1.1.6 root 2463: }
2464: }
2465:
1.1.1.8 ! root 2466: static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2467: {
2468: if (unlikely(ctx->le_mode)) {
2469: tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
1.1.1.7 root 2470: tcg_gen_bswap16_tl(arg1, arg1);
1.1.1.6 root 2471: tcg_gen_ext16s_tl(arg1, arg1);
2472: } else {
2473: tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2474: }
2475: }
2476:
1.1.1.8 ! root 2477: static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2478: {
2479: tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2480: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2481: tcg_gen_bswap32_tl(arg1, arg1);
1.1.1.6 root 2482: }
1.1 root 2483: }
2484:
1.1.1.6 root 2485: #if defined(TARGET_PPC64)
1.1.1.8 ! root 2486: static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2487: {
2488: if (unlikely(ctx->le_mode)) {
2489: tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
1.1.1.7 root 2490: tcg_gen_bswap32_tl(arg1, arg1);
2491: tcg_gen_ext32s_tl(arg1, arg1);
1.1.1.6 root 2492: } else
2493: tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
2494: }
2495: #endif
2496:
1.1.1.8 ! root 2497: static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 2498: {
2499: tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2500: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2501: tcg_gen_bswap64_i64(arg1, arg1);
1.1.1.6 root 2502: }
2503: }
2504:
1.1.1.8 ! root 2505: static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2506: {
2507: tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2508: }
2509:
1.1.1.8 ! root 2510: static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2511: {
2512: if (unlikely(ctx->le_mode)) {
2513: TCGv t0 = tcg_temp_new();
2514: tcg_gen_ext16u_tl(t0, arg1);
1.1.1.7 root 2515: tcg_gen_bswap16_tl(t0, t0);
1.1.1.6 root 2516: tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2517: tcg_temp_free(t0);
2518: } else {
2519: tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2520: }
2521: }
2522:
1.1.1.8 ! root 2523: static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2524: {
2525: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2526: TCGv t0 = tcg_temp_new();
2527: tcg_gen_ext32u_tl(t0, arg1);
2528: tcg_gen_bswap32_tl(t0, t0);
1.1.1.6 root 2529: tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2530: tcg_temp_free(t0);
2531: } else {
2532: tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2533: }
2534: }
2535:
1.1.1.8 ! root 2536: static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 2537: {
2538: if (unlikely(ctx->le_mode)) {
2539: TCGv_i64 t0 = tcg_temp_new_i64();
1.1.1.7 root 2540: tcg_gen_bswap64_i64(t0, arg1);
1.1.1.6 root 2541: tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
2542: tcg_temp_free_i64(t0);
2543: } else
2544: tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
2545: }
2546:
2547: #define GEN_LD(name, ldop, opc, type) \
1.1.1.7 root 2548: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 2549: { \
2550: TCGv EA; \
2551: gen_set_access_type(ctx, ACCESS_INT); \
2552: EA = tcg_temp_new(); \
2553: gen_addr_imm_index(ctx, EA, 0); \
2554: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2555: tcg_temp_free(EA); \
2556: }
2557:
2558: #define GEN_LDU(name, ldop, opc, type) \
1.1.1.7 root 2559: static void glue(gen_, name##u)(DisasContext *ctx) \
1.1 root 2560: { \
1.1.1.6 root 2561: TCGv EA; \
1.1.1.5 root 2562: if (unlikely(rA(ctx->opcode) == 0 || \
2563: rA(ctx->opcode) == rD(ctx->opcode))) { \
1.1.1.6 root 2564: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2565: return; \
2566: } \
1.1.1.6 root 2567: gen_set_access_type(ctx, ACCESS_INT); \
2568: EA = tcg_temp_new(); \
1.1.1.5 root 2569: if (type == PPC_64B) \
1.1.1.6 root 2570: gen_addr_imm_index(ctx, EA, 0x03); \
1.1.1.5 root 2571: else \
1.1.1.6 root 2572: gen_addr_imm_index(ctx, EA, 0); \
2573: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2574: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2575: tcg_temp_free(EA); \
1.1 root 2576: }
2577:
1.1.1.6 root 2578: #define GEN_LDUX(name, ldop, opc2, opc3, type) \
1.1.1.7 root 2579: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 2580: { \
1.1.1.6 root 2581: TCGv EA; \
1.1.1.5 root 2582: if (unlikely(rA(ctx->opcode) == 0 || \
2583: rA(ctx->opcode) == rD(ctx->opcode))) { \
1.1.1.6 root 2584: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2585: return; \
2586: } \
1.1.1.6 root 2587: gen_set_access_type(ctx, ACCESS_INT); \
2588: EA = tcg_temp_new(); \
2589: gen_addr_reg_index(ctx, EA); \
2590: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2591: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2592: tcg_temp_free(EA); \
2593: }
2594:
2595: #define GEN_LDX(name, ldop, opc2, opc3, type) \
1.1.1.7 root 2596: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1.1.6 root 2597: { \
2598: TCGv EA; \
2599: gen_set_access_type(ctx, ACCESS_INT); \
2600: EA = tcg_temp_new(); \
2601: gen_addr_reg_index(ctx, EA); \
2602: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2603: tcg_temp_free(EA); \
2604: }
2605:
2606: #define GEN_LDS(name, ldop, op, type) \
2607: GEN_LD(name, ldop, op | 0x20, type); \
2608: GEN_LDU(name, ldop, op | 0x21, type); \
2609: GEN_LDUX(name, ldop, 0x17, op | 0x01, type); \
2610: GEN_LDX(name, ldop, 0x17, op | 0x00, type)
1.1 root 2611:
2612: /* lbz lbzu lbzux lbzx */
1.1.1.6 root 2613: GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
1.1 root 2614: /* lha lhau lhaux lhax */
1.1.1.6 root 2615: GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
1.1 root 2616: /* lhz lhzu lhzux lhzx */
1.1.1.6 root 2617: GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
1.1 root 2618: /* lwz lwzu lwzux lwzx */
1.1.1.6 root 2619: GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
1.1.1.5 root 2620: #if defined(TARGET_PPC64)
2621: /* lwaux */
1.1.1.6 root 2622: GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
1.1.1.5 root 2623: /* lwax */
1.1.1.6 root 2624: GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
1.1.1.5 root 2625: /* ldux */
1.1.1.6 root 2626: GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
1.1.1.5 root 2627: /* ldx */
1.1.1.6 root 2628: GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
1.1.1.7 root 2629:
2630: static void gen_ld(DisasContext *ctx)
1.1.1.5 root 2631: {
1.1.1.6 root 2632: TCGv EA;
1.1.1.5 root 2633: if (Rc(ctx->opcode)) {
2634: if (unlikely(rA(ctx->opcode) == 0 ||
2635: rA(ctx->opcode) == rD(ctx->opcode))) {
1.1.1.6 root 2636: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2637: return;
2638: }
2639: }
1.1.1.6 root 2640: gen_set_access_type(ctx, ACCESS_INT);
2641: EA = tcg_temp_new();
2642: gen_addr_imm_index(ctx, EA, 0x03);
1.1.1.5 root 2643: if (ctx->opcode & 0x02) {
2644: /* lwa (lwau is undefined) */
1.1.1.6 root 2645: gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
1.1.1.5 root 2646: } else {
2647: /* ld - ldu */
1.1.1.6 root 2648: gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
1.1.1.5 root 2649: }
2650: if (Rc(ctx->opcode))
1.1.1.6 root 2651: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2652: tcg_temp_free(EA);
1.1.1.5 root 2653: }
1.1.1.7 root 2654:
1.1.1.5 root 2655: /* lq */
1.1.1.7 root 2656: static void gen_lq(DisasContext *ctx)
1.1.1.5 root 2657: {
2658: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 2659: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2660: #else
2661: int ra, rd;
1.1.1.6 root 2662: TCGv EA;
1.1.1.5 root 2663:
2664: /* Restore CPU state */
1.1.1.6 root 2665: if (unlikely(ctx->mem_idx == 0)) {
2666: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2667: return;
2668: }
2669: ra = rA(ctx->opcode);
2670: rd = rD(ctx->opcode);
2671: if (unlikely((rd & 1) || rd == ra)) {
1.1.1.6 root 2672: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2673: return;
2674: }
1.1.1.6 root 2675: if (unlikely(ctx->le_mode)) {
1.1.1.5 root 2676: /* Little-endian mode is not handled */
1.1.1.6 root 2677: gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
1.1.1.5 root 2678: return;
2679: }
1.1.1.6 root 2680: gen_set_access_type(ctx, ACCESS_INT);
2681: EA = tcg_temp_new();
2682: gen_addr_imm_index(ctx, EA, 0x0F);
2683: gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2684: gen_addr_add(ctx, EA, EA, 8);
2685: gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2686: tcg_temp_free(EA);
1.1.1.5 root 2687: #endif
2688: }
2689: #endif
1.1 root 2690:
2691: /*** Integer store ***/
1.1.1.6 root 2692: #define GEN_ST(name, stop, opc, type) \
1.1.1.7 root 2693: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 2694: { \
1.1.1.6 root 2695: TCGv EA; \
2696: gen_set_access_type(ctx, ACCESS_INT); \
2697: EA = tcg_temp_new(); \
2698: gen_addr_imm_index(ctx, EA, 0); \
2699: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2700: tcg_temp_free(EA); \
1.1 root 2701: }
2702:
1.1.1.6 root 2703: #define GEN_STU(name, stop, opc, type) \
1.1.1.7 root 2704: static void glue(gen_, stop##u)(DisasContext *ctx) \
1.1 root 2705: { \
1.1.1.6 root 2706: TCGv EA; \
1.1.1.5 root 2707: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 2708: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2709: return; \
2710: } \
1.1.1.6 root 2711: gen_set_access_type(ctx, ACCESS_INT); \
2712: EA = tcg_temp_new(); \
1.1.1.5 root 2713: if (type == PPC_64B) \
1.1.1.6 root 2714: gen_addr_imm_index(ctx, EA, 0x03); \
1.1.1.5 root 2715: else \
1.1.1.6 root 2716: gen_addr_imm_index(ctx, EA, 0); \
2717: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2718: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2719: tcg_temp_free(EA); \
1.1 root 2720: }
2721:
1.1.1.6 root 2722: #define GEN_STUX(name, stop, opc2, opc3, type) \
1.1.1.7 root 2723: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 2724: { \
1.1.1.6 root 2725: TCGv EA; \
1.1.1.5 root 2726: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 2727: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2728: return; \
2729: } \
1.1.1.6 root 2730: gen_set_access_type(ctx, ACCESS_INT); \
2731: EA = tcg_temp_new(); \
2732: gen_addr_reg_index(ctx, EA); \
2733: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2734: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2735: tcg_temp_free(EA); \
2736: }
2737:
2738: #define GEN_STX(name, stop, opc2, opc3, type) \
1.1.1.7 root 2739: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1.1.6 root 2740: { \
2741: TCGv EA; \
2742: gen_set_access_type(ctx, ACCESS_INT); \
2743: EA = tcg_temp_new(); \
2744: gen_addr_reg_index(ctx, EA); \
2745: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2746: tcg_temp_free(EA); \
2747: }
2748:
2749: #define GEN_STS(name, stop, op, type) \
2750: GEN_ST(name, stop, op | 0x20, type); \
2751: GEN_STU(name, stop, op | 0x21, type); \
2752: GEN_STUX(name, stop, 0x17, op | 0x01, type); \
2753: GEN_STX(name, stop, 0x17, op | 0x00, type)
1.1 root 2754:
2755: /* stb stbu stbux stbx */
1.1.1.6 root 2756: GEN_STS(stb, st8, 0x06, PPC_INTEGER);
1.1 root 2757: /* sth sthu sthux sthx */
1.1.1.6 root 2758: GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
1.1 root 2759: /* stw stwu stwux stwx */
1.1.1.6 root 2760: GEN_STS(stw, st32, 0x04, PPC_INTEGER);
1.1.1.5 root 2761: #if defined(TARGET_PPC64)
1.1.1.6 root 2762: GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2763: GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
1.1.1.7 root 2764:
2765: static void gen_std(DisasContext *ctx)
1.1.1.5 root 2766: {
2767: int rs;
1.1.1.6 root 2768: TCGv EA;
1.1 root 2769:
1.1.1.5 root 2770: rs = rS(ctx->opcode);
2771: if ((ctx->opcode & 0x3) == 0x2) {
2772: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 2773: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2774: #else
2775: /* stq */
1.1.1.6 root 2776: if (unlikely(ctx->mem_idx == 0)) {
2777: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2778: return;
2779: }
2780: if (unlikely(rs & 1)) {
1.1.1.6 root 2781: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2782: return;
2783: }
1.1.1.6 root 2784: if (unlikely(ctx->le_mode)) {
1.1.1.5 root 2785: /* Little-endian mode is not handled */
1.1.1.6 root 2786: gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
1.1.1.5 root 2787: return;
2788: }
1.1.1.6 root 2789: gen_set_access_type(ctx, ACCESS_INT);
2790: EA = tcg_temp_new();
2791: gen_addr_imm_index(ctx, EA, 0x03);
2792: gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2793: gen_addr_add(ctx, EA, EA, 8);
2794: gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
2795: tcg_temp_free(EA);
1.1.1.5 root 2796: #endif
2797: } else {
2798: /* std / stdu */
2799: if (Rc(ctx->opcode)) {
2800: if (unlikely(rA(ctx->opcode) == 0)) {
1.1.1.6 root 2801: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2802: return;
2803: }
2804: }
1.1.1.6 root 2805: gen_set_access_type(ctx, ACCESS_INT);
2806: EA = tcg_temp_new();
2807: gen_addr_imm_index(ctx, EA, 0x03);
2808: gen_qemu_st64(ctx, cpu_gpr[rs], EA);
1.1.1.5 root 2809: if (Rc(ctx->opcode))
1.1.1.6 root 2810: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2811: tcg_temp_free(EA);
1.1.1.5 root 2812: }
2813: }
2814: #endif
1.1 root 2815: /*** Integer load and store with byte reverse ***/
2816: /* lhbrx */
1.1.1.8 ! root 2817: static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2818: {
2819: tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2820: if (likely(!ctx->le_mode)) {
1.1.1.7 root 2821: tcg_gen_bswap16_tl(arg1, arg1);
1.1.1.6 root 2822: }
2823: }
2824: GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
2825:
1.1 root 2826: /* lwbrx */
1.1.1.8 ! root 2827: static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2828: {
2829: tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2830: if (likely(!ctx->le_mode)) {
1.1.1.7 root 2831: tcg_gen_bswap32_tl(arg1, arg1);
1.1.1.6 root 2832: }
2833: }
2834: GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
2835:
1.1 root 2836: /* sthbrx */
1.1.1.8 ! root 2837: static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2838: {
2839: if (likely(!ctx->le_mode)) {
2840: TCGv t0 = tcg_temp_new();
2841: tcg_gen_ext16u_tl(t0, arg1);
1.1.1.7 root 2842: tcg_gen_bswap16_tl(t0, t0);
1.1.1.6 root 2843: tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2844: tcg_temp_free(t0);
2845: } else {
2846: tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2847: }
2848: }
2849: GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
2850:
1.1 root 2851: /* stwbrx */
1.1.1.8 ! root 2852: static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2853: {
2854: if (likely(!ctx->le_mode)) {
1.1.1.7 root 2855: TCGv t0 = tcg_temp_new();
2856: tcg_gen_ext32u_tl(t0, arg1);
2857: tcg_gen_bswap32_tl(t0, t0);
1.1.1.6 root 2858: tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2859: tcg_temp_free(t0);
2860: } else {
2861: tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2862: }
2863: }
2864: GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
1.1 root 2865:
2866: /*** Integer load and store multiple ***/
1.1.1.7 root 2867:
1.1 root 2868: /* lmw */
1.1.1.7 root 2869: static void gen_lmw(DisasContext *ctx)
1.1 root 2870: {
1.1.1.6 root 2871: TCGv t0;
2872: TCGv_i32 t1;
2873: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 2874: /* NIP cannot be restored if the memory exception comes from an helper */
2875: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2876: t0 = tcg_temp_new();
2877: t1 = tcg_const_i32(rD(ctx->opcode));
2878: gen_addr_imm_index(ctx, t0, 0);
2879: gen_helper_lmw(t0, t1);
2880: tcg_temp_free(t0);
2881: tcg_temp_free_i32(t1);
1.1 root 2882: }
2883:
2884: /* stmw */
1.1.1.7 root 2885: static void gen_stmw(DisasContext *ctx)
1.1 root 2886: {
1.1.1.6 root 2887: TCGv t0;
2888: TCGv_i32 t1;
2889: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 2890: /* NIP cannot be restored if the memory exception comes from an helper */
2891: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2892: t0 = tcg_temp_new();
2893: t1 = tcg_const_i32(rS(ctx->opcode));
2894: gen_addr_imm_index(ctx, t0, 0);
2895: gen_helper_stmw(t0, t1);
2896: tcg_temp_free(t0);
2897: tcg_temp_free_i32(t1);
1.1 root 2898: }
2899:
2900: /*** Integer load and store strings ***/
1.1.1.7 root 2901:
1.1 root 2902: /* lswi */
2903: /* PowerPC32 specification says we must generate an exception if
2904: * rA is in the range of registers to be loaded.
2905: * In an other hand, IBM says this is valid, but rA won't be loaded.
2906: * For now, I'll follow the spec...
2907: */
1.1.1.7 root 2908: static void gen_lswi(DisasContext *ctx)
1.1 root 2909: {
1.1.1.6 root 2910: TCGv t0;
2911: TCGv_i32 t1, t2;
1.1 root 2912: int nb = NB(ctx->opcode);
2913: int start = rD(ctx->opcode);
2914: int ra = rA(ctx->opcode);
2915: int nr;
2916:
2917: if (nb == 0)
2918: nb = 32;
2919: nr = nb / 4;
1.1.1.5 root 2920: if (unlikely(((start + nr) > 32 &&
2921: start <= ra && (start + nr - 32) > ra) ||
2922: ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
1.1.1.6 root 2923: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
1.1 root 2924: return;
2925: }
1.1.1.6 root 2926: gen_set_access_type(ctx, ACCESS_INT);
1.1 root 2927: /* NIP cannot be restored if the memory exception comes from an helper */
1.1.1.5 root 2928: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2929: t0 = tcg_temp_new();
2930: gen_addr_register(ctx, t0);
2931: t1 = tcg_const_i32(nb);
2932: t2 = tcg_const_i32(start);
2933: gen_helper_lsw(t0, t1, t2);
2934: tcg_temp_free(t0);
2935: tcg_temp_free_i32(t1);
2936: tcg_temp_free_i32(t2);
1.1 root 2937: }
2938:
2939: /* lswx */
1.1.1.7 root 2940: static void gen_lswx(DisasContext *ctx)
1.1 root 2941: {
1.1.1.6 root 2942: TCGv t0;
2943: TCGv_i32 t1, t2, t3;
2944: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 2945: /* NIP cannot be restored if the memory exception comes from an helper */
2946: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2947: t0 = tcg_temp_new();
2948: gen_addr_reg_index(ctx, t0);
2949: t1 = tcg_const_i32(rD(ctx->opcode));
2950: t2 = tcg_const_i32(rA(ctx->opcode));
2951: t3 = tcg_const_i32(rB(ctx->opcode));
2952: gen_helper_lswx(t0, t1, t2, t3);
2953: tcg_temp_free(t0);
2954: tcg_temp_free_i32(t1);
2955: tcg_temp_free_i32(t2);
2956: tcg_temp_free_i32(t3);
1.1 root 2957: }
2958:
2959: /* stswi */
1.1.1.7 root 2960: static void gen_stswi(DisasContext *ctx)
1.1 root 2961: {
1.1.1.6 root 2962: TCGv t0;
2963: TCGv_i32 t1, t2;
1.1 root 2964: int nb = NB(ctx->opcode);
1.1.1.6 root 2965: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 2966: /* NIP cannot be restored if the memory exception comes from an helper */
2967: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2968: t0 = tcg_temp_new();
2969: gen_addr_register(ctx, t0);
1.1 root 2970: if (nb == 0)
2971: nb = 32;
1.1.1.6 root 2972: t1 = tcg_const_i32(nb);
2973: t2 = tcg_const_i32(rS(ctx->opcode));
2974: gen_helper_stsw(t0, t1, t2);
2975: tcg_temp_free(t0);
2976: tcg_temp_free_i32(t1);
2977: tcg_temp_free_i32(t2);
1.1 root 2978: }
2979:
2980: /* stswx */
1.1.1.7 root 2981: static void gen_stswx(DisasContext *ctx)
1.1 root 2982: {
1.1.1.6 root 2983: TCGv t0;
2984: TCGv_i32 t1, t2;
2985: gen_set_access_type(ctx, ACCESS_INT);
1.1 root 2986: /* NIP cannot be restored if the memory exception comes from an helper */
1.1.1.5 root 2987: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2988: t0 = tcg_temp_new();
2989: gen_addr_reg_index(ctx, t0);
2990: t1 = tcg_temp_new_i32();
2991: tcg_gen_trunc_tl_i32(t1, cpu_xer);
2992: tcg_gen_andi_i32(t1, t1, 0x7F);
2993: t2 = tcg_const_i32(rS(ctx->opcode));
2994: gen_helper_stsw(t0, t1, t2);
2995: tcg_temp_free(t0);
2996: tcg_temp_free_i32(t1);
2997: tcg_temp_free_i32(t2);
1.1 root 2998: }
2999:
3000: /*** Memory synchronisation ***/
3001: /* eieio */
1.1.1.7 root 3002: static void gen_eieio(DisasContext *ctx)
1.1 root 3003: {
3004: }
3005:
3006: /* isync */
1.1.1.7 root 3007: static void gen_isync(DisasContext *ctx)
1.1 root 3008: {
1.1.1.6 root 3009: gen_stop_exception(ctx);
1.1 root 3010: }
3011:
3012: /* lwarx */
1.1.1.7 root 3013: static void gen_lwarx(DisasContext *ctx)
1.1 root 3014: {
1.1.1.6 root 3015: TCGv t0;
1.1.1.8 ! root 3016: TCGv gpr = cpu_gpr[rD(ctx->opcode)];
1.1.1.6 root 3017: gen_set_access_type(ctx, ACCESS_RES);
3018: t0 = tcg_temp_local_new();
3019: gen_addr_reg_index(ctx, t0);
3020: gen_check_align(ctx, t0, 0x03);
1.1.1.8 ! root 3021: gen_qemu_ld32u(ctx, gpr, t0);
1.1.1.6 root 3022: tcg_gen_mov_tl(cpu_reserve, t0);
1.1.1.8 ! root 3023: tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
1.1.1.6 root 3024: tcg_temp_free(t0);
1.1 root 3025: }
3026:
1.1.1.8 ! root 3027: #if defined(CONFIG_USER_ONLY)
! 3028: static void gen_conditional_store (DisasContext *ctx, TCGv EA,
! 3029: int reg, int size)
! 3030: {
! 3031: TCGv t0 = tcg_temp_new();
! 3032: uint32_t save_exception = ctx->exception;
! 3033:
! 3034: tcg_gen_st_tl(EA, cpu_env, offsetof(CPUState, reserve_ea));
! 3035: tcg_gen_movi_tl(t0, (size << 5) | reg);
! 3036: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, reserve_info));
! 3037: tcg_temp_free(t0);
! 3038: gen_update_nip(ctx, ctx->nip-4);
! 3039: ctx->exception = POWERPC_EXCP_BRANCH;
! 3040: gen_exception(ctx, POWERPC_EXCP_STCX);
! 3041: ctx->exception = save_exception;
! 3042: }
! 3043: #endif
! 3044:
1.1 root 3045: /* stwcx. */
1.1.1.7 root 3046: static void gen_stwcx_(DisasContext *ctx)
1.1 root 3047: {
1.1.1.6 root 3048: TCGv t0;
3049: gen_set_access_type(ctx, ACCESS_RES);
3050: t0 = tcg_temp_local_new();
3051: gen_addr_reg_index(ctx, t0);
3052: gen_check_align(ctx, t0, 0x03);
1.1.1.8 ! root 3053: #if defined(CONFIG_USER_ONLY)
! 3054: gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
! 3055: #else
! 3056: {
! 3057: int l1;
! 3058:
! 3059: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
! 3060: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
! 3061: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
! 3062: l1 = gen_new_label();
! 3063: tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
! 3064: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
! 3065: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
! 3066: gen_set_label(l1);
! 3067: tcg_gen_movi_tl(cpu_reserve, -1);
! 3068: }
! 3069: #endif
1.1.1.6 root 3070: tcg_temp_free(t0);
1.1 root 3071: }
3072:
1.1.1.5 root 3073: #if defined(TARGET_PPC64)
3074: /* ldarx */
1.1.1.7 root 3075: static void gen_ldarx(DisasContext *ctx)
1.1.1.5 root 3076: {
1.1.1.6 root 3077: TCGv t0;
1.1.1.8 ! root 3078: TCGv gpr = cpu_gpr[rD(ctx->opcode)];
1.1.1.6 root 3079: gen_set_access_type(ctx, ACCESS_RES);
3080: t0 = tcg_temp_local_new();
3081: gen_addr_reg_index(ctx, t0);
3082: gen_check_align(ctx, t0, 0x07);
1.1.1.8 ! root 3083: gen_qemu_ld64(ctx, gpr, t0);
1.1.1.6 root 3084: tcg_gen_mov_tl(cpu_reserve, t0);
1.1.1.8 ! root 3085: tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
1.1.1.6 root 3086: tcg_temp_free(t0);
1.1.1.5 root 3087: }
3088:
3089: /* stdcx. */
1.1.1.7 root 3090: static void gen_stdcx_(DisasContext *ctx)
1.1.1.5 root 3091: {
1.1.1.6 root 3092: TCGv t0;
3093: gen_set_access_type(ctx, ACCESS_RES);
3094: t0 = tcg_temp_local_new();
3095: gen_addr_reg_index(ctx, t0);
3096: gen_check_align(ctx, t0, 0x07);
1.1.1.8 ! root 3097: #if defined(CONFIG_USER_ONLY)
! 3098: gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
! 3099: #else
! 3100: {
! 3101: int l1;
! 3102: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
! 3103: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
! 3104: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
! 3105: l1 = gen_new_label();
! 3106: tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
! 3107: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
! 3108: gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
! 3109: gen_set_label(l1);
! 3110: tcg_gen_movi_tl(cpu_reserve, -1);
! 3111: }
! 3112: #endif
1.1.1.6 root 3113: tcg_temp_free(t0);
1.1.1.5 root 3114: }
3115: #endif /* defined(TARGET_PPC64) */
3116:
1.1 root 3117: /* sync */
1.1.1.7 root 3118: static void gen_sync(DisasContext *ctx)
1.1 root 3119: {
3120: }
3121:
1.1.1.5 root 3122: /* wait */
1.1.1.7 root 3123: static void gen_wait(DisasContext *ctx)
1.1.1.5 root 3124: {
1.1.1.6 root 3125: TCGv_i32 t0 = tcg_temp_new_i32();
3126: tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3127: tcg_temp_free_i32(t0);
1.1.1.5 root 3128: /* Stop translation, as the CPU is supposed to sleep from now */
1.1.1.6 root 3129: gen_exception_err(ctx, EXCP_HLT, 1);
1.1.1.5 root 3130: }
3131:
1.1 root 3132: /*** Floating-point load ***/
1.1.1.6 root 3133: #define GEN_LDF(name, ldop, opc, type) \
1.1.1.7 root 3134: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 3135: { \
1.1.1.6 root 3136: TCGv EA; \
1.1.1.5 root 3137: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3138: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3139: return; \
3140: } \
1.1.1.6 root 3141: gen_set_access_type(ctx, ACCESS_FLOAT); \
3142: EA = tcg_temp_new(); \
3143: gen_addr_imm_index(ctx, EA, 0); \
3144: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3145: tcg_temp_free(EA); \
1.1 root 3146: }
3147:
1.1.1.6 root 3148: #define GEN_LDUF(name, ldop, opc, type) \
1.1.1.7 root 3149: static void glue(gen_, name##u)(DisasContext *ctx) \
1.1 root 3150: { \
1.1.1.6 root 3151: TCGv EA; \
1.1.1.5 root 3152: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3153: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3154: return; \
3155: } \
1.1.1.5 root 3156: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3157: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3158: return; \
3159: } \
1.1.1.6 root 3160: gen_set_access_type(ctx, ACCESS_FLOAT); \
3161: EA = tcg_temp_new(); \
3162: gen_addr_imm_index(ctx, EA, 0); \
3163: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3164: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3165: tcg_temp_free(EA); \
1.1 root 3166: }
3167:
1.1.1.6 root 3168: #define GEN_LDUXF(name, ldop, opc, type) \
1.1.1.7 root 3169: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 3170: { \
1.1.1.6 root 3171: TCGv EA; \
1.1.1.5 root 3172: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3173: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3174: return; \
3175: } \
1.1.1.5 root 3176: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3177: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3178: return; \
3179: } \
1.1.1.6 root 3180: gen_set_access_type(ctx, ACCESS_FLOAT); \
3181: EA = tcg_temp_new(); \
3182: gen_addr_reg_index(ctx, EA); \
3183: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3184: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3185: tcg_temp_free(EA); \
1.1 root 3186: }
3187:
1.1.1.6 root 3188: #define GEN_LDXF(name, ldop, opc2, opc3, type) \
1.1.1.7 root 3189: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1 root 3190: { \
1.1.1.6 root 3191: TCGv EA; \
1.1.1.5 root 3192: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3193: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3194: return; \
3195: } \
1.1.1.6 root 3196: gen_set_access_type(ctx, ACCESS_FLOAT); \
3197: EA = tcg_temp_new(); \
3198: gen_addr_reg_index(ctx, EA); \
3199: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3200: tcg_temp_free(EA); \
3201: }
3202:
3203: #define GEN_LDFS(name, ldop, op, type) \
3204: GEN_LDF(name, ldop, op | 0x20, type); \
3205: GEN_LDUF(name, ldop, op | 0x21, type); \
3206: GEN_LDUXF(name, ldop, op | 0x01, type); \
3207: GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3208:
1.1.1.8 ! root 3209: static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 3210: {
3211: TCGv t0 = tcg_temp_new();
3212: TCGv_i32 t1 = tcg_temp_new_i32();
3213: gen_qemu_ld32u(ctx, t0, arg2);
3214: tcg_gen_trunc_tl_i32(t1, t0);
3215: tcg_temp_free(t0);
3216: gen_helper_float32_to_float64(arg1, t1);
3217: tcg_temp_free_i32(t1);
3218: }
3219:
3220: /* lfd lfdu lfdux lfdx */
3221: GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3222: /* lfs lfsu lfsux lfsx */
3223: GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
1.1 root 3224:
3225: /*** Floating-point store ***/
1.1.1.6 root 3226: #define GEN_STF(name, stop, opc, type) \
1.1.1.7 root 3227: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 3228: { \
1.1.1.6 root 3229: TCGv EA; \
1.1.1.5 root 3230: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3231: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1.1.5 root 3232: return; \
1.1 root 3233: } \
1.1.1.6 root 3234: gen_set_access_type(ctx, ACCESS_FLOAT); \
3235: EA = tcg_temp_new(); \
3236: gen_addr_imm_index(ctx, EA, 0); \
3237: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3238: tcg_temp_free(EA); \
1.1 root 3239: }
3240:
1.1.1.6 root 3241: #define GEN_STUF(name, stop, opc, type) \
1.1.1.7 root 3242: static void glue(gen_, name##u)(DisasContext *ctx) \
1.1 root 3243: { \
1.1.1.6 root 3244: TCGv EA; \
1.1.1.5 root 3245: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3246: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3247: return; \
3248: } \
1.1.1.5 root 3249: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3250: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3251: return; \
3252: } \
1.1.1.6 root 3253: gen_set_access_type(ctx, ACCESS_FLOAT); \
3254: EA = tcg_temp_new(); \
3255: gen_addr_imm_index(ctx, EA, 0); \
3256: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3257: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3258: tcg_temp_free(EA); \
1.1 root 3259: }
3260:
1.1.1.6 root 3261: #define GEN_STUXF(name, stop, opc, type) \
1.1.1.7 root 3262: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 3263: { \
1.1.1.6 root 3264: TCGv EA; \
1.1.1.5 root 3265: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3266: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3267: return; \
3268: } \
1.1.1.5 root 3269: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3270: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3271: return; \
3272: } \
1.1.1.6 root 3273: gen_set_access_type(ctx, ACCESS_FLOAT); \
3274: EA = tcg_temp_new(); \
3275: gen_addr_reg_index(ctx, EA); \
3276: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3277: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3278: tcg_temp_free(EA); \
1.1 root 3279: }
3280:
1.1.1.6 root 3281: #define GEN_STXF(name, stop, opc2, opc3, type) \
1.1.1.7 root 3282: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1 root 3283: { \
1.1.1.6 root 3284: TCGv EA; \
1.1.1.5 root 3285: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3286: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3287: return; \
3288: } \
1.1.1.6 root 3289: gen_set_access_type(ctx, ACCESS_FLOAT); \
3290: EA = tcg_temp_new(); \
3291: gen_addr_reg_index(ctx, EA); \
3292: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3293: tcg_temp_free(EA); \
3294: }
3295:
3296: #define GEN_STFS(name, stop, op, type) \
3297: GEN_STF(name, stop, op | 0x20, type); \
3298: GEN_STUF(name, stop, op | 0x21, type); \
3299: GEN_STUXF(name, stop, op | 0x01, type); \
3300: GEN_STXF(name, stop, 0x17, op | 0x00, type)
3301:
1.1.1.8 ! root 3302: static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 3303: {
3304: TCGv_i32 t0 = tcg_temp_new_i32();
3305: TCGv t1 = tcg_temp_new();
3306: gen_helper_float64_to_float32(t0, arg1);
3307: tcg_gen_extu_i32_tl(t1, t0);
3308: tcg_temp_free_i32(t0);
3309: gen_qemu_st32(ctx, t1, arg2);
3310: tcg_temp_free(t1);
1.1 root 3311: }
3312:
3313: /* stfd stfdu stfdux stfdx */
1.1.1.6 root 3314: GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
1.1 root 3315: /* stfs stfsu stfsux stfsx */
1.1.1.6 root 3316: GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
1.1 root 3317:
3318: /* Optional: */
1.1.1.8 ! root 3319: static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 3320: {
3321: TCGv t0 = tcg_temp_new();
3322: tcg_gen_trunc_i64_tl(t0, arg1),
3323: gen_qemu_st32(ctx, t0, arg2);
3324: tcg_temp_free(t0);
3325: }
1.1 root 3326: /* stfiwx */
1.1.1.6 root 3327: GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
1.1 root 3328:
3329: /*** Branch ***/
1.1.1.8 ! root 3330: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 3331: {
3332: TranslationBlock *tb;
3333: tb = ctx->tb;
1.1.1.5 root 3334: #if defined(TARGET_PPC64)
1.1.1.6 root 3335: if (!ctx->sf_mode)
3336: dest = (uint32_t) dest;
1.1.1.5 root 3337: #endif
1.1.1.6 root 3338: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3339: likely(!ctx->singlestep_enabled)) {
3340: tcg_gen_goto_tb(n);
3341: tcg_gen_movi_tl(cpu_nip, dest & ~3);
3342: tcg_gen_exit_tb((long)tb + n);
1.1.1.2 root 3343: } else {
1.1.1.6 root 3344: tcg_gen_movi_tl(cpu_nip, dest & ~3);
3345: if (unlikely(ctx->singlestep_enabled)) {
3346: if ((ctx->singlestep_enabled &
3347: (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3348: ctx->exception == POWERPC_EXCP_BRANCH) {
3349: target_ulong tmp = ctx->nip;
3350: ctx->nip = dest;
3351: gen_exception(ctx, POWERPC_EXCP_TRACE);
3352: ctx->nip = tmp;
3353: }
3354: if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3355: gen_debug_exception(ctx);
3356: }
3357: }
3358: tcg_gen_exit_tb(0);
1.1.1.2 root 3359: }
3360: }
3361:
1.1.1.8 ! root 3362: static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
1.1.1.5 root 3363: {
3364: #if defined(TARGET_PPC64)
1.1.1.6 root 3365: if (ctx->sf_mode == 0)
3366: tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
1.1.1.5 root 3367: else
3368: #endif
1.1.1.6 root 3369: tcg_gen_movi_tl(cpu_lr, nip);
1.1.1.5 root 3370: }
3371:
1.1 root 3372: /* b ba bl bla */
1.1.1.7 root 3373: static void gen_b(DisasContext *ctx)
1.1 root 3374: {
1.1.1.5 root 3375: target_ulong li, target;
1.1 root 3376:
1.1.1.6 root 3377: ctx->exception = POWERPC_EXCP_BRANCH;
1.1 root 3378: /* sign extend LI */
1.1.1.5 root 3379: #if defined(TARGET_PPC64)
3380: if (ctx->sf_mode)
3381: li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3382: else
3383: #endif
3384: li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3385: if (likely(AA(ctx->opcode) == 0))
1.1 root 3386: target = ctx->nip + li - 4;
3387: else
3388: target = li;
1.1.1.5 root 3389: if (LK(ctx->opcode))
3390: gen_setlr(ctx, ctx->nip);
1.1.1.2 root 3391: gen_goto_tb(ctx, 0, target);
1.1 root 3392: }
3393:
3394: #define BCOND_IM 0
3395: #define BCOND_LR 1
3396: #define BCOND_CTR 2
3397:
1.1.1.8 ! root 3398: static inline void gen_bcond(DisasContext *ctx, int type)
1.1.1.5 root 3399: {
3400: uint32_t bo = BO(ctx->opcode);
1.1.1.6 root 3401: int l1 = gen_new_label();
3402: TCGv target;
1.1 root 3403:
1.1.1.6 root 3404: ctx->exception = POWERPC_EXCP_BRANCH;
3405: if (type == BCOND_LR || type == BCOND_CTR) {
3406: target = tcg_temp_local_new();
3407: if (type == BCOND_CTR)
3408: tcg_gen_mov_tl(target, cpu_ctr);
3409: else
3410: tcg_gen_mov_tl(target, cpu_lr);
1.1.1.7 root 3411: } else {
3412: TCGV_UNUSED(target);
1.1 root 3413: }
1.1.1.5 root 3414: if (LK(ctx->opcode))
3415: gen_setlr(ctx, ctx->nip);
1.1.1.6 root 3416: l1 = gen_new_label();
3417: if ((bo & 0x4) == 0) {
3418: /* Decrement and test CTR */
3419: TCGv temp = tcg_temp_new();
3420: if (unlikely(type == BCOND_CTR)) {
3421: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3422: return;
3423: }
3424: tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
1.1.1.5 root 3425: #if defined(TARGET_PPC64)
1.1.1.6 root 3426: if (!ctx->sf_mode)
3427: tcg_gen_ext32u_tl(temp, cpu_ctr);
3428: else
1.1.1.5 root 3429: #endif
1.1.1.6 root 3430: tcg_gen_mov_tl(temp, cpu_ctr);
3431: if (bo & 0x2) {
3432: tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3433: } else {
3434: tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
1.1 root 3435: }
1.1.1.6 root 3436: tcg_temp_free(temp);
3437: }
3438: if ((bo & 0x10) == 0) {
3439: /* Test CR */
3440: uint32_t bi = BI(ctx->opcode);
3441: uint32_t mask = 1 << (3 - (bi & 0x03));
3442: TCGv_i32 temp = tcg_temp_new_i32();
3443:
1.1.1.5 root 3444: if (bo & 0x8) {
1.1.1.6 root 3445: tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3446: tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
1.1.1.5 root 3447: } else {
1.1.1.6 root 3448: tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3449: tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
1.1.1.5 root 3450: }
1.1.1.6 root 3451: tcg_temp_free_i32(temp);
1.1.1.5 root 3452: }
1.1 root 3453: if (type == BCOND_IM) {
1.1.1.6 root 3454: target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3455: if (likely(AA(ctx->opcode) == 0)) {
3456: gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3457: } else {
3458: gen_goto_tb(ctx, 0, li);
3459: }
1.1.1.2 root 3460: gen_set_label(l1);
3461: gen_goto_tb(ctx, 1, ctx->nip);
1.1 root 3462: } else {
1.1.1.5 root 3463: #if defined(TARGET_PPC64)
1.1.1.6 root 3464: if (!(ctx->sf_mode))
3465: tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3466: else
3467: #endif
3468: tcg_gen_andi_tl(cpu_nip, target, ~3);
3469: tcg_gen_exit_tb(0);
3470: gen_set_label(l1);
3471: #if defined(TARGET_PPC64)
3472: if (!(ctx->sf_mode))
3473: tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
1.1.1.5 root 3474: else
3475: #endif
1.1.1.6 root 3476: tcg_gen_movi_tl(cpu_nip, ctx->nip);
3477: tcg_gen_exit_tb(0);
1.1 root 3478: }
3479: }
3480:
1.1.1.7 root 3481: static void gen_bc(DisasContext *ctx)
1.1.1.5 root 3482: {
1.1 root 3483: gen_bcond(ctx, BCOND_IM);
3484: }
3485:
1.1.1.7 root 3486: static void gen_bcctr(DisasContext *ctx)
1.1.1.5 root 3487: {
1.1 root 3488: gen_bcond(ctx, BCOND_CTR);
3489: }
3490:
1.1.1.7 root 3491: static void gen_bclr(DisasContext *ctx)
1.1.1.5 root 3492: {
1.1 root 3493: gen_bcond(ctx, BCOND_LR);
3494: }
3495:
3496: /*** Condition register logical ***/
1.1.1.6 root 3497: #define GEN_CRLOGIC(name, tcg_op, opc) \
1.1.1.7 root 3498: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 3499: { \
1.1.1.5 root 3500: uint8_t bitmask; \
3501: int sh; \
1.1.1.6 root 3502: TCGv_i32 t0, t1; \
1.1.1.5 root 3503: sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
1.1.1.6 root 3504: t0 = tcg_temp_new_i32(); \
1.1.1.5 root 3505: if (sh > 0) \
1.1.1.6 root 3506: tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
1.1.1.5 root 3507: else if (sh < 0) \
1.1.1.6 root 3508: tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
3509: else \
3510: tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
3511: t1 = tcg_temp_new_i32(); \
1.1.1.5 root 3512: sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3513: if (sh > 0) \
1.1.1.6 root 3514: tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
1.1.1.5 root 3515: else if (sh < 0) \
1.1.1.6 root 3516: tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
3517: else \
3518: tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
3519: tcg_op(t0, t0, t1); \
1.1.1.5 root 3520: bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
1.1.1.6 root 3521: tcg_gen_andi_i32(t0, t0, bitmask); \
3522: tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
3523: tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
3524: tcg_temp_free_i32(t0); \
3525: tcg_temp_free_i32(t1); \
1.1 root 3526: }
3527:
3528: /* crand */
1.1.1.6 root 3529: GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
1.1 root 3530: /* crandc */
1.1.1.6 root 3531: GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
1.1 root 3532: /* creqv */
1.1.1.6 root 3533: GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
1.1 root 3534: /* crnand */
1.1.1.6 root 3535: GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
1.1 root 3536: /* crnor */
1.1.1.6 root 3537: GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
1.1 root 3538: /* cror */
1.1.1.6 root 3539: GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
1.1 root 3540: /* crorc */
1.1.1.6 root 3541: GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
1.1 root 3542: /* crxor */
1.1.1.6 root 3543: GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
1.1.1.7 root 3544:
1.1 root 3545: /* mcrf */
1.1.1.7 root 3546: static void gen_mcrf(DisasContext *ctx)
1.1 root 3547: {
1.1.1.6 root 3548: tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
1.1 root 3549: }
3550:
3551: /*** System linkage ***/
1.1.1.7 root 3552:
1.1.1.6 root 3553: /* rfi (mem_idx only) */
1.1.1.7 root 3554: static void gen_rfi(DisasContext *ctx)
1.1 root 3555: {
3556: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3557: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3558: #else
3559: /* Restore CPU state */
1.1.1.6 root 3560: if (unlikely(!ctx->mem_idx)) {
3561: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3562: return;
3563: }
1.1.1.6 root 3564: gen_helper_rfi();
3565: gen_sync_exception(ctx);
1.1 root 3566: #endif
3567: }
3568:
1.1.1.5 root 3569: #if defined(TARGET_PPC64)
1.1.1.7 root 3570: static void gen_rfid(DisasContext *ctx)
1.1.1.5 root 3571: {
3572: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3573: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3574: #else
3575: /* Restore CPU state */
1.1.1.6 root 3576: if (unlikely(!ctx->mem_idx)) {
3577: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3578: return;
3579: }
1.1.1.6 root 3580: gen_helper_rfid();
3581: gen_sync_exception(ctx);
1.1.1.5 root 3582: #endif
3583: }
3584:
1.1.1.7 root 3585: static void gen_hrfid(DisasContext *ctx)
1.1 root 3586: {
3587: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3588: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3589: #else
3590: /* Restore CPU state */
1.1.1.6 root 3591: if (unlikely(ctx->mem_idx <= 1)) {
3592: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3593: return;
3594: }
1.1.1.6 root 3595: gen_helper_hrfid();
3596: gen_sync_exception(ctx);
1.1.1.5 root 3597: #endif
3598: }
3599: #endif
3600:
3601: /* sc */
3602: #if defined(CONFIG_USER_ONLY)
3603: #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
1.1 root 3604: #else
1.1.1.5 root 3605: #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
1.1 root 3606: #endif
1.1.1.7 root 3607: static void gen_sc(DisasContext *ctx)
1.1.1.5 root 3608: {
3609: uint32_t lev;
3610:
3611: lev = (ctx->opcode >> 5) & 0x7F;
1.1.1.6 root 3612: gen_exception_err(ctx, POWERPC_SYSCALL, lev);
1.1 root 3613: }
3614:
3615: /*** Trap ***/
1.1.1.7 root 3616:
1.1 root 3617: /* tw */
1.1.1.7 root 3618: static void gen_tw(DisasContext *ctx)
1.1 root 3619: {
1.1.1.6 root 3620: TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
1.1.1.4 root 3621: /* Update the nip since this might generate a trap exception */
1.1.1.5 root 3622: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3623: gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3624: tcg_temp_free_i32(t0);
1.1 root 3625: }
3626:
3627: /* twi */
1.1.1.7 root 3628: static void gen_twi(DisasContext *ctx)
1.1 root 3629: {
1.1.1.6 root 3630: TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3631: TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
1.1.1.5 root 3632: /* Update the nip since this might generate a trap exception */
3633: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3634: gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3635: tcg_temp_free(t0);
3636: tcg_temp_free_i32(t1);
1.1 root 3637: }
3638:
1.1.1.5 root 3639: #if defined(TARGET_PPC64)
3640: /* td */
1.1.1.7 root 3641: static void gen_td(DisasContext *ctx)
1.1 root 3642: {
1.1.1.6 root 3643: TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
1.1.1.5 root 3644: /* Update the nip since this might generate a trap exception */
3645: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3646: gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3647: tcg_temp_free_i32(t0);
1.1.1.5 root 3648: }
1.1 root 3649:
1.1.1.5 root 3650: /* tdi */
1.1.1.7 root 3651: static void gen_tdi(DisasContext *ctx)
1.1.1.5 root 3652: {
1.1.1.6 root 3653: TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3654: TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
1.1.1.5 root 3655: /* Update the nip since this might generate a trap exception */
3656: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3657: gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3658: tcg_temp_free(t0);
3659: tcg_temp_free_i32(t1);
1.1 root 3660: }
1.1.1.5 root 3661: #endif
1.1 root 3662:
1.1.1.5 root 3663: /*** Processor control ***/
1.1.1.7 root 3664:
1.1 root 3665: /* mcrxr */
1.1.1.7 root 3666: static void gen_mcrxr(DisasContext *ctx)
1.1 root 3667: {
1.1.1.6 root 3668: tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3669: tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3670: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
1.1 root 3671: }
3672:
1.1.1.6 root 3673: /* mfcr mfocrf */
1.1.1.7 root 3674: static void gen_mfcr(DisasContext *ctx)
1.1 root 3675: {
1.1.1.5 root 3676: uint32_t crm, crn;
3677:
3678: if (likely(ctx->opcode & 0x00100000)) {
3679: crm = CRM(ctx->opcode);
1.1.1.6 root 3680: if (likely(crm && ((crm & (crm - 1)) == 0))) {
3681: crn = ctz32 (crm);
3682: tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
1.1.1.7 root 3683: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
3684: cpu_gpr[rD(ctx->opcode)], crn * 4);
1.1.1.5 root 3685: }
3686: } else {
1.1.1.7 root 3687: TCGv_i32 t0 = tcg_temp_new_i32();
3688: tcg_gen_mov_i32(t0, cpu_crf[0]);
3689: tcg_gen_shli_i32(t0, t0, 4);
3690: tcg_gen_or_i32(t0, t0, cpu_crf[1]);
3691: tcg_gen_shli_i32(t0, t0, 4);
3692: tcg_gen_or_i32(t0, t0, cpu_crf[2]);
3693: tcg_gen_shli_i32(t0, t0, 4);
3694: tcg_gen_or_i32(t0, t0, cpu_crf[3]);
3695: tcg_gen_shli_i32(t0, t0, 4);
3696: tcg_gen_or_i32(t0, t0, cpu_crf[4]);
3697: tcg_gen_shli_i32(t0, t0, 4);
3698: tcg_gen_or_i32(t0, t0, cpu_crf[5]);
3699: tcg_gen_shli_i32(t0, t0, 4);
3700: tcg_gen_or_i32(t0, t0, cpu_crf[6]);
3701: tcg_gen_shli_i32(t0, t0, 4);
3702: tcg_gen_or_i32(t0, t0, cpu_crf[7]);
3703: tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
3704: tcg_temp_free_i32(t0);
1.1.1.5 root 3705: }
1.1 root 3706: }
3707:
3708: /* mfmsr */
1.1.1.7 root 3709: static void gen_mfmsr(DisasContext *ctx)
1.1 root 3710: {
3711: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3712: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3713: #else
1.1.1.6 root 3714: if (unlikely(!ctx->mem_idx)) {
3715: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3716: return;
3717: }
1.1.1.6 root 3718: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
1.1 root 3719: #endif
3720: }
3721:
1.1.1.5 root 3722: #if 1
3723: #define SPR_NOACCESS ((void *)(-1UL))
1.1 root 3724: #else
3725: static void spr_noaccess (void *opaque, int sprn)
3726: {
3727: sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3728: printf("ERROR: try to access SPR %d !\n", sprn);
3729: }
3730: #define SPR_NOACCESS (&spr_noaccess)
3731: #endif
3732:
3733: /* mfspr */
1.1.1.8 ! root 3734: static inline void gen_op_mfspr(DisasContext *ctx)
1.1 root 3735: {
1.1.1.6 root 3736: void (*read_cb)(void *opaque, int gprn, int sprn);
1.1 root 3737: uint32_t sprn = SPR(ctx->opcode);
3738:
3739: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 root 3740: if (ctx->mem_idx == 2)
1.1.1.5 root 3741: read_cb = ctx->spr_cb[sprn].hea_read;
1.1.1.6 root 3742: else if (ctx->mem_idx)
1.1 root 3743: read_cb = ctx->spr_cb[sprn].oea_read;
3744: else
3745: #endif
3746: read_cb = ctx->spr_cb[sprn].uea_read;
1.1.1.5 root 3747: if (likely(read_cb != NULL)) {
3748: if (likely(read_cb != SPR_NOACCESS)) {
1.1.1.6 root 3749: (*read_cb)(ctx, rD(ctx->opcode), sprn);
1.1 root 3750: } else {
3751: /* Privilege exception */
1.1.1.5 root 3752: /* This is a hack to avoid warnings when running Linux:
3753: * this OS breaks the PowerPC virtualisation model,
3754: * allowing userland application to read the PVR
3755: */
3756: if (sprn != SPR_PVR) {
1.1.1.6 root 3757: qemu_log("Trying to read privileged spr %d %03x at "
1.1.1.8 ! root 3758: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
! 3759: printf("Trying to read privileged spr %d %03x at "
! 3760: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
1.1.1.2 root 3761: }
1.1.1.6 root 3762: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3763: }
3764: } else {
3765: /* Not defined */
1.1.1.6 root 3766: qemu_log("Trying to read invalid spr %d %03x at "
1.1.1.8 ! root 3767: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
! 3768: printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
1.1.1.5 root 3769: sprn, sprn, ctx->nip);
1.1.1.6 root 3770: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
1.1 root 3771: }
3772: }
3773:
1.1.1.7 root 3774: static void gen_mfspr(DisasContext *ctx)
1.1 root 3775: {
3776: gen_op_mfspr(ctx);
1.1.1.5 root 3777: }
1.1 root 3778:
3779: /* mftb */
1.1.1.7 root 3780: static void gen_mftb(DisasContext *ctx)
1.1 root 3781: {
3782: gen_op_mfspr(ctx);
3783: }
3784:
1.1.1.6 root 3785: /* mtcrf mtocrf*/
1.1.1.7 root 3786: static void gen_mtcrf(DisasContext *ctx)
1.1 root 3787: {
1.1.1.5 root 3788: uint32_t crm, crn;
3789:
3790: crm = CRM(ctx->opcode);
1.1.1.6 root 3791: if (likely((ctx->opcode & 0x00100000))) {
3792: if (crm && ((crm & (crm - 1)) == 0)) {
3793: TCGv_i32 temp = tcg_temp_new_i32();
3794: crn = ctz32 (crm);
3795: tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3796: tcg_gen_shri_i32(temp, temp, crn * 4);
3797: tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
3798: tcg_temp_free_i32(temp);
3799: }
1.1.1.5 root 3800: } else {
1.1.1.7 root 3801: TCGv_i32 temp = tcg_temp_new_i32();
3802: tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3803: for (crn = 0 ; crn < 8 ; crn++) {
3804: if (crm & (1 << crn)) {
3805: tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3806: tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3807: }
3808: }
1.1.1.6 root 3809: tcg_temp_free_i32(temp);
1.1.1.5 root 3810: }
1.1 root 3811: }
3812:
3813: /* mtmsr */
1.1.1.5 root 3814: #if defined(TARGET_PPC64)
1.1.1.7 root 3815: static void gen_mtmsrd(DisasContext *ctx)
1.1.1.5 root 3816: {
3817: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3818: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3819: #else
1.1.1.6 root 3820: if (unlikely(!ctx->mem_idx)) {
3821: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3822: return;
3823: }
3824: if (ctx->opcode & 0x00010000) {
3825: /* Special form that does not need any synchronisation */
1.1.1.6 root 3826: TCGv t0 = tcg_temp_new();
3827: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3828: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3829: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3830: tcg_temp_free(t0);
1.1.1.5 root 3831: } else {
3832: /* XXX: we need to update nip before the store
3833: * if we enter power saving mode, we will exit the loop
3834: * directly from ppc_store_msr
3835: */
3836: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3837: gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 3838: /* Must stop the translation as machine state (may have) changed */
3839: /* Note that mtmsr is not always defined as context-synchronizing */
1.1.1.6 root 3840: gen_stop_exception(ctx);
1.1.1.5 root 3841: }
3842: #endif
3843: }
3844: #endif
3845:
1.1.1.7 root 3846: static void gen_mtmsr(DisasContext *ctx)
1.1 root 3847: {
3848: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3849: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3850: #else
1.1.1.6 root 3851: if (unlikely(!ctx->mem_idx)) {
3852: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3853: return;
3854: }
1.1.1.5 root 3855: if (ctx->opcode & 0x00010000) {
3856: /* Special form that does not need any synchronisation */
1.1.1.6 root 3857: TCGv t0 = tcg_temp_new();
3858: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3859: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3860: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3861: tcg_temp_free(t0);
1.1.1.5 root 3862: } else {
3863: /* XXX: we need to update nip before the store
3864: * if we enter power saving mode, we will exit the loop
3865: * directly from ppc_store_msr
3866: */
3867: gen_update_nip(ctx, ctx->nip);
3868: #if defined(TARGET_PPC64)
1.1.1.6 root 3869: if (!ctx->sf_mode) {
3870: TCGv t0 = tcg_temp_new();
3871: TCGv t1 = tcg_temp_new();
3872: tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
3873: tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
3874: tcg_gen_or_tl(t0, t0, t1);
3875: tcg_temp_free(t1);
3876: gen_helper_store_msr(t0);
3877: tcg_temp_free(t0);
3878: } else
1.1.1.5 root 3879: #endif
1.1.1.6 root 3880: gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 3881: /* Must stop the translation as machine state (may have) changed */
1.1.1.6 root 3882: /* Note that mtmsr is not always defined as context-synchronizing */
3883: gen_stop_exception(ctx);
1.1.1.5 root 3884: }
1.1 root 3885: #endif
3886: }
3887:
3888: /* mtspr */
1.1.1.7 root 3889: static void gen_mtspr(DisasContext *ctx)
1.1 root 3890: {
1.1.1.6 root 3891: void (*write_cb)(void *opaque, int sprn, int gprn);
1.1 root 3892: uint32_t sprn = SPR(ctx->opcode);
3893:
3894: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 root 3895: if (ctx->mem_idx == 2)
1.1.1.5 root 3896: write_cb = ctx->spr_cb[sprn].hea_write;
1.1.1.6 root 3897: else if (ctx->mem_idx)
1.1 root 3898: write_cb = ctx->spr_cb[sprn].oea_write;
3899: else
3900: #endif
3901: write_cb = ctx->spr_cb[sprn].uea_write;
1.1.1.5 root 3902: if (likely(write_cb != NULL)) {
3903: if (likely(write_cb != SPR_NOACCESS)) {
1.1.1.6 root 3904: (*write_cb)(ctx, sprn, rS(ctx->opcode));
1.1 root 3905: } else {
3906: /* Privilege exception */
1.1.1.6 root 3907: qemu_log("Trying to write privileged spr %d %03x at "
1.1.1.8 ! root 3908: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
! 3909: printf("Trying to write privileged spr %d %03x at " TARGET_FMT_lx
! 3910: "\n", sprn, sprn, ctx->nip);
1.1.1.6 root 3911: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3912: }
1.1 root 3913: } else {
3914: /* Not defined */
1.1.1.6 root 3915: qemu_log("Trying to write invalid spr %d %03x at "
1.1.1.8 ! root 3916: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
! 3917: printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
1.1.1.5 root 3918: sprn, sprn, ctx->nip);
1.1.1.6 root 3919: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
1.1 root 3920: }
3921: }
3922:
3923: /*** Cache management ***/
1.1.1.7 root 3924:
1.1 root 3925: /* dcbf */
1.1.1.7 root 3926: static void gen_dcbf(DisasContext *ctx)
1.1 root 3927: {
1.1.1.5 root 3928: /* XXX: specification says this is treated as a load by the MMU */
1.1.1.6 root 3929: TCGv t0;
3930: gen_set_access_type(ctx, ACCESS_CACHE);
3931: t0 = tcg_temp_new();
3932: gen_addr_reg_index(ctx, t0);
3933: gen_qemu_ld8u(ctx, t0, t0);
3934: tcg_temp_free(t0);
1.1 root 3935: }
3936:
3937: /* dcbi (Supervisor only) */
1.1.1.7 root 3938: static void gen_dcbi(DisasContext *ctx)
1.1 root 3939: {
3940: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3941: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3942: #else
1.1.1.6 root 3943: TCGv EA, val;
3944: if (unlikely(!ctx->mem_idx)) {
3945: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3946: return;
3947: }
1.1.1.6 root 3948: EA = tcg_temp_new();
3949: gen_set_access_type(ctx, ACCESS_CACHE);
3950: gen_addr_reg_index(ctx, EA);
3951: val = tcg_temp_new();
1.1.1.5 root 3952: /* XXX: specification says this should be treated as a store by the MMU */
1.1.1.6 root 3953: gen_qemu_ld8u(ctx, val, EA);
3954: gen_qemu_st8(ctx, val, EA);
3955: tcg_temp_free(val);
3956: tcg_temp_free(EA);
1.1 root 3957: #endif
3958: }
3959:
3960: /* dcdst */
1.1.1.7 root 3961: static void gen_dcbst(DisasContext *ctx)
1.1 root 3962: {
1.1.1.5 root 3963: /* XXX: specification say this is treated as a load by the MMU */
1.1.1.6 root 3964: TCGv t0;
3965: gen_set_access_type(ctx, ACCESS_CACHE);
3966: t0 = tcg_temp_new();
3967: gen_addr_reg_index(ctx, t0);
3968: gen_qemu_ld8u(ctx, t0, t0);
3969: tcg_temp_free(t0);
1.1 root 3970: }
3971:
3972: /* dcbt */
1.1.1.7 root 3973: static void gen_dcbt(DisasContext *ctx)
1.1 root 3974: {
1.1.1.5 root 3975: /* interpreted as no-op */
3976: /* XXX: specification say this is treated as a load by the MMU
3977: * but does not generate any exception
3978: */
1.1 root 3979: }
3980:
3981: /* dcbtst */
1.1.1.7 root 3982: static void gen_dcbtst(DisasContext *ctx)
1.1 root 3983: {
1.1.1.5 root 3984: /* interpreted as no-op */
3985: /* XXX: specification say this is treated as a load by the MMU
3986: * but does not generate any exception
3987: */
1.1 root 3988: }
3989:
3990: /* dcbz */
1.1.1.7 root 3991: static void gen_dcbz(DisasContext *ctx)
1.1.1.6 root 3992: {
3993: TCGv t0;
3994: gen_set_access_type(ctx, ACCESS_CACHE);
3995: /* NIP cannot be restored if the memory exception comes from an helper */
3996: gen_update_nip(ctx, ctx->nip - 4);
3997: t0 = tcg_temp_new();
3998: gen_addr_reg_index(ctx, t0);
3999: gen_helper_dcbz(t0);
4000: tcg_temp_free(t0);
4001: }
1.1 root 4002:
1.1.1.7 root 4003: static void gen_dcbz_970(DisasContext *ctx)
1.1 root 4004: {
1.1.1.6 root 4005: TCGv t0;
4006: gen_set_access_type(ctx, ACCESS_CACHE);
4007: /* NIP cannot be restored if the memory exception comes from an helper */
4008: gen_update_nip(ctx, ctx->nip - 4);
4009: t0 = tcg_temp_new();
4010: gen_addr_reg_index(ctx, t0);
4011: if (ctx->opcode & 0x00200000)
4012: gen_helper_dcbz(t0);
4013: else
4014: gen_helper_dcbz_970(t0);
4015: tcg_temp_free(t0);
4016: }
1.1.1.5 root 4017:
1.1.1.6 root 4018: /* dst / dstt */
1.1.1.7 root 4019: static void gen_dst(DisasContext *ctx)
1.1.1.6 root 4020: {
4021: if (rA(ctx->opcode) == 0) {
4022: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4023: } else {
4024: /* interpreted as no-op */
1.1 root 4025: }
1.1.1.5 root 4026: }
4027:
1.1.1.6 root 4028: /* dstst /dststt */
1.1.1.7 root 4029: static void gen_dstst(DisasContext *ctx)
1.1.1.5 root 4030: {
1.1.1.6 root 4031: if (rA(ctx->opcode) == 0) {
4032: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4033: } else {
4034: /* interpreted as no-op */
4035: }
4036:
1.1.1.5 root 4037: }
4038:
1.1.1.6 root 4039: /* dss / dssall */
1.1.1.7 root 4040: static void gen_dss(DisasContext *ctx)
1.1.1.5 root 4041: {
1.1.1.6 root 4042: /* interpreted as no-op */
1.1 root 4043: }
4044:
4045: /* icbi */
1.1.1.7 root 4046: static void gen_icbi(DisasContext *ctx)
1.1 root 4047: {
1.1.1.6 root 4048: TCGv t0;
4049: gen_set_access_type(ctx, ACCESS_CACHE);
1.1.1.5 root 4050: /* NIP cannot be restored if the memory exception comes from an helper */
4051: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 4052: t0 = tcg_temp_new();
4053: gen_addr_reg_index(ctx, t0);
4054: gen_helper_icbi(t0);
4055: tcg_temp_free(t0);
1.1 root 4056: }
4057:
4058: /* Optional: */
4059: /* dcba */
1.1.1.7 root 4060: static void gen_dcba(DisasContext *ctx)
1.1 root 4061: {
1.1.1.5 root 4062: /* interpreted as no-op */
4063: /* XXX: specification say this is treated as a store by the MMU
4064: * but does not generate any exception
4065: */
1.1 root 4066: }
4067:
4068: /*** Segment register manipulation ***/
4069: /* Supervisor only: */
1.1.1.7 root 4070:
1.1 root 4071: /* mfsr */
1.1.1.7 root 4072: static void gen_mfsr(DisasContext *ctx)
1.1 root 4073: {
4074: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4075: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4076: #else
1.1.1.6 root 4077: TCGv t0;
4078: if (unlikely(!ctx->mem_idx)) {
4079: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4080: return;
4081: }
1.1.1.6 root 4082: t0 = tcg_const_tl(SR(ctx->opcode));
4083: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4084: tcg_temp_free(t0);
1.1 root 4085: #endif
4086: }
4087:
4088: /* mfsrin */
1.1.1.7 root 4089: static void gen_mfsrin(DisasContext *ctx)
1.1 root 4090: {
4091: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4092: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4093: #else
1.1.1.6 root 4094: TCGv t0;
4095: if (unlikely(!ctx->mem_idx)) {
4096: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4097: return;
4098: }
1.1.1.6 root 4099: t0 = tcg_temp_new();
4100: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4101: tcg_gen_andi_tl(t0, t0, 0xF);
4102: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4103: tcg_temp_free(t0);
1.1 root 4104: #endif
4105: }
4106:
4107: /* mtsr */
1.1.1.7 root 4108: static void gen_mtsr(DisasContext *ctx)
1.1 root 4109: {
4110: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4111: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4112: #else
1.1.1.6 root 4113: TCGv t0;
4114: if (unlikely(!ctx->mem_idx)) {
4115: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4116: return;
4117: }
1.1.1.6 root 4118: t0 = tcg_const_tl(SR(ctx->opcode));
4119: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4120: tcg_temp_free(t0);
1.1 root 4121: #endif
4122: }
4123:
4124: /* mtsrin */
1.1.1.7 root 4125: static void gen_mtsrin(DisasContext *ctx)
1.1 root 4126: {
4127: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4128: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4129: #else
1.1.1.6 root 4130: TCGv t0;
4131: if (unlikely(!ctx->mem_idx)) {
4132: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4133: return;
4134: }
1.1.1.6 root 4135: t0 = tcg_temp_new();
4136: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4137: tcg_gen_andi_tl(t0, t0, 0xF);
4138: gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4139: tcg_temp_free(t0);
1.1 root 4140: #endif
4141: }
4142:
1.1.1.5 root 4143: #if defined(TARGET_PPC64)
4144: /* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
1.1.1.7 root 4145:
1.1.1.5 root 4146: /* mfsr */
1.1.1.7 root 4147: static void gen_mfsr_64b(DisasContext *ctx)
1.1 root 4148: {
4149: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4150: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4151: #else
1.1.1.6 root 4152: TCGv t0;
4153: if (unlikely(!ctx->mem_idx)) {
4154: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4155: return;
4156: }
1.1.1.6 root 4157: t0 = tcg_const_tl(SR(ctx->opcode));
1.1.1.7 root 4158: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.6 root 4159: tcg_temp_free(t0);
1.1.1.5 root 4160: #endif
4161: }
4162:
4163: /* mfsrin */
1.1.1.7 root 4164: static void gen_mfsrin_64b(DisasContext *ctx)
1.1.1.5 root 4165: {
4166: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4167: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4168: #else
1.1.1.6 root 4169: TCGv t0;
4170: if (unlikely(!ctx->mem_idx)) {
4171: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4172: return;
4173: }
1.1.1.6 root 4174: t0 = tcg_temp_new();
4175: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4176: tcg_gen_andi_tl(t0, t0, 0xF);
1.1.1.7 root 4177: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.6 root 4178: tcg_temp_free(t0);
1.1.1.5 root 4179: #endif
4180: }
4181:
4182: /* mtsr */
1.1.1.7 root 4183: static void gen_mtsr_64b(DisasContext *ctx)
1.1.1.5 root 4184: {
4185: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4186: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4187: #else
1.1.1.6 root 4188: TCGv t0;
4189: if (unlikely(!ctx->mem_idx)) {
4190: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4191: return;
4192: }
1.1.1.6 root 4193: t0 = tcg_const_tl(SR(ctx->opcode));
1.1.1.7 root 4194: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
1.1.1.6 root 4195: tcg_temp_free(t0);
1.1.1.5 root 4196: #endif
4197: }
4198:
4199: /* mtsrin */
1.1.1.7 root 4200: static void gen_mtsrin_64b(DisasContext *ctx)
1.1.1.5 root 4201: {
4202: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4203: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4204: #else
1.1.1.6 root 4205: TCGv t0;
4206: if (unlikely(!ctx->mem_idx)) {
4207: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4208: return;
4209: }
1.1.1.6 root 4210: t0 = tcg_temp_new();
4211: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4212: tcg_gen_andi_tl(t0, t0, 0xF);
1.1.1.7 root 4213: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
1.1.1.6 root 4214: tcg_temp_free(t0);
1.1.1.5 root 4215: #endif
4216: }
1.1.1.7 root 4217:
4218: /* slbmte */
4219: static void gen_slbmte(DisasContext *ctx)
4220: {
4221: #if defined(CONFIG_USER_ONLY)
4222: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4223: #else
4224: if (unlikely(!ctx->mem_idx)) {
4225: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4226: return;
4227: }
4228: gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
4229: #endif
4230: }
4231:
1.1.1.5 root 4232: #endif /* defined(TARGET_PPC64) */
4233:
4234: /*** Lookaside buffer management ***/
1.1.1.6 root 4235: /* Optional & mem_idx only: */
1.1.1.7 root 4236:
1.1.1.5 root 4237: /* tlbia */
1.1.1.7 root 4238: static void gen_tlbia(DisasContext *ctx)
1.1.1.5 root 4239: {
4240: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4241: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4242: #else
1.1.1.6 root 4243: if (unlikely(!ctx->mem_idx)) {
4244: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4245: return;
4246: }
1.1.1.6 root 4247: gen_helper_tlbia();
1.1 root 4248: #endif
4249: }
4250:
1.1.1.7 root 4251: /* tlbiel */
4252: static void gen_tlbiel(DisasContext *ctx)
4253: {
4254: #if defined(CONFIG_USER_ONLY)
4255: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4256: #else
4257: if (unlikely(!ctx->mem_idx)) {
4258: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4259: return;
4260: }
4261: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4262: #endif
4263: }
4264:
1.1 root 4265: /* tlbie */
1.1.1.7 root 4266: static void gen_tlbie(DisasContext *ctx)
1.1.1.5 root 4267: {
4268: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4269: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4270: #else
1.1.1.6 root 4271: if (unlikely(!ctx->mem_idx)) {
4272: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4273: return;
4274: }
4275: #if defined(TARGET_PPC64)
1.1.1.6 root 4276: if (!ctx->sf_mode) {
4277: TCGv t0 = tcg_temp_new();
4278: tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4279: gen_helper_tlbie(t0);
4280: tcg_temp_free(t0);
4281: } else
1.1.1.5 root 4282: #endif
1.1.1.6 root 4283: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4284: #endif
4285: }
4286:
4287: /* tlbsync */
1.1.1.7 root 4288: static void gen_tlbsync(DisasContext *ctx)
1.1.1.5 root 4289: {
4290: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4291: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4292: #else
1.1.1.6 root 4293: if (unlikely(!ctx->mem_idx)) {
4294: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4295: return;
4296: }
4297: /* This has no effect: it should ensure that all previous
4298: * tlbie have completed
4299: */
1.1.1.6 root 4300: gen_stop_exception(ctx);
1.1.1.5 root 4301: #endif
4302: }
4303:
4304: #if defined(TARGET_PPC64)
4305: /* slbia */
1.1.1.7 root 4306: static void gen_slbia(DisasContext *ctx)
1.1.1.5 root 4307: {
4308: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4309: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4310: #else
1.1.1.6 root 4311: if (unlikely(!ctx->mem_idx)) {
4312: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4313: return;
4314: }
1.1.1.6 root 4315: gen_helper_slbia();
1.1.1.5 root 4316: #endif
4317: }
4318:
4319: /* slbie */
1.1.1.7 root 4320: static void gen_slbie(DisasContext *ctx)
1.1.1.5 root 4321: {
4322: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4323: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4324: #else
1.1.1.6 root 4325: if (unlikely(!ctx->mem_idx)) {
4326: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4327: return;
4328: }
1.1.1.6 root 4329: gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4330: #endif
4331: }
4332: #endif
4333:
4334: /*** External control ***/
4335: /* Optional: */
1.1.1.7 root 4336:
1.1.1.5 root 4337: /* eciwx */
1.1.1.7 root 4338: static void gen_eciwx(DisasContext *ctx)
1.1.1.5 root 4339: {
1.1.1.6 root 4340: TCGv t0;
4341: /* Should check EAR[E] ! */
4342: gen_set_access_type(ctx, ACCESS_EXT);
4343: t0 = tcg_temp_new();
4344: gen_addr_reg_index(ctx, t0);
4345: gen_check_align(ctx, t0, 0x03);
4346: gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4347: tcg_temp_free(t0);
1.1.1.5 root 4348: }
4349:
4350: /* ecowx */
1.1.1.7 root 4351: static void gen_ecowx(DisasContext *ctx)
1.1.1.5 root 4352: {
1.1.1.6 root 4353: TCGv t0;
4354: /* Should check EAR[E] ! */
4355: gen_set_access_type(ctx, ACCESS_EXT);
4356: t0 = tcg_temp_new();
4357: gen_addr_reg_index(ctx, t0);
4358: gen_check_align(ctx, t0, 0x03);
4359: gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4360: tcg_temp_free(t0);
1.1.1.5 root 4361: }
4362:
4363: /* PowerPC 601 specific instructions */
1.1.1.7 root 4364:
1.1.1.5 root 4365: /* abs - abs. */
1.1.1.7 root 4366: static void gen_abs(DisasContext *ctx)
1.1.1.5 root 4367: {
1.1.1.6 root 4368: int l1 = gen_new_label();
4369: int l2 = gen_new_label();
4370: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4371: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4372: tcg_gen_br(l2);
4373: gen_set_label(l1);
4374: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4375: gen_set_label(l2);
1.1.1.5 root 4376: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4377: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4378: }
4379:
4380: /* abso - abso. */
1.1.1.7 root 4381: static void gen_abso(DisasContext *ctx)
1.1.1.5 root 4382: {
1.1.1.6 root 4383: int l1 = gen_new_label();
4384: int l2 = gen_new_label();
4385: int l3 = gen_new_label();
4386: /* Start with XER OV disabled, the most likely case */
4387: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4388: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4389: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4390: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4391: tcg_gen_br(l2);
4392: gen_set_label(l1);
4393: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4394: tcg_gen_br(l3);
4395: gen_set_label(l2);
4396: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4397: gen_set_label(l3);
1.1.1.5 root 4398: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4399: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4400: }
4401:
4402: /* clcs */
1.1.1.7 root 4403: static void gen_clcs(DisasContext *ctx)
1.1.1.5 root 4404: {
1.1.1.6 root 4405: TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4406: gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4407: tcg_temp_free_i32(t0);
1.1.1.5 root 4408: /* Rc=1 sets CR0 to an undefined state */
4409: }
4410:
4411: /* div - div. */
1.1.1.7 root 4412: static void gen_div(DisasContext *ctx)
1.1.1.5 root 4413: {
1.1.1.6 root 4414: gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4415: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4416: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4417: }
4418:
4419: /* divo - divo. */
1.1.1.7 root 4420: static void gen_divo(DisasContext *ctx)
1.1.1.5 root 4421: {
1.1.1.6 root 4422: gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4423: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4424: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4425: }
4426:
4427: /* divs - divs. */
1.1.1.7 root 4428: static void gen_divs(DisasContext *ctx)
1.1.1.5 root 4429: {
1.1.1.6 root 4430: gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4431: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4432: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4433: }
4434:
4435: /* divso - divso. */
1.1.1.7 root 4436: static void gen_divso(DisasContext *ctx)
1.1.1.5 root 4437: {
1.1.1.6 root 4438: gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4439: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4440: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4441: }
4442:
4443: /* doz - doz. */
1.1.1.7 root 4444: static void gen_doz(DisasContext *ctx)
1.1.1.5 root 4445: {
1.1.1.6 root 4446: int l1 = gen_new_label();
4447: int l2 = gen_new_label();
4448: tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4449: tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4450: tcg_gen_br(l2);
4451: gen_set_label(l1);
4452: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4453: gen_set_label(l2);
1.1.1.5 root 4454: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4455: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4456: }
4457:
4458: /* dozo - dozo. */
1.1.1.7 root 4459: static void gen_dozo(DisasContext *ctx)
1.1.1.5 root 4460: {
1.1.1.6 root 4461: int l1 = gen_new_label();
4462: int l2 = gen_new_label();
4463: TCGv t0 = tcg_temp_new();
4464: TCGv t1 = tcg_temp_new();
4465: TCGv t2 = tcg_temp_new();
4466: /* Start with XER OV disabled, the most likely case */
4467: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4468: tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4469: tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4470: tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4471: tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4472: tcg_gen_andc_tl(t1, t1, t2);
4473: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4474: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4475: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4476: tcg_gen_br(l2);
4477: gen_set_label(l1);
4478: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4479: gen_set_label(l2);
4480: tcg_temp_free(t0);
4481: tcg_temp_free(t1);
4482: tcg_temp_free(t2);
1.1.1.5 root 4483: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4484: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4485: }
4486:
4487: /* dozi */
1.1.1.7 root 4488: static void gen_dozi(DisasContext *ctx)
1.1.1.5 root 4489: {
1.1.1.6 root 4490: target_long simm = SIMM(ctx->opcode);
4491: int l1 = gen_new_label();
4492: int l2 = gen_new_label();
4493: tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4494: tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4495: tcg_gen_br(l2);
4496: gen_set_label(l1);
4497: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4498: gen_set_label(l2);
4499: if (unlikely(Rc(ctx->opcode) != 0))
4500: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4501: }
4502:
4503: /* lscbx - lscbx. */
1.1.1.7 root 4504: static void gen_lscbx(DisasContext *ctx)
1.1.1.5 root 4505: {
1.1.1.6 root 4506: TCGv t0 = tcg_temp_new();
4507: TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4508: TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4509: TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
1.1.1.5 root 4510:
1.1.1.6 root 4511: gen_addr_reg_index(ctx, t0);
1.1.1.5 root 4512: /* NIP cannot be restored if the memory exception comes from an helper */
4513: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 4514: gen_helper_lscbx(t0, t0, t1, t2, t3);
4515: tcg_temp_free_i32(t1);
4516: tcg_temp_free_i32(t2);
4517: tcg_temp_free_i32(t3);
4518: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4519: tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
1.1.1.5 root 4520: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4521: gen_set_Rc0(ctx, t0);
4522: tcg_temp_free(t0);
1.1.1.5 root 4523: }
4524:
4525: /* maskg - maskg. */
1.1.1.7 root 4526: static void gen_maskg(DisasContext *ctx)
1.1.1.5 root 4527: {
1.1.1.6 root 4528: int l1 = gen_new_label();
4529: TCGv t0 = tcg_temp_new();
4530: TCGv t1 = tcg_temp_new();
4531: TCGv t2 = tcg_temp_new();
4532: TCGv t3 = tcg_temp_new();
4533: tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4534: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4535: tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4536: tcg_gen_addi_tl(t2, t0, 1);
4537: tcg_gen_shr_tl(t2, t3, t2);
4538: tcg_gen_shr_tl(t3, t3, t1);
4539: tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4540: tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4541: tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4542: gen_set_label(l1);
4543: tcg_temp_free(t0);
4544: tcg_temp_free(t1);
4545: tcg_temp_free(t2);
4546: tcg_temp_free(t3);
1.1.1.5 root 4547: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4548: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4549: }
4550:
4551: /* maskir - maskir. */
1.1.1.7 root 4552: static void gen_maskir(DisasContext *ctx)
1.1.1.5 root 4553: {
1.1.1.6 root 4554: TCGv t0 = tcg_temp_new();
4555: TCGv t1 = tcg_temp_new();
4556: tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4557: tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4558: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4559: tcg_temp_free(t0);
4560: tcg_temp_free(t1);
1.1.1.5 root 4561: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4562: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4563: }
4564:
4565: /* mul - mul. */
1.1.1.7 root 4566: static void gen_mul(DisasContext *ctx)
1.1.1.5 root 4567: {
1.1.1.6 root 4568: TCGv_i64 t0 = tcg_temp_new_i64();
4569: TCGv_i64 t1 = tcg_temp_new_i64();
4570: TCGv t2 = tcg_temp_new();
4571: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4572: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4573: tcg_gen_mul_i64(t0, t0, t1);
4574: tcg_gen_trunc_i64_tl(t2, t0);
4575: gen_store_spr(SPR_MQ, t2);
4576: tcg_gen_shri_i64(t1, t0, 32);
4577: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4578: tcg_temp_free_i64(t0);
4579: tcg_temp_free_i64(t1);
4580: tcg_temp_free(t2);
1.1.1.5 root 4581: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4582: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4583: }
4584:
4585: /* mulo - mulo. */
1.1.1.7 root 4586: static void gen_mulo(DisasContext *ctx)
1.1.1.5 root 4587: {
1.1.1.6 root 4588: int l1 = gen_new_label();
4589: TCGv_i64 t0 = tcg_temp_new_i64();
4590: TCGv_i64 t1 = tcg_temp_new_i64();
4591: TCGv t2 = tcg_temp_new();
4592: /* Start with XER OV disabled, the most likely case */
4593: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4594: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4595: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4596: tcg_gen_mul_i64(t0, t0, t1);
4597: tcg_gen_trunc_i64_tl(t2, t0);
4598: gen_store_spr(SPR_MQ, t2);
4599: tcg_gen_shri_i64(t1, t0, 32);
4600: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4601: tcg_gen_ext32s_i64(t1, t0);
4602: tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4603: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4604: gen_set_label(l1);
4605: tcg_temp_free_i64(t0);
4606: tcg_temp_free_i64(t1);
4607: tcg_temp_free(t2);
1.1.1.5 root 4608: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4609: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4610: }
4611:
4612: /* nabs - nabs. */
1.1.1.7 root 4613: static void gen_nabs(DisasContext *ctx)
1.1.1.5 root 4614: {
1.1.1.6 root 4615: int l1 = gen_new_label();
4616: int l2 = gen_new_label();
4617: tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4618: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4619: tcg_gen_br(l2);
4620: gen_set_label(l1);
4621: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4622: gen_set_label(l2);
1.1.1.5 root 4623: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4624: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4625: }
4626:
4627: /* nabso - nabso. */
1.1.1.7 root 4628: static void gen_nabso(DisasContext *ctx)
1.1.1.5 root 4629: {
1.1.1.6 root 4630: int l1 = gen_new_label();
4631: int l2 = gen_new_label();
4632: tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4633: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4634: tcg_gen_br(l2);
4635: gen_set_label(l1);
4636: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4637: gen_set_label(l2);
4638: /* nabs never overflows */
4639: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1.1.1.5 root 4640: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4641: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4642: }
4643:
4644: /* rlmi - rlmi. */
1.1.1.7 root 4645: static void gen_rlmi(DisasContext *ctx)
1.1.1.5 root 4646: {
1.1.1.6 root 4647: uint32_t mb = MB(ctx->opcode);
4648: uint32_t me = ME(ctx->opcode);
4649: TCGv t0 = tcg_temp_new();
4650: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4651: tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4652: tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4653: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4654: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4655: tcg_temp_free(t0);
1.1.1.5 root 4656: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4657: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4658: }
4659:
4660: /* rrib - rrib. */
1.1.1.7 root 4661: static void gen_rrib(DisasContext *ctx)
1.1.1.5 root 4662: {
1.1.1.6 root 4663: TCGv t0 = tcg_temp_new();
4664: TCGv t1 = tcg_temp_new();
4665: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4666: tcg_gen_movi_tl(t1, 0x80000000);
4667: tcg_gen_shr_tl(t1, t1, t0);
4668: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4669: tcg_gen_and_tl(t0, t0, t1);
4670: tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4671: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4672: tcg_temp_free(t0);
4673: tcg_temp_free(t1);
1.1.1.5 root 4674: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4675: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4676: }
4677:
4678: /* sle - sle. */
1.1.1.7 root 4679: static void gen_sle(DisasContext *ctx)
1.1.1.5 root 4680: {
1.1.1.6 root 4681: TCGv t0 = tcg_temp_new();
4682: TCGv t1 = tcg_temp_new();
4683: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4684: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4685: tcg_gen_subfi_tl(t1, 32, t1);
4686: tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4687: tcg_gen_or_tl(t1, t0, t1);
4688: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4689: gen_store_spr(SPR_MQ, t1);
4690: tcg_temp_free(t0);
4691: tcg_temp_free(t1);
1.1.1.5 root 4692: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4693: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4694: }
4695:
4696: /* sleq - sleq. */
1.1.1.7 root 4697: static void gen_sleq(DisasContext *ctx)
1.1.1.5 root 4698: {
1.1.1.6 root 4699: TCGv t0 = tcg_temp_new();
4700: TCGv t1 = tcg_temp_new();
4701: TCGv t2 = tcg_temp_new();
4702: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4703: tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4704: tcg_gen_shl_tl(t2, t2, t0);
4705: tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4706: gen_load_spr(t1, SPR_MQ);
4707: gen_store_spr(SPR_MQ, t0);
4708: tcg_gen_and_tl(t0, t0, t2);
4709: tcg_gen_andc_tl(t1, t1, t2);
4710: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4711: tcg_temp_free(t0);
4712: tcg_temp_free(t1);
4713: tcg_temp_free(t2);
1.1.1.5 root 4714: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4715: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4716: }
4717:
4718: /* sliq - sliq. */
1.1.1.7 root 4719: static void gen_sliq(DisasContext *ctx)
1.1.1.5 root 4720: {
1.1.1.6 root 4721: int sh = SH(ctx->opcode);
4722: TCGv t0 = tcg_temp_new();
4723: TCGv t1 = tcg_temp_new();
4724: tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4725: tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4726: tcg_gen_or_tl(t1, t0, t1);
4727: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4728: gen_store_spr(SPR_MQ, t1);
4729: tcg_temp_free(t0);
4730: tcg_temp_free(t1);
1.1.1.5 root 4731: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4732: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4733: }
4734:
4735: /* slliq - slliq. */
1.1.1.7 root 4736: static void gen_slliq(DisasContext *ctx)
1.1.1.5 root 4737: {
1.1.1.6 root 4738: int sh = SH(ctx->opcode);
4739: TCGv t0 = tcg_temp_new();
4740: TCGv t1 = tcg_temp_new();
4741: tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4742: gen_load_spr(t1, SPR_MQ);
4743: gen_store_spr(SPR_MQ, t0);
4744: tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
4745: tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4746: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4747: tcg_temp_free(t0);
4748: tcg_temp_free(t1);
1.1.1.5 root 4749: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4750: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4751: }
4752:
4753: /* sllq - sllq. */
1.1.1.7 root 4754: static void gen_sllq(DisasContext *ctx)
1.1.1.5 root 4755: {
1.1.1.6 root 4756: int l1 = gen_new_label();
4757: int l2 = gen_new_label();
4758: TCGv t0 = tcg_temp_local_new();
4759: TCGv t1 = tcg_temp_local_new();
4760: TCGv t2 = tcg_temp_local_new();
4761: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4762: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4763: tcg_gen_shl_tl(t1, t1, t2);
4764: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4765: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4766: gen_load_spr(t0, SPR_MQ);
4767: tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4768: tcg_gen_br(l2);
4769: gen_set_label(l1);
4770: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4771: gen_load_spr(t2, SPR_MQ);
4772: tcg_gen_andc_tl(t1, t2, t1);
4773: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4774: gen_set_label(l2);
4775: tcg_temp_free(t0);
4776: tcg_temp_free(t1);
4777: tcg_temp_free(t2);
1.1.1.5 root 4778: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4779: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4780: }
4781:
4782: /* slq - slq. */
1.1.1.7 root 4783: static void gen_slq(DisasContext *ctx)
1.1.1.5 root 4784: {
1.1.1.6 root 4785: int l1 = gen_new_label();
4786: TCGv t0 = tcg_temp_new();
4787: TCGv t1 = tcg_temp_new();
4788: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4789: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4790: tcg_gen_subfi_tl(t1, 32, t1);
4791: tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4792: tcg_gen_or_tl(t1, t0, t1);
4793: gen_store_spr(SPR_MQ, t1);
4794: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4795: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4796: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4797: tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4798: gen_set_label(l1);
4799: tcg_temp_free(t0);
4800: tcg_temp_free(t1);
1.1.1.5 root 4801: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4802: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4803: }
4804:
4805: /* sraiq - sraiq. */
1.1.1.7 root 4806: static void gen_sraiq(DisasContext *ctx)
1.1.1.5 root 4807: {
1.1.1.6 root 4808: int sh = SH(ctx->opcode);
4809: int l1 = gen_new_label();
4810: TCGv t0 = tcg_temp_new();
4811: TCGv t1 = tcg_temp_new();
4812: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4813: tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4814: tcg_gen_or_tl(t0, t0, t1);
4815: gen_store_spr(SPR_MQ, t0);
4816: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4817: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4818: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4819: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4820: gen_set_label(l1);
4821: tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4822: tcg_temp_free(t0);
4823: tcg_temp_free(t1);
1.1.1.5 root 4824: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4825: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4826: }
4827:
4828: /* sraq - sraq. */
1.1.1.7 root 4829: static void gen_sraq(DisasContext *ctx)
1.1.1.5 root 4830: {
1.1.1.6 root 4831: int l1 = gen_new_label();
4832: int l2 = gen_new_label();
4833: TCGv t0 = tcg_temp_new();
4834: TCGv t1 = tcg_temp_local_new();
4835: TCGv t2 = tcg_temp_local_new();
4836: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4837: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4838: tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4839: tcg_gen_subfi_tl(t2, 32, t2);
4840: tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4841: tcg_gen_or_tl(t0, t0, t2);
4842: gen_store_spr(SPR_MQ, t0);
4843: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4844: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4845: tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4846: tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4847: gen_set_label(l1);
4848: tcg_temp_free(t0);
4849: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4850: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4851: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4852: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4853: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4854: gen_set_label(l2);
4855: tcg_temp_free(t1);
4856: tcg_temp_free(t2);
1.1.1.5 root 4857: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4858: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4859: }
4860:
4861: /* sre - sre. */
1.1.1.7 root 4862: static void gen_sre(DisasContext *ctx)
1.1.1.5 root 4863: {
1.1.1.6 root 4864: TCGv t0 = tcg_temp_new();
4865: TCGv t1 = tcg_temp_new();
4866: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4867: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4868: tcg_gen_subfi_tl(t1, 32, t1);
4869: tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4870: tcg_gen_or_tl(t1, t0, t1);
4871: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4872: gen_store_spr(SPR_MQ, t1);
4873: tcg_temp_free(t0);
4874: tcg_temp_free(t1);
1.1.1.5 root 4875: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4876: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4877: }
4878:
4879: /* srea - srea. */
1.1.1.7 root 4880: static void gen_srea(DisasContext *ctx)
1.1.1.5 root 4881: {
1.1.1.6 root 4882: TCGv t0 = tcg_temp_new();
4883: TCGv t1 = tcg_temp_new();
4884: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4885: tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4886: gen_store_spr(SPR_MQ, t0);
4887: tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4888: tcg_temp_free(t0);
4889: tcg_temp_free(t1);
1.1.1.5 root 4890: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4891: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4892: }
4893:
4894: /* sreq */
1.1.1.7 root 4895: static void gen_sreq(DisasContext *ctx)
1.1.1.5 root 4896: {
1.1.1.6 root 4897: TCGv t0 = tcg_temp_new();
4898: TCGv t1 = tcg_temp_new();
4899: TCGv t2 = tcg_temp_new();
4900: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4901: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4902: tcg_gen_shr_tl(t1, t1, t0);
4903: tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4904: gen_load_spr(t2, SPR_MQ);
4905: gen_store_spr(SPR_MQ, t0);
4906: tcg_gen_and_tl(t0, t0, t1);
4907: tcg_gen_andc_tl(t2, t2, t1);
4908: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4909: tcg_temp_free(t0);
4910: tcg_temp_free(t1);
4911: tcg_temp_free(t2);
1.1.1.5 root 4912: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4913: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4914: }
4915:
4916: /* sriq */
1.1.1.7 root 4917: static void gen_sriq(DisasContext *ctx)
1.1.1.5 root 4918: {
1.1.1.6 root 4919: int sh = SH(ctx->opcode);
4920: TCGv t0 = tcg_temp_new();
4921: TCGv t1 = tcg_temp_new();
4922: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4923: tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4924: tcg_gen_or_tl(t1, t0, t1);
4925: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4926: gen_store_spr(SPR_MQ, t1);
4927: tcg_temp_free(t0);
4928: tcg_temp_free(t1);
1.1.1.5 root 4929: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4930: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4931: }
4932:
4933: /* srliq */
1.1.1.7 root 4934: static void gen_srliq(DisasContext *ctx)
1.1.1.5 root 4935: {
1.1.1.6 root 4936: int sh = SH(ctx->opcode);
4937: TCGv t0 = tcg_temp_new();
4938: TCGv t1 = tcg_temp_new();
4939: tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4940: gen_load_spr(t1, SPR_MQ);
4941: gen_store_spr(SPR_MQ, t0);
4942: tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
4943: tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
4944: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4945: tcg_temp_free(t0);
4946: tcg_temp_free(t1);
1.1.1.5 root 4947: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4948: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4949: }
4950:
4951: /* srlq */
1.1.1.7 root 4952: static void gen_srlq(DisasContext *ctx)
1.1.1.5 root 4953: {
1.1.1.6 root 4954: int l1 = gen_new_label();
4955: int l2 = gen_new_label();
4956: TCGv t0 = tcg_temp_local_new();
4957: TCGv t1 = tcg_temp_local_new();
4958: TCGv t2 = tcg_temp_local_new();
4959: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4960: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4961: tcg_gen_shr_tl(t2, t1, t2);
4962: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4963: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4964: gen_load_spr(t0, SPR_MQ);
4965: tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4966: tcg_gen_br(l2);
4967: gen_set_label(l1);
4968: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4969: tcg_gen_and_tl(t0, t0, t2);
4970: gen_load_spr(t1, SPR_MQ);
4971: tcg_gen_andc_tl(t1, t1, t2);
4972: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4973: gen_set_label(l2);
4974: tcg_temp_free(t0);
4975: tcg_temp_free(t1);
4976: tcg_temp_free(t2);
1.1.1.5 root 4977: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4978: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4979: }
4980:
4981: /* srq */
1.1.1.7 root 4982: static void gen_srq(DisasContext *ctx)
1.1.1.5 root 4983: {
1.1.1.6 root 4984: int l1 = gen_new_label();
4985: TCGv t0 = tcg_temp_new();
4986: TCGv t1 = tcg_temp_new();
4987: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4988: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4989: tcg_gen_subfi_tl(t1, 32, t1);
4990: tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4991: tcg_gen_or_tl(t1, t0, t1);
4992: gen_store_spr(SPR_MQ, t1);
4993: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4994: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4995: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4996: tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4997: gen_set_label(l1);
4998: tcg_temp_free(t0);
4999: tcg_temp_free(t1);
1.1.1.5 root 5000: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 5001: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5002: }
5003:
5004: /* PowerPC 602 specific instructions */
1.1.1.7 root 5005:
1.1.1.5 root 5006: /* dsa */
1.1.1.7 root 5007: static void gen_dsa(DisasContext *ctx)
1.1.1.5 root 5008: {
5009: /* XXX: TODO */
1.1.1.6 root 5010: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5011: }
5012:
5013: /* esa */
1.1.1.7 root 5014: static void gen_esa(DisasContext *ctx)
1.1.1.5 root 5015: {
5016: /* XXX: TODO */
1.1.1.6 root 5017: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5018: }
5019:
5020: /* mfrom */
1.1.1.7 root 5021: static void gen_mfrom(DisasContext *ctx)
1.1.1.5 root 5022: {
5023: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5024: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5025: #else
1.1.1.6 root 5026: if (unlikely(!ctx->mem_idx)) {
5027: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5028: return;
5029: }
1.1.1.6 root 5030: gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5031: #endif
5032: }
5033:
5034: /* 602 - 603 - G2 TLB management */
1.1.1.7 root 5035:
1.1.1.5 root 5036: /* tlbld */
1.1.1.7 root 5037: static void gen_tlbld_6xx(DisasContext *ctx)
1.1.1.5 root 5038: {
5039: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5040: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5041: #else
1.1.1.6 root 5042: if (unlikely(!ctx->mem_idx)) {
5043: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5044: return;
5045: }
1.1.1.6 root 5046: gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5047: #endif
5048: }
5049:
5050: /* tlbli */
1.1.1.7 root 5051: static void gen_tlbli_6xx(DisasContext *ctx)
1.1.1.5 root 5052: {
5053: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5054: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5055: #else
1.1.1.6 root 5056: if (unlikely(!ctx->mem_idx)) {
5057: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5058: return;
5059: }
1.1.1.6 root 5060: gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5061: #endif
5062: }
5063:
5064: /* 74xx TLB management */
1.1.1.7 root 5065:
1.1.1.5 root 5066: /* tlbld */
1.1.1.7 root 5067: static void gen_tlbld_74xx(DisasContext *ctx)
1.1.1.5 root 5068: {
5069: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5070: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5071: #else
1.1.1.6 root 5072: if (unlikely(!ctx->mem_idx)) {
5073: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5074: return;
5075: }
1.1.1.6 root 5076: gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5077: #endif
5078: }
5079:
5080: /* tlbli */
1.1.1.7 root 5081: static void gen_tlbli_74xx(DisasContext *ctx)
1.1.1.5 root 5082: {
5083: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5084: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5085: #else
1.1.1.6 root 5086: if (unlikely(!ctx->mem_idx)) {
5087: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5088: return;
5089: }
1.1.1.6 root 5090: gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5091: #endif
5092: }
5093:
5094: /* POWER instructions not in PowerPC 601 */
1.1.1.7 root 5095:
1.1.1.5 root 5096: /* clf */
1.1.1.7 root 5097: static void gen_clf(DisasContext *ctx)
1.1.1.5 root 5098: {
5099: /* Cache line flush: implemented as no-op */
5100: }
5101:
5102: /* cli */
1.1.1.7 root 5103: static void gen_cli(DisasContext *ctx)
1.1.1.5 root 5104: {
5105: /* Cache line invalidate: privileged and treated as no-op */
5106: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5107: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5108: #else
1.1.1.6 root 5109: if (unlikely(!ctx->mem_idx)) {
5110: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5111: return;
5112: }
5113: #endif
5114: }
5115:
5116: /* dclst */
1.1.1.7 root 5117: static void gen_dclst(DisasContext *ctx)
1.1.1.5 root 5118: {
5119: /* Data cache line store: treated as no-op */
5120: }
5121:
1.1.1.7 root 5122: static void gen_mfsri(DisasContext *ctx)
1.1.1.5 root 5123: {
5124: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5125: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5126: #else
5127: int ra = rA(ctx->opcode);
5128: int rd = rD(ctx->opcode);
1.1.1.6 root 5129: TCGv t0;
5130: if (unlikely(!ctx->mem_idx)) {
5131: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5132: return;
5133: }
5134: t0 = tcg_temp_new();
5135: gen_addr_reg_index(ctx, t0);
5136: tcg_gen_shri_tl(t0, t0, 28);
5137: tcg_gen_andi_tl(t0, t0, 0xF);
5138: gen_helper_load_sr(cpu_gpr[rd], t0);
5139: tcg_temp_free(t0);
1.1.1.5 root 5140: if (ra != 0 && ra != rd)
1.1.1.6 root 5141: tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
1.1.1.5 root 5142: #endif
5143: }
5144:
1.1.1.7 root 5145: static void gen_rac(DisasContext *ctx)
1.1.1.5 root 5146: {
5147: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5148: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5149: #else
1.1.1.6 root 5150: TCGv t0;
5151: if (unlikely(!ctx->mem_idx)) {
5152: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5153: return;
5154: }
1.1.1.6 root 5155: t0 = tcg_temp_new();
5156: gen_addr_reg_index(ctx, t0);
5157: gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5158: tcg_temp_free(t0);
1.1.1.5 root 5159: #endif
5160: }
5161:
1.1.1.7 root 5162: static void gen_rfsvc(DisasContext *ctx)
1.1.1.5 root 5163: {
5164: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5165: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5166: #else
1.1.1.6 root 5167: if (unlikely(!ctx->mem_idx)) {
5168: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5169: return;
5170: }
1.1.1.6 root 5171: gen_helper_rfsvc();
5172: gen_sync_exception(ctx);
1.1.1.5 root 5173: #endif
5174: }
5175:
5176: /* svc is not implemented for now */
5177:
5178: /* POWER2 specific instructions */
5179: /* Quad manipulation (load/store two floats at a time) */
5180:
5181: /* lfq */
1.1.1.7 root 5182: static void gen_lfq(DisasContext *ctx)
1.1.1.5 root 5183: {
1.1.1.6 root 5184: int rd = rD(ctx->opcode);
5185: TCGv t0;
5186: gen_set_access_type(ctx, ACCESS_FLOAT);
5187: t0 = tcg_temp_new();
5188: gen_addr_imm_index(ctx, t0, 0);
5189: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5190: gen_addr_add(ctx, t0, t0, 8);
5191: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5192: tcg_temp_free(t0);
1.1.1.5 root 5193: }
5194:
5195: /* lfqu */
1.1.1.7 root 5196: static void gen_lfqu(DisasContext *ctx)
1.1.1.5 root 5197: {
5198: int ra = rA(ctx->opcode);
1.1.1.6 root 5199: int rd = rD(ctx->opcode);
5200: TCGv t0, t1;
5201: gen_set_access_type(ctx, ACCESS_FLOAT);
5202: t0 = tcg_temp_new();
5203: t1 = tcg_temp_new();
5204: gen_addr_imm_index(ctx, t0, 0);
5205: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5206: gen_addr_add(ctx, t1, t0, 8);
5207: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
1.1.1.5 root 5208: if (ra != 0)
1.1.1.6 root 5209: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5210: tcg_temp_free(t0);
5211: tcg_temp_free(t1);
1.1.1.5 root 5212: }
5213:
5214: /* lfqux */
1.1.1.7 root 5215: static void gen_lfqux(DisasContext *ctx)
1.1.1.5 root 5216: {
5217: int ra = rA(ctx->opcode);
1.1.1.6 root 5218: int rd = rD(ctx->opcode);
5219: gen_set_access_type(ctx, ACCESS_FLOAT);
5220: TCGv t0, t1;
5221: t0 = tcg_temp_new();
5222: gen_addr_reg_index(ctx, t0);
5223: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5224: t1 = tcg_temp_new();
5225: gen_addr_add(ctx, t1, t0, 8);
5226: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5227: tcg_temp_free(t1);
1.1.1.5 root 5228: if (ra != 0)
1.1.1.6 root 5229: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5230: tcg_temp_free(t0);
1.1.1.5 root 5231: }
5232:
5233: /* lfqx */
1.1.1.7 root 5234: static void gen_lfqx(DisasContext *ctx)
1.1.1.5 root 5235: {
1.1.1.6 root 5236: int rd = rD(ctx->opcode);
5237: TCGv t0;
5238: gen_set_access_type(ctx, ACCESS_FLOAT);
5239: t0 = tcg_temp_new();
5240: gen_addr_reg_index(ctx, t0);
5241: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5242: gen_addr_add(ctx, t0, t0, 8);
5243: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5244: tcg_temp_free(t0);
1.1.1.5 root 5245: }
5246:
5247: /* stfq */
1.1.1.7 root 5248: static void gen_stfq(DisasContext *ctx)
1.1.1.5 root 5249: {
1.1.1.6 root 5250: int rd = rD(ctx->opcode);
5251: TCGv t0;
5252: gen_set_access_type(ctx, ACCESS_FLOAT);
5253: t0 = tcg_temp_new();
5254: gen_addr_imm_index(ctx, t0, 0);
5255: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5256: gen_addr_add(ctx, t0, t0, 8);
5257: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5258: tcg_temp_free(t0);
1.1.1.5 root 5259: }
5260:
5261: /* stfqu */
1.1.1.7 root 5262: static void gen_stfqu(DisasContext *ctx)
1.1.1.5 root 5263: {
5264: int ra = rA(ctx->opcode);
1.1.1.6 root 5265: int rd = rD(ctx->opcode);
5266: TCGv t0, t1;
5267: gen_set_access_type(ctx, ACCESS_FLOAT);
5268: t0 = tcg_temp_new();
5269: gen_addr_imm_index(ctx, t0, 0);
5270: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5271: t1 = tcg_temp_new();
5272: gen_addr_add(ctx, t1, t0, 8);
5273: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5274: tcg_temp_free(t1);
1.1.1.5 root 5275: if (ra != 0)
1.1.1.6 root 5276: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5277: tcg_temp_free(t0);
1.1.1.5 root 5278: }
5279:
5280: /* stfqux */
1.1.1.7 root 5281: static void gen_stfqux(DisasContext *ctx)
1.1.1.5 root 5282: {
5283: int ra = rA(ctx->opcode);
1.1.1.6 root 5284: int rd = rD(ctx->opcode);
5285: TCGv t0, t1;
5286: gen_set_access_type(ctx, ACCESS_FLOAT);
5287: t0 = tcg_temp_new();
5288: gen_addr_reg_index(ctx, t0);
5289: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5290: t1 = tcg_temp_new();
5291: gen_addr_add(ctx, t1, t0, 8);
5292: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5293: tcg_temp_free(t1);
1.1.1.5 root 5294: if (ra != 0)
1.1.1.6 root 5295: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5296: tcg_temp_free(t0);
1.1.1.5 root 5297: }
5298:
5299: /* stfqx */
1.1.1.7 root 5300: static void gen_stfqx(DisasContext *ctx)
1.1.1.5 root 5301: {
1.1.1.6 root 5302: int rd = rD(ctx->opcode);
5303: TCGv t0;
5304: gen_set_access_type(ctx, ACCESS_FLOAT);
5305: t0 = tcg_temp_new();
5306: gen_addr_reg_index(ctx, t0);
5307: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5308: gen_addr_add(ctx, t0, t0, 8);
5309: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5310: tcg_temp_free(t0);
1.1.1.5 root 5311: }
5312:
5313: /* BookE specific instructions */
1.1.1.7 root 5314:
1.1.1.5 root 5315: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5316: static void gen_mfapidi(DisasContext *ctx)
1.1.1.5 root 5317: {
5318: /* XXX: TODO */
1.1.1.6 root 5319: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5320: }
5321:
5322: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5323: static void gen_tlbiva(DisasContext *ctx)
1.1.1.5 root 5324: {
5325: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5326: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5327: #else
1.1.1.6 root 5328: TCGv t0;
5329: if (unlikely(!ctx->mem_idx)) {
5330: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5331: return;
5332: }
1.1.1.6 root 5333: t0 = tcg_temp_new();
5334: gen_addr_reg_index(ctx, t0);
5335: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
5336: tcg_temp_free(t0);
1.1.1.5 root 5337: #endif
5338: }
5339:
5340: /* All 405 MAC instructions are translated here */
1.1.1.8 ! root 5341: static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
! 5342: int ra, int rb, int rt, int Rc)
1.1.1.5 root 5343: {
1.1.1.6 root 5344: TCGv t0, t1;
5345:
5346: t0 = tcg_temp_local_new();
5347: t1 = tcg_temp_local_new();
5348:
1.1.1.5 root 5349: switch (opc3 & 0x0D) {
5350: case 0x05:
5351: /* macchw - macchw. - macchwo - macchwo. */
5352: /* macchws - macchws. - macchwso - macchwso. */
5353: /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5354: /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5355: /* mulchw - mulchw. */
1.1.1.6 root 5356: tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5357: tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5358: tcg_gen_ext16s_tl(t1, t1);
1.1.1.5 root 5359: break;
5360: case 0x04:
5361: /* macchwu - macchwu. - macchwuo - macchwuo. */
5362: /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5363: /* mulchwu - mulchwu. */
1.1.1.6 root 5364: tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5365: tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5366: tcg_gen_ext16u_tl(t1, t1);
1.1.1.5 root 5367: break;
5368: case 0x01:
5369: /* machhw - machhw. - machhwo - machhwo. */
5370: /* machhws - machhws. - machhwso - machhwso. */
5371: /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5372: /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5373: /* mulhhw - mulhhw. */
1.1.1.6 root 5374: tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5375: tcg_gen_ext16s_tl(t0, t0);
5376: tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5377: tcg_gen_ext16s_tl(t1, t1);
1.1.1.5 root 5378: break;
5379: case 0x00:
5380: /* machhwu - machhwu. - machhwuo - machhwuo. */
5381: /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5382: /* mulhhwu - mulhhwu. */
1.1.1.6 root 5383: tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5384: tcg_gen_ext16u_tl(t0, t0);
5385: tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5386: tcg_gen_ext16u_tl(t1, t1);
1.1.1.5 root 5387: break;
5388: case 0x0D:
5389: /* maclhw - maclhw. - maclhwo - maclhwo. */
5390: /* maclhws - maclhws. - maclhwso - maclhwso. */
5391: /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5392: /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5393: /* mullhw - mullhw. */
1.1.1.6 root 5394: tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5395: tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
1.1.1.5 root 5396: break;
5397: case 0x0C:
5398: /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5399: /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5400: /* mullhwu - mullhwu. */
1.1.1.6 root 5401: tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5402: tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
1.1.1.5 root 5403: break;
5404: }
5405: if (opc2 & 0x04) {
1.1.1.6 root 5406: /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5407: tcg_gen_mul_tl(t1, t0, t1);
5408: if (opc2 & 0x02) {
5409: /* nmultiply-and-accumulate (0x0E) */
5410: tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5411: } else {
5412: /* multiply-and-accumulate (0x0C) */
5413: tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5414: }
5415:
5416: if (opc3 & 0x12) {
5417: /* Check overflow and/or saturate */
5418: int l1 = gen_new_label();
5419:
5420: if (opc3 & 0x10) {
5421: /* Start with XER OV disabled, the most likely case */
5422: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5423: }
5424: if (opc3 & 0x01) {
5425: /* Signed */
5426: tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5427: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5428: tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5429: tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
5430: if (opc3 & 0x02) {
5431: /* Saturate */
5432: tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5433: tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5434: }
5435: } else {
5436: /* Unsigned */
5437: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5438: if (opc3 & 0x02) {
5439: /* Saturate */
5440: tcg_gen_movi_tl(t0, UINT32_MAX);
5441: }
5442: }
5443: if (opc3 & 0x10) {
5444: /* Check overflow */
5445: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5446: }
5447: gen_set_label(l1);
5448: tcg_gen_mov_tl(cpu_gpr[rt], t0);
5449: }
5450: } else {
5451: tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
1.1.1.5 root 5452: }
1.1.1.6 root 5453: tcg_temp_free(t0);
5454: tcg_temp_free(t1);
1.1.1.5 root 5455: if (unlikely(Rc) != 0) {
5456: /* Update Rc0 */
1.1.1.6 root 5457: gen_set_Rc0(ctx, cpu_gpr[rt]);
1.1.1.5 root 5458: }
5459: }
5460:
5461: #define GEN_MAC_HANDLER(name, opc2, opc3) \
1.1.1.7 root 5462: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.5 root 5463: { \
5464: gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5465: rD(ctx->opcode), Rc(ctx->opcode)); \
5466: }
5467:
5468: /* macchw - macchw. */
5469: GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5470: /* macchwo - macchwo. */
5471: GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5472: /* macchws - macchws. */
5473: GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5474: /* macchwso - macchwso. */
5475: GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5476: /* macchwsu - macchwsu. */
5477: GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5478: /* macchwsuo - macchwsuo. */
5479: GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5480: /* macchwu - macchwu. */
5481: GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5482: /* macchwuo - macchwuo. */
5483: GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5484: /* machhw - machhw. */
5485: GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5486: /* machhwo - machhwo. */
5487: GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5488: /* machhws - machhws. */
5489: GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5490: /* machhwso - machhwso. */
5491: GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5492: /* machhwsu - machhwsu. */
5493: GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5494: /* machhwsuo - machhwsuo. */
5495: GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5496: /* machhwu - machhwu. */
5497: GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5498: /* machhwuo - machhwuo. */
5499: GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5500: /* maclhw - maclhw. */
5501: GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5502: /* maclhwo - maclhwo. */
5503: GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5504: /* maclhws - maclhws. */
5505: GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5506: /* maclhwso - maclhwso. */
5507: GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5508: /* maclhwu - maclhwu. */
5509: GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5510: /* maclhwuo - maclhwuo. */
5511: GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5512: /* maclhwsu - maclhwsu. */
5513: GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5514: /* maclhwsuo - maclhwsuo. */
5515: GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5516: /* nmacchw - nmacchw. */
5517: GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5518: /* nmacchwo - nmacchwo. */
5519: GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5520: /* nmacchws - nmacchws. */
5521: GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5522: /* nmacchwso - nmacchwso. */
5523: GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5524: /* nmachhw - nmachhw. */
5525: GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5526: /* nmachhwo - nmachhwo. */
5527: GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5528: /* nmachhws - nmachhws. */
5529: GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5530: /* nmachhwso - nmachhwso. */
5531: GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5532: /* nmaclhw - nmaclhw. */
5533: GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5534: /* nmaclhwo - nmaclhwo. */
5535: GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5536: /* nmaclhws - nmaclhws. */
5537: GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5538: /* nmaclhwso - nmaclhwso. */
5539: GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5540:
5541: /* mulchw - mulchw. */
5542: GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5543: /* mulchwu - mulchwu. */
5544: GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5545: /* mulhhw - mulhhw. */
5546: GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5547: /* mulhhwu - mulhhwu. */
5548: GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5549: /* mullhw - mullhw. */
5550: GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5551: /* mullhwu - mullhwu. */
5552: GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5553:
5554: /* mfdcr */
1.1.1.7 root 5555: static void gen_mfdcr(DisasContext *ctx)
1.1.1.5 root 5556: {
5557: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5558: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5559: #else
1.1.1.6 root 5560: TCGv dcrn;
5561: if (unlikely(!ctx->mem_idx)) {
5562: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5563: return;
5564: }
1.1.1.6 root 5565: /* NIP cannot be restored if the memory exception comes from an helper */
5566: gen_update_nip(ctx, ctx->nip - 4);
5567: dcrn = tcg_const_tl(SPR(ctx->opcode));
5568: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5569: tcg_temp_free(dcrn);
1.1.1.5 root 5570: #endif
5571: }
5572:
5573: /* mtdcr */
1.1.1.7 root 5574: static void gen_mtdcr(DisasContext *ctx)
1.1.1.5 root 5575: {
5576: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5577: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5578: #else
1.1.1.6 root 5579: TCGv dcrn;
5580: if (unlikely(!ctx->mem_idx)) {
5581: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5582: return;
5583: }
1.1.1.6 root 5584: /* NIP cannot be restored if the memory exception comes from an helper */
5585: gen_update_nip(ctx, ctx->nip - 4);
5586: dcrn = tcg_const_tl(SPR(ctx->opcode));
5587: gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5588: tcg_temp_free(dcrn);
1.1.1.5 root 5589: #endif
5590: }
5591:
5592: /* mfdcrx */
5593: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5594: static void gen_mfdcrx(DisasContext *ctx)
1.1.1.5 root 5595: {
5596: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5597: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5598: #else
1.1.1.6 root 5599: if (unlikely(!ctx->mem_idx)) {
5600: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5601: return;
5602: }
1.1.1.6 root 5603: /* NIP cannot be restored if the memory exception comes from an helper */
5604: gen_update_nip(ctx, ctx->nip - 4);
5605: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5606: /* Note: Rc update flag set leads to undefined state of Rc0 */
5607: #endif
5608: }
5609:
5610: /* mtdcrx */
5611: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5612: static void gen_mtdcrx(DisasContext *ctx)
1.1.1.5 root 5613: {
5614: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5615: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5616: #else
1.1.1.6 root 5617: if (unlikely(!ctx->mem_idx)) {
5618: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5619: return;
5620: }
1.1.1.6 root 5621: /* NIP cannot be restored if the memory exception comes from an helper */
5622: gen_update_nip(ctx, ctx->nip - 4);
5623: gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5624: /* Note: Rc update flag set leads to undefined state of Rc0 */
5625: #endif
5626: }
5627:
5628: /* mfdcrux (PPC 460) : user-mode access to DCR */
1.1.1.7 root 5629: static void gen_mfdcrux(DisasContext *ctx)
1.1.1.5 root 5630: {
1.1.1.6 root 5631: /* NIP cannot be restored if the memory exception comes from an helper */
5632: gen_update_nip(ctx, ctx->nip - 4);
5633: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5634: /* Note: Rc update flag set leads to undefined state of Rc0 */
5635: }
5636:
5637: /* mtdcrux (PPC 460) : user-mode access to DCR */
1.1.1.7 root 5638: static void gen_mtdcrux(DisasContext *ctx)
1.1.1.5 root 5639: {
1.1.1.6 root 5640: /* NIP cannot be restored if the memory exception comes from an helper */
5641: gen_update_nip(ctx, ctx->nip - 4);
5642: gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5643: /* Note: Rc update flag set leads to undefined state of Rc0 */
5644: }
5645:
5646: /* dccci */
1.1.1.7 root 5647: static void gen_dccci(DisasContext *ctx)
1.1.1.5 root 5648: {
5649: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5650: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5651: #else
1.1.1.6 root 5652: if (unlikely(!ctx->mem_idx)) {
5653: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5654: return;
5655: }
5656: /* interpreted as no-op */
5657: #endif
5658: }
5659:
5660: /* dcread */
1.1.1.7 root 5661: static void gen_dcread(DisasContext *ctx)
1.1.1.5 root 5662: {
5663: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5664: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5665: #else
1.1.1.6 root 5666: TCGv EA, val;
5667: if (unlikely(!ctx->mem_idx)) {
5668: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5669: return;
5670: }
1.1.1.6 root 5671: gen_set_access_type(ctx, ACCESS_CACHE);
5672: EA = tcg_temp_new();
5673: gen_addr_reg_index(ctx, EA);
5674: val = tcg_temp_new();
5675: gen_qemu_ld32u(ctx, val, EA);
5676: tcg_temp_free(val);
5677: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5678: tcg_temp_free(EA);
1.1.1.5 root 5679: #endif
5680: }
5681:
5682: /* icbt */
1.1.1.7 root 5683: static void gen_icbt_40x(DisasContext *ctx)
1.1.1.5 root 5684: {
5685: /* interpreted as no-op */
5686: /* XXX: specification say this is treated as a load by the MMU
5687: * but does not generate any exception
5688: */
5689: }
5690:
5691: /* iccci */
1.1.1.7 root 5692: static void gen_iccci(DisasContext *ctx)
1.1.1.5 root 5693: {
5694: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5695: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5696: #else
1.1.1.6 root 5697: if (unlikely(!ctx->mem_idx)) {
5698: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5699: return;
5700: }
5701: /* interpreted as no-op */
5702: #endif
5703: }
5704:
5705: /* icread */
1.1.1.7 root 5706: static void gen_icread(DisasContext *ctx)
1.1.1.5 root 5707: {
5708: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5709: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5710: #else
1.1.1.6 root 5711: if (unlikely(!ctx->mem_idx)) {
5712: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5713: return;
5714: }
5715: /* interpreted as no-op */
5716: #endif
5717: }
5718:
1.1.1.6 root 5719: /* rfci (mem_idx only) */
1.1.1.7 root 5720: static void gen_rfci_40x(DisasContext *ctx)
1.1.1.5 root 5721: {
5722: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5723: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5724: #else
1.1.1.6 root 5725: if (unlikely(!ctx->mem_idx)) {
5726: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5727: return;
5728: }
5729: /* Restore CPU state */
1.1.1.6 root 5730: gen_helper_40x_rfci();
5731: gen_sync_exception(ctx);
1.1.1.5 root 5732: #endif
5733: }
5734:
1.1.1.7 root 5735: static void gen_rfci(DisasContext *ctx)
1.1.1.5 root 5736: {
5737: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5738: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5739: #else
1.1.1.6 root 5740: if (unlikely(!ctx->mem_idx)) {
5741: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5742: return;
5743: }
5744: /* Restore CPU state */
1.1.1.6 root 5745: gen_helper_rfci();
5746: gen_sync_exception(ctx);
1.1.1.5 root 5747: #endif
5748: }
5749:
5750: /* BookE specific */
1.1.1.7 root 5751:
1.1.1.5 root 5752: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5753: static void gen_rfdi(DisasContext *ctx)
1.1.1.5 root 5754: {
5755: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5756: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5757: #else
1.1.1.6 root 5758: if (unlikely(!ctx->mem_idx)) {
5759: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5760: return;
5761: }
5762: /* Restore CPU state */
1.1.1.6 root 5763: gen_helper_rfdi();
5764: gen_sync_exception(ctx);
1.1.1.5 root 5765: #endif
5766: }
5767:
5768: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5769: static void gen_rfmci(DisasContext *ctx)
1.1.1.5 root 5770: {
5771: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5772: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5773: #else
1.1.1.6 root 5774: if (unlikely(!ctx->mem_idx)) {
5775: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5776: return;
5777: }
5778: /* Restore CPU state */
1.1.1.6 root 5779: gen_helper_rfmci();
5780: gen_sync_exception(ctx);
1.1.1.5 root 5781: #endif
5782: }
5783:
5784: /* TLB management - PowerPC 405 implementation */
1.1.1.7 root 5785:
1.1.1.5 root 5786: /* tlbre */
1.1.1.7 root 5787: static void gen_tlbre_40x(DisasContext *ctx)
1.1.1.5 root 5788: {
5789: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5790: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5791: #else
1.1.1.6 root 5792: if (unlikely(!ctx->mem_idx)) {
5793: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5794: return;
5795: }
5796: switch (rB(ctx->opcode)) {
5797: case 0:
1.1.1.6 root 5798: gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5799: break;
5800: case 1:
1.1.1.6 root 5801: gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5802: break;
5803: default:
1.1.1.6 root 5804: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5805: break;
5806: }
5807: #endif
5808: }
5809:
5810: /* tlbsx - tlbsx. */
1.1.1.7 root 5811: static void gen_tlbsx_40x(DisasContext *ctx)
1.1.1.5 root 5812: {
5813: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5814: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5815: #else
1.1.1.6 root 5816: TCGv t0;
5817: if (unlikely(!ctx->mem_idx)) {
5818: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5819: return;
5820: }
1.1.1.6 root 5821: t0 = tcg_temp_new();
5822: gen_addr_reg_index(ctx, t0);
5823: gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5824: tcg_temp_free(t0);
5825: if (Rc(ctx->opcode)) {
5826: int l1 = gen_new_label();
5827: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5828: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5829: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5830: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5831: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5832: gen_set_label(l1);
5833: }
1.1.1.5 root 5834: #endif
5835: }
5836:
5837: /* tlbwe */
1.1.1.7 root 5838: static void gen_tlbwe_40x(DisasContext *ctx)
1.1.1.5 root 5839: {
5840: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5841: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5842: #else
1.1.1.6 root 5843: if (unlikely(!ctx->mem_idx)) {
5844: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5845: return;
5846: }
5847: switch (rB(ctx->opcode)) {
5848: case 0:
1.1.1.6 root 5849: gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5850: break;
5851: case 1:
1.1.1.6 root 5852: gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5853: break;
5854: default:
1.1.1.6 root 5855: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5856: break;
5857: }
5858: #endif
5859: }
5860:
5861: /* TLB management - PowerPC 440 implementation */
1.1.1.7 root 5862:
1.1.1.5 root 5863: /* tlbre */
1.1.1.7 root 5864: static void gen_tlbre_440(DisasContext *ctx)
1.1.1.5 root 5865: {
5866: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5867: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5868: #else
1.1.1.6 root 5869: if (unlikely(!ctx->mem_idx)) {
5870: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5871: return;
5872: }
5873: switch (rB(ctx->opcode)) {
5874: case 0:
5875: case 1:
5876: case 2:
1.1.1.6 root 5877: {
5878: TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5879: gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5880: tcg_temp_free_i32(t0);
5881: }
1.1.1.5 root 5882: break;
5883: default:
1.1.1.6 root 5884: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5885: break;
5886: }
5887: #endif
5888: }
5889:
5890: /* tlbsx - tlbsx. */
1.1.1.7 root 5891: static void gen_tlbsx_440(DisasContext *ctx)
1.1 root 5892: {
5893: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5894: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5895: #else
1.1.1.6 root 5896: TCGv t0;
5897: if (unlikely(!ctx->mem_idx)) {
5898: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5899: return;
5900: }
1.1.1.6 root 5901: t0 = tcg_temp_new();
5902: gen_addr_reg_index(ctx, t0);
5903: gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5904: tcg_temp_free(t0);
5905: if (Rc(ctx->opcode)) {
5906: int l1 = gen_new_label();
5907: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5908: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5909: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5910: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5911: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5912: gen_set_label(l1);
5913: }
1.1 root 5914: #endif
5915: }
5916:
1.1.1.5 root 5917: /* tlbwe */
1.1.1.7 root 5918: static void gen_tlbwe_440(DisasContext *ctx)
1.1 root 5919: {
5920: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5921: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5922: #else
1.1.1.6 root 5923: if (unlikely(!ctx->mem_idx)) {
5924: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5925: return;
5926: }
1.1.1.5 root 5927: switch (rB(ctx->opcode)) {
5928: case 0:
5929: case 1:
5930: case 2:
1.1.1.6 root 5931: {
5932: TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5933: gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5934: tcg_temp_free_i32(t0);
5935: }
1.1.1.5 root 5936: break;
5937: default:
1.1.1.6 root 5938: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5939: break;
5940: }
5941: #endif
5942: }
5943:
5944: /* wrtee */
1.1.1.7 root 5945: static void gen_wrtee(DisasContext *ctx)
1.1.1.5 root 5946: {
5947: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5948: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5949: #else
1.1.1.6 root 5950: TCGv t0;
5951: if (unlikely(!ctx->mem_idx)) {
5952: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5953: return;
5954: }
1.1.1.6 root 5955: t0 = tcg_temp_new();
5956: tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
5957: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
5958: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
5959: tcg_temp_free(t0);
1.1.1.5 root 5960: /* Stop translation to have a chance to raise an exception
5961: * if we just set msr_ee to 1
1.1 root 5962: */
1.1.1.6 root 5963: gen_stop_exception(ctx);
1.1 root 5964: #endif
5965: }
5966:
1.1.1.5 root 5967: /* wrteei */
1.1.1.7 root 5968: static void gen_wrteei(DisasContext *ctx)
1.1.1.5 root 5969: {
1.1 root 5970: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5971: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5972: #else
1.1.1.6 root 5973: if (unlikely(!ctx->mem_idx)) {
5974: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5975: return;
5976: }
1.1.1.7 root 5977: if (ctx->opcode & 0x00008000) {
1.1.1.6 root 5978: tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
5979: /* Stop translation to have a chance to raise an exception */
5980: gen_stop_exception(ctx);
5981: } else {
5982: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
5983: }
1.1.1.5 root 5984: #endif
5985: }
5986:
5987: /* PowerPC 440 specific instructions */
1.1.1.7 root 5988:
1.1.1.5 root 5989: /* dlmzb */
1.1.1.7 root 5990: static void gen_dlmzb(DisasContext *ctx)
1.1.1.5 root 5991: {
1.1.1.6 root 5992: TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
5993: gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
5994: cpu_gpr[rB(ctx->opcode)], t0);
5995: tcg_temp_free_i32(t0);
1.1.1.5 root 5996: }
5997:
5998: /* mbar replaces eieio on 440 */
1.1.1.7 root 5999: static void gen_mbar(DisasContext *ctx)
1.1.1.5 root 6000: {
6001: /* interpreted as no-op */
6002: }
6003:
6004: /* msync replaces sync on 440 */
1.1.1.7 root 6005: static void gen_msync(DisasContext *ctx)
1.1.1.5 root 6006: {
6007: /* interpreted as no-op */
6008: }
6009:
6010: /* icbt */
1.1.1.7 root 6011: static void gen_icbt_440(DisasContext *ctx)
1.1.1.5 root 6012: {
6013: /* interpreted as no-op */
6014: /* XXX: specification say this is treated as a load by the MMU
6015: * but does not generate any exception
6016: */
6017: }
6018:
6019: /*** Altivec vector extension ***/
6020: /* Altivec registers moves */
6021:
1.1.1.8 ! root 6022: static inline TCGv_ptr gen_avr_ptr(int reg)
1.1.1.6 root 6023: {
6024: TCGv_ptr r = tcg_temp_new_ptr();
6025: tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6026: return r;
6027: }
1.1.1.5 root 6028:
6029: #define GEN_VR_LDX(name, opc2, opc3) \
1.1.1.7 root 6030: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.5 root 6031: { \
1.1.1.6 root 6032: TCGv EA; \
1.1.1.5 root 6033: if (unlikely(!ctx->altivec_enabled)) { \
1.1.1.6 root 6034: gen_exception(ctx, POWERPC_EXCP_VPU); \
1.1.1.5 root 6035: return; \
6036: } \
1.1.1.6 root 6037: gen_set_access_type(ctx, ACCESS_INT); \
6038: EA = tcg_temp_new(); \
6039: gen_addr_reg_index(ctx, EA); \
6040: tcg_gen_andi_tl(EA, EA, ~0xf); \
6041: if (ctx->le_mode) { \
6042: gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6043: tcg_gen_addi_tl(EA, EA, 8); \
6044: gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6045: } else { \
6046: gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6047: tcg_gen_addi_tl(EA, EA, 8); \
6048: gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6049: } \
6050: tcg_temp_free(EA); \
1.1.1.5 root 6051: }
6052:
6053: #define GEN_VR_STX(name, opc2, opc3) \
1.1.1.7 root 6054: static void gen_st##name(DisasContext *ctx) \
1.1.1.5 root 6055: { \
1.1.1.6 root 6056: TCGv EA; \
1.1.1.5 root 6057: if (unlikely(!ctx->altivec_enabled)) { \
1.1.1.6 root 6058: gen_exception(ctx, POWERPC_EXCP_VPU); \
1.1.1.5 root 6059: return; \
6060: } \
1.1.1.6 root 6061: gen_set_access_type(ctx, ACCESS_INT); \
6062: EA = tcg_temp_new(); \
6063: gen_addr_reg_index(ctx, EA); \
6064: tcg_gen_andi_tl(EA, EA, ~0xf); \
6065: if (ctx->le_mode) { \
6066: gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6067: tcg_gen_addi_tl(EA, EA, 8); \
6068: gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6069: } else { \
6070: gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6071: tcg_gen_addi_tl(EA, EA, 8); \
6072: gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6073: } \
6074: tcg_temp_free(EA); \
1.1.1.5 root 6075: }
6076:
1.1.1.6 root 6077: #define GEN_VR_LVE(name, opc2, opc3) \
1.1.1.7 root 6078: static void gen_lve##name(DisasContext *ctx) \
1.1.1.6 root 6079: { \
6080: TCGv EA; \
6081: TCGv_ptr rs; \
6082: if (unlikely(!ctx->altivec_enabled)) { \
6083: gen_exception(ctx, POWERPC_EXCP_VPU); \
6084: return; \
6085: } \
6086: gen_set_access_type(ctx, ACCESS_INT); \
6087: EA = tcg_temp_new(); \
6088: gen_addr_reg_index(ctx, EA); \
6089: rs = gen_avr_ptr(rS(ctx->opcode)); \
6090: gen_helper_lve##name (rs, EA); \
6091: tcg_temp_free(EA); \
6092: tcg_temp_free_ptr(rs); \
6093: }
6094:
6095: #define GEN_VR_STVE(name, opc2, opc3) \
1.1.1.7 root 6096: static void gen_stve##name(DisasContext *ctx) \
1.1.1.6 root 6097: { \
6098: TCGv EA; \
6099: TCGv_ptr rs; \
6100: if (unlikely(!ctx->altivec_enabled)) { \
6101: gen_exception(ctx, POWERPC_EXCP_VPU); \
6102: return; \
6103: } \
6104: gen_set_access_type(ctx, ACCESS_INT); \
6105: EA = tcg_temp_new(); \
6106: gen_addr_reg_index(ctx, EA); \
6107: rs = gen_avr_ptr(rS(ctx->opcode)); \
6108: gen_helper_stve##name (rs, EA); \
6109: tcg_temp_free(EA); \
6110: tcg_temp_free_ptr(rs); \
6111: }
6112:
6113: GEN_VR_LDX(lvx, 0x07, 0x03);
1.1.1.5 root 6114: /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
1.1.1.6 root 6115: GEN_VR_LDX(lvxl, 0x07, 0x0B);
1.1.1.5 root 6116:
1.1.1.6 root 6117: GEN_VR_LVE(bx, 0x07, 0x00);
6118: GEN_VR_LVE(hx, 0x07, 0x01);
6119: GEN_VR_LVE(wx, 0x07, 0x02);
6120:
6121: GEN_VR_STX(svx, 0x07, 0x07);
1.1.1.5 root 6122: /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
1.1.1.6 root 6123: GEN_VR_STX(svxl, 0x07, 0x0F);
6124:
6125: GEN_VR_STVE(bx, 0x07, 0x04);
6126: GEN_VR_STVE(hx, 0x07, 0x05);
6127: GEN_VR_STVE(wx, 0x07, 0x06);
6128:
1.1.1.7 root 6129: static void gen_lvsl(DisasContext *ctx)
1.1.1.6 root 6130: {
6131: TCGv_ptr rd;
6132: TCGv EA;
6133: if (unlikely(!ctx->altivec_enabled)) {
6134: gen_exception(ctx, POWERPC_EXCP_VPU);
6135: return;
6136: }
6137: EA = tcg_temp_new();
6138: gen_addr_reg_index(ctx, EA);
6139: rd = gen_avr_ptr(rD(ctx->opcode));
6140: gen_helper_lvsl(rd, EA);
6141: tcg_temp_free(EA);
6142: tcg_temp_free_ptr(rd);
6143: }
6144:
1.1.1.7 root 6145: static void gen_lvsr(DisasContext *ctx)
1.1.1.6 root 6146: {
6147: TCGv_ptr rd;
6148: TCGv EA;
6149: if (unlikely(!ctx->altivec_enabled)) {
6150: gen_exception(ctx, POWERPC_EXCP_VPU);
6151: return;
6152: }
6153: EA = tcg_temp_new();
6154: gen_addr_reg_index(ctx, EA);
6155: rd = gen_avr_ptr(rD(ctx->opcode));
6156: gen_helper_lvsr(rd, EA);
6157: tcg_temp_free(EA);
6158: tcg_temp_free_ptr(rd);
6159: }
6160:
1.1.1.7 root 6161: static void gen_mfvscr(DisasContext *ctx)
1.1.1.6 root 6162: {
6163: TCGv_i32 t;
6164: if (unlikely(!ctx->altivec_enabled)) {
6165: gen_exception(ctx, POWERPC_EXCP_VPU);
6166: return;
6167: }
6168: tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6169: t = tcg_temp_new_i32();
6170: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
6171: tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6172: tcg_temp_free_i32(t);
6173: }
6174:
1.1.1.7 root 6175: static void gen_mtvscr(DisasContext *ctx)
1.1.1.6 root 6176: {
6177: TCGv_ptr p;
6178: if (unlikely(!ctx->altivec_enabled)) {
6179: gen_exception(ctx, POWERPC_EXCP_VPU);
6180: return;
6181: }
6182: p = gen_avr_ptr(rD(ctx->opcode));
6183: gen_helper_mtvscr(p);
6184: tcg_temp_free_ptr(p);
6185: }
6186:
6187: /* Logical operations */
6188: #define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
1.1.1.7 root 6189: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6190: { \
6191: if (unlikely(!ctx->altivec_enabled)) { \
6192: gen_exception(ctx, POWERPC_EXCP_VPU); \
6193: return; \
6194: } \
6195: tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6196: tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6197: }
6198:
6199: GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6200: GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6201: GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6202: GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6203: GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6204:
6205: #define GEN_VXFORM(name, opc2, opc3) \
1.1.1.7 root 6206: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6207: { \
6208: TCGv_ptr ra, rb, rd; \
6209: if (unlikely(!ctx->altivec_enabled)) { \
6210: gen_exception(ctx, POWERPC_EXCP_VPU); \
6211: return; \
6212: } \
6213: ra = gen_avr_ptr(rA(ctx->opcode)); \
6214: rb = gen_avr_ptr(rB(ctx->opcode)); \
6215: rd = gen_avr_ptr(rD(ctx->opcode)); \
6216: gen_helper_##name (rd, ra, rb); \
6217: tcg_temp_free_ptr(ra); \
6218: tcg_temp_free_ptr(rb); \
6219: tcg_temp_free_ptr(rd); \
6220: }
6221:
6222: GEN_VXFORM(vaddubm, 0, 0);
6223: GEN_VXFORM(vadduhm, 0, 1);
6224: GEN_VXFORM(vadduwm, 0, 2);
6225: GEN_VXFORM(vsububm, 0, 16);
6226: GEN_VXFORM(vsubuhm, 0, 17);
6227: GEN_VXFORM(vsubuwm, 0, 18);
6228: GEN_VXFORM(vmaxub, 1, 0);
6229: GEN_VXFORM(vmaxuh, 1, 1);
6230: GEN_VXFORM(vmaxuw, 1, 2);
6231: GEN_VXFORM(vmaxsb, 1, 4);
6232: GEN_VXFORM(vmaxsh, 1, 5);
6233: GEN_VXFORM(vmaxsw, 1, 6);
6234: GEN_VXFORM(vminub, 1, 8);
6235: GEN_VXFORM(vminuh, 1, 9);
6236: GEN_VXFORM(vminuw, 1, 10);
6237: GEN_VXFORM(vminsb, 1, 12);
6238: GEN_VXFORM(vminsh, 1, 13);
6239: GEN_VXFORM(vminsw, 1, 14);
6240: GEN_VXFORM(vavgub, 1, 16);
6241: GEN_VXFORM(vavguh, 1, 17);
6242: GEN_VXFORM(vavguw, 1, 18);
6243: GEN_VXFORM(vavgsb, 1, 20);
6244: GEN_VXFORM(vavgsh, 1, 21);
6245: GEN_VXFORM(vavgsw, 1, 22);
6246: GEN_VXFORM(vmrghb, 6, 0);
6247: GEN_VXFORM(vmrghh, 6, 1);
6248: GEN_VXFORM(vmrghw, 6, 2);
6249: GEN_VXFORM(vmrglb, 6, 4);
6250: GEN_VXFORM(vmrglh, 6, 5);
6251: GEN_VXFORM(vmrglw, 6, 6);
6252: GEN_VXFORM(vmuloub, 4, 0);
6253: GEN_VXFORM(vmulouh, 4, 1);
6254: GEN_VXFORM(vmulosb, 4, 4);
6255: GEN_VXFORM(vmulosh, 4, 5);
6256: GEN_VXFORM(vmuleub, 4, 8);
6257: GEN_VXFORM(vmuleuh, 4, 9);
6258: GEN_VXFORM(vmulesb, 4, 12);
6259: GEN_VXFORM(vmulesh, 4, 13);
6260: GEN_VXFORM(vslb, 2, 4);
6261: GEN_VXFORM(vslh, 2, 5);
6262: GEN_VXFORM(vslw, 2, 6);
6263: GEN_VXFORM(vsrb, 2, 8);
6264: GEN_VXFORM(vsrh, 2, 9);
6265: GEN_VXFORM(vsrw, 2, 10);
6266: GEN_VXFORM(vsrab, 2, 12);
6267: GEN_VXFORM(vsrah, 2, 13);
6268: GEN_VXFORM(vsraw, 2, 14);
6269: GEN_VXFORM(vslo, 6, 16);
6270: GEN_VXFORM(vsro, 6, 17);
6271: GEN_VXFORM(vaddcuw, 0, 6);
6272: GEN_VXFORM(vsubcuw, 0, 22);
6273: GEN_VXFORM(vaddubs, 0, 8);
6274: GEN_VXFORM(vadduhs, 0, 9);
6275: GEN_VXFORM(vadduws, 0, 10);
6276: GEN_VXFORM(vaddsbs, 0, 12);
6277: GEN_VXFORM(vaddshs, 0, 13);
6278: GEN_VXFORM(vaddsws, 0, 14);
6279: GEN_VXFORM(vsububs, 0, 24);
6280: GEN_VXFORM(vsubuhs, 0, 25);
6281: GEN_VXFORM(vsubuws, 0, 26);
6282: GEN_VXFORM(vsubsbs, 0, 28);
6283: GEN_VXFORM(vsubshs, 0, 29);
6284: GEN_VXFORM(vsubsws, 0, 30);
6285: GEN_VXFORM(vrlb, 2, 0);
6286: GEN_VXFORM(vrlh, 2, 1);
6287: GEN_VXFORM(vrlw, 2, 2);
6288: GEN_VXFORM(vsl, 2, 7);
6289: GEN_VXFORM(vsr, 2, 11);
6290: GEN_VXFORM(vpkuhum, 7, 0);
6291: GEN_VXFORM(vpkuwum, 7, 1);
6292: GEN_VXFORM(vpkuhus, 7, 2);
6293: GEN_VXFORM(vpkuwus, 7, 3);
6294: GEN_VXFORM(vpkshus, 7, 4);
6295: GEN_VXFORM(vpkswus, 7, 5);
6296: GEN_VXFORM(vpkshss, 7, 6);
6297: GEN_VXFORM(vpkswss, 7, 7);
6298: GEN_VXFORM(vpkpx, 7, 12);
6299: GEN_VXFORM(vsum4ubs, 4, 24);
6300: GEN_VXFORM(vsum4sbs, 4, 28);
6301: GEN_VXFORM(vsum4shs, 4, 25);
6302: GEN_VXFORM(vsum2sws, 4, 26);
6303: GEN_VXFORM(vsumsws, 4, 30);
6304: GEN_VXFORM(vaddfp, 5, 0);
6305: GEN_VXFORM(vsubfp, 5, 1);
6306: GEN_VXFORM(vmaxfp, 5, 16);
6307: GEN_VXFORM(vminfp, 5, 17);
6308:
6309: #define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
1.1.1.7 root 6310: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6311: { \
6312: TCGv_ptr ra, rb, rd; \
6313: if (unlikely(!ctx->altivec_enabled)) { \
6314: gen_exception(ctx, POWERPC_EXCP_VPU); \
6315: return; \
6316: } \
6317: ra = gen_avr_ptr(rA(ctx->opcode)); \
6318: rb = gen_avr_ptr(rB(ctx->opcode)); \
6319: rd = gen_avr_ptr(rD(ctx->opcode)); \
6320: gen_helper_##opname (rd, ra, rb); \
6321: tcg_temp_free_ptr(ra); \
6322: tcg_temp_free_ptr(rb); \
6323: tcg_temp_free_ptr(rd); \
6324: }
6325:
6326: #define GEN_VXRFORM(name, opc2, opc3) \
6327: GEN_VXRFORM1(name, name, #name, opc2, opc3) \
6328: GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
6329:
6330: GEN_VXRFORM(vcmpequb, 3, 0)
6331: GEN_VXRFORM(vcmpequh, 3, 1)
6332: GEN_VXRFORM(vcmpequw, 3, 2)
6333: GEN_VXRFORM(vcmpgtsb, 3, 12)
6334: GEN_VXRFORM(vcmpgtsh, 3, 13)
6335: GEN_VXRFORM(vcmpgtsw, 3, 14)
6336: GEN_VXRFORM(vcmpgtub, 3, 8)
6337: GEN_VXRFORM(vcmpgtuh, 3, 9)
6338: GEN_VXRFORM(vcmpgtuw, 3, 10)
6339: GEN_VXRFORM(vcmpeqfp, 3, 3)
6340: GEN_VXRFORM(vcmpgefp, 3, 7)
6341: GEN_VXRFORM(vcmpgtfp, 3, 11)
6342: GEN_VXRFORM(vcmpbfp, 3, 15)
6343:
6344: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
1.1.1.7 root 6345: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6346: { \
6347: TCGv_ptr rd; \
6348: TCGv_i32 simm; \
6349: if (unlikely(!ctx->altivec_enabled)) { \
6350: gen_exception(ctx, POWERPC_EXCP_VPU); \
6351: return; \
6352: } \
6353: simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6354: rd = gen_avr_ptr(rD(ctx->opcode)); \
6355: gen_helper_##name (rd, simm); \
6356: tcg_temp_free_i32(simm); \
6357: tcg_temp_free_ptr(rd); \
6358: }
6359:
6360: GEN_VXFORM_SIMM(vspltisb, 6, 12);
6361: GEN_VXFORM_SIMM(vspltish, 6, 13);
6362: GEN_VXFORM_SIMM(vspltisw, 6, 14);
6363:
6364: #define GEN_VXFORM_NOA(name, opc2, opc3) \
1.1.1.7 root 6365: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6366: { \
6367: TCGv_ptr rb, rd; \
6368: if (unlikely(!ctx->altivec_enabled)) { \
6369: gen_exception(ctx, POWERPC_EXCP_VPU); \
6370: return; \
6371: } \
6372: rb = gen_avr_ptr(rB(ctx->opcode)); \
6373: rd = gen_avr_ptr(rD(ctx->opcode)); \
6374: gen_helper_##name (rd, rb); \
6375: tcg_temp_free_ptr(rb); \
6376: tcg_temp_free_ptr(rd); \
6377: }
6378:
6379: GEN_VXFORM_NOA(vupkhsb, 7, 8);
6380: GEN_VXFORM_NOA(vupkhsh, 7, 9);
6381: GEN_VXFORM_NOA(vupklsb, 7, 10);
6382: GEN_VXFORM_NOA(vupklsh, 7, 11);
6383: GEN_VXFORM_NOA(vupkhpx, 7, 13);
6384: GEN_VXFORM_NOA(vupklpx, 7, 15);
6385: GEN_VXFORM_NOA(vrefp, 5, 4);
6386: GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6387: GEN_VXFORM_NOA(vlogefp, 5, 7);
6388: GEN_VXFORM_NOA(vrfim, 5, 8);
6389: GEN_VXFORM_NOA(vrfin, 5, 9);
6390: GEN_VXFORM_NOA(vrfip, 5, 10);
6391: GEN_VXFORM_NOA(vrfiz, 5, 11);
6392:
6393: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
1.1.1.7 root 6394: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6395: { \
6396: TCGv_ptr rd; \
6397: TCGv_i32 simm; \
6398: if (unlikely(!ctx->altivec_enabled)) { \
6399: gen_exception(ctx, POWERPC_EXCP_VPU); \
6400: return; \
6401: } \
6402: simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6403: rd = gen_avr_ptr(rD(ctx->opcode)); \
6404: gen_helper_##name (rd, simm); \
6405: tcg_temp_free_i32(simm); \
6406: tcg_temp_free_ptr(rd); \
6407: }
6408:
6409: #define GEN_VXFORM_UIMM(name, opc2, opc3) \
1.1.1.7 root 6410: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6411: { \
6412: TCGv_ptr rb, rd; \
6413: TCGv_i32 uimm; \
6414: if (unlikely(!ctx->altivec_enabled)) { \
6415: gen_exception(ctx, POWERPC_EXCP_VPU); \
6416: return; \
6417: } \
6418: uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
6419: rb = gen_avr_ptr(rB(ctx->opcode)); \
6420: rd = gen_avr_ptr(rD(ctx->opcode)); \
6421: gen_helper_##name (rd, rb, uimm); \
6422: tcg_temp_free_i32(uimm); \
6423: tcg_temp_free_ptr(rb); \
6424: tcg_temp_free_ptr(rd); \
6425: }
6426:
6427: GEN_VXFORM_UIMM(vspltb, 6, 8);
6428: GEN_VXFORM_UIMM(vsplth, 6, 9);
6429: GEN_VXFORM_UIMM(vspltw, 6, 10);
6430: GEN_VXFORM_UIMM(vcfux, 5, 12);
6431: GEN_VXFORM_UIMM(vcfsx, 5, 13);
6432: GEN_VXFORM_UIMM(vctuxs, 5, 14);
6433: GEN_VXFORM_UIMM(vctsxs, 5, 15);
6434:
1.1.1.7 root 6435: static void gen_vsldoi(DisasContext *ctx)
1.1.1.6 root 6436: {
6437: TCGv_ptr ra, rb, rd;
6438: TCGv_i32 sh;
6439: if (unlikely(!ctx->altivec_enabled)) {
6440: gen_exception(ctx, POWERPC_EXCP_VPU);
6441: return;
6442: }
6443: ra = gen_avr_ptr(rA(ctx->opcode));
6444: rb = gen_avr_ptr(rB(ctx->opcode));
6445: rd = gen_avr_ptr(rD(ctx->opcode));
6446: sh = tcg_const_i32(VSH(ctx->opcode));
6447: gen_helper_vsldoi (rd, ra, rb, sh);
6448: tcg_temp_free_ptr(ra);
6449: tcg_temp_free_ptr(rb);
6450: tcg_temp_free_ptr(rd);
6451: tcg_temp_free_i32(sh);
6452: }
6453:
6454: #define GEN_VAFORM_PAIRED(name0, name1, opc2) \
1.1.1.7 root 6455: static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
1.1.1.6 root 6456: { \
6457: TCGv_ptr ra, rb, rc, rd; \
6458: if (unlikely(!ctx->altivec_enabled)) { \
6459: gen_exception(ctx, POWERPC_EXCP_VPU); \
6460: return; \
6461: } \
6462: ra = gen_avr_ptr(rA(ctx->opcode)); \
6463: rb = gen_avr_ptr(rB(ctx->opcode)); \
6464: rc = gen_avr_ptr(rC(ctx->opcode)); \
6465: rd = gen_avr_ptr(rD(ctx->opcode)); \
6466: if (Rc(ctx->opcode)) { \
6467: gen_helper_##name1 (rd, ra, rb, rc); \
6468: } else { \
6469: gen_helper_##name0 (rd, ra, rb, rc); \
6470: } \
6471: tcg_temp_free_ptr(ra); \
6472: tcg_temp_free_ptr(rb); \
6473: tcg_temp_free_ptr(rc); \
6474: tcg_temp_free_ptr(rd); \
6475: }
6476:
6477: GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
6478:
1.1.1.7 root 6479: static void gen_vmladduhm(DisasContext *ctx)
1.1.1.6 root 6480: {
6481: TCGv_ptr ra, rb, rc, rd;
6482: if (unlikely(!ctx->altivec_enabled)) {
6483: gen_exception(ctx, POWERPC_EXCP_VPU);
6484: return;
6485: }
6486: ra = gen_avr_ptr(rA(ctx->opcode));
6487: rb = gen_avr_ptr(rB(ctx->opcode));
6488: rc = gen_avr_ptr(rC(ctx->opcode));
6489: rd = gen_avr_ptr(rD(ctx->opcode));
6490: gen_helper_vmladduhm(rd, ra, rb, rc);
6491: tcg_temp_free_ptr(ra);
6492: tcg_temp_free_ptr(rb);
6493: tcg_temp_free_ptr(rc);
6494: tcg_temp_free_ptr(rd);
6495: }
6496:
6497: GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
6498: GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
6499: GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
6500: GEN_VAFORM_PAIRED(vsel, vperm, 21)
6501: GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
1.1.1.5 root 6502:
6503: /*** SPE extension ***/
6504: /* Register moves */
6505:
1.1.1.8 ! root 6506: static inline void gen_load_gpr64(TCGv_i64 t, int reg)
! 6507: {
1.1.1.6 root 6508: #if defined(TARGET_PPC64)
6509: tcg_gen_mov_i64(t, cpu_gpr[reg]);
6510: #else
6511: tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
1.1.1.5 root 6512: #endif
1.1.1.6 root 6513: }
1.1.1.5 root 6514:
1.1.1.8 ! root 6515: static inline void gen_store_gpr64(int reg, TCGv_i64 t)
! 6516: {
1.1.1.6 root 6517: #if defined(TARGET_PPC64)
6518: tcg_gen_mov_i64(cpu_gpr[reg], t);
6519: #else
6520: TCGv_i64 tmp = tcg_temp_new_i64();
6521: tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
6522: tcg_gen_shri_i64(tmp, t, 32);
6523: tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
6524: tcg_temp_free_i64(tmp);
1.1.1.5 root 6525: #endif
1.1.1.6 root 6526: }
1.1.1.5 root 6527:
6528: #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
1.1.1.7 root 6529: static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
1.1.1.5 root 6530: { \
6531: if (Rc(ctx->opcode)) \
6532: gen_##name1(ctx); \
6533: else \
6534: gen_##name0(ctx); \
6535: }
6536:
6537: /* Handler for undefined SPE opcodes */
1.1.1.8 ! root 6538: static inline void gen_speundef(DisasContext *ctx)
1.1 root 6539: {
1.1.1.6 root 6540: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 6541: }
6542:
1.1.1.6 root 6543: /* SPE logic */
6544: #if defined(TARGET_PPC64)
6545: #define GEN_SPEOP_LOGIC2(name, tcg_op) \
1.1.1.8 ! root 6546: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6547: { \
6548: if (unlikely(!ctx->spe_enabled)) { \
6549: gen_exception(ctx, POWERPC_EXCP_APU); \
6550: return; \
6551: } \
6552: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6553: cpu_gpr[rB(ctx->opcode)]); \
6554: }
6555: #else
6556: #define GEN_SPEOP_LOGIC2(name, tcg_op) \
1.1.1.8 ! root 6557: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6558: { \
6559: if (unlikely(!ctx->spe_enabled)) { \
6560: gen_exception(ctx, POWERPC_EXCP_APU); \
6561: return; \
6562: } \
6563: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6564: cpu_gpr[rB(ctx->opcode)]); \
6565: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6566: cpu_gprh[rB(ctx->opcode)]); \
1.1.1.5 root 6567: }
1.1.1.6 root 6568: #endif
1.1.1.5 root 6569:
1.1.1.6 root 6570: GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6571: GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6572: GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6573: GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6574: GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6575: GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6576: GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6577: GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
1.1.1.5 root 6578:
1.1.1.6 root 6579: /* SPE logic immediate */
6580: #if defined(TARGET_PPC64)
6581: #define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
1.1.1.8 ! root 6582: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6583: { \
6584: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6585: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6586: return; \
6587: } \
1.1.1.6 root 6588: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6589: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6590: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6591: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6592: tcg_opi(t0, t0, rB(ctx->opcode)); \
6593: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6594: tcg_gen_trunc_i64_i32(t1, t2); \
6595: tcg_temp_free_i64(t2); \
6596: tcg_opi(t1, t1, rB(ctx->opcode)); \
6597: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6598: tcg_temp_free_i32(t0); \
6599: tcg_temp_free_i32(t1); \
1.1.1.5 root 6600: }
1.1.1.6 root 6601: #else
6602: #define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
1.1.1.8 ! root 6603: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6604: { \
6605: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6606: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6607: return; \
6608: } \
1.1.1.6 root 6609: tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6610: rB(ctx->opcode)); \
6611: tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6612: rB(ctx->opcode)); \
1.1.1.5 root 6613: }
1.1.1.6 root 6614: #endif
6615: GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6616: GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6617: GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6618: GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
1.1.1.5 root 6619:
1.1.1.6 root 6620: /* SPE arithmetic */
6621: #if defined(TARGET_PPC64)
6622: #define GEN_SPEOP_ARITH1(name, tcg_op) \
1.1.1.8 ! root 6623: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6624: { \
6625: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6626: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6627: return; \
6628: } \
1.1.1.6 root 6629: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6630: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6631: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6632: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6633: tcg_op(t0, t0); \
6634: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6635: tcg_gen_trunc_i64_i32(t1, t2); \
6636: tcg_temp_free_i64(t2); \
6637: tcg_op(t1, t1); \
6638: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6639: tcg_temp_free_i32(t0); \
6640: tcg_temp_free_i32(t1); \
1.1.1.5 root 6641: }
1.1.1.6 root 6642: #else
6643: #define GEN_SPEOP_ARITH1(name, tcg_op) \
1.1.1.8 ! root 6644: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6645: { \
6646: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6647: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6648: return; \
6649: } \
1.1.1.6 root 6650: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
6651: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
1.1.1.5 root 6652: }
1.1.1.6 root 6653: #endif
1.1.1.5 root 6654:
1.1.1.8 ! root 6655: static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
1.1.1.6 root 6656: {
6657: int l1 = gen_new_label();
6658: int l2 = gen_new_label();
1.1.1.5 root 6659:
1.1.1.6 root 6660: tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6661: tcg_gen_neg_i32(ret, arg1);
6662: tcg_gen_br(l2);
6663: gen_set_label(l1);
6664: tcg_gen_mov_i32(ret, arg1);
6665: gen_set_label(l2);
6666: }
6667: GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6668: GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6669: GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6670: GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
1.1.1.8 ! root 6671: static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
1.1.1.6 root 6672: {
6673: tcg_gen_addi_i32(ret, arg1, 0x8000);
6674: tcg_gen_ext16u_i32(ret, ret);
6675: }
6676: GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
6677: GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6678: GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
1.1.1.5 root 6679:
1.1.1.6 root 6680: #if defined(TARGET_PPC64)
6681: #define GEN_SPEOP_ARITH2(name, tcg_op) \
1.1.1.8 ! root 6682: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6683: { \
6684: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6685: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6686: return; \
6687: } \
1.1.1.6 root 6688: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6689: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6690: TCGv_i32 t2 = tcg_temp_local_new_i32(); \
6691: TCGv_i64 t3 = tcg_temp_local_new_i64(); \
6692: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6693: tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
6694: tcg_op(t0, t0, t2); \
6695: tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
6696: tcg_gen_trunc_i64_i32(t1, t3); \
6697: tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
6698: tcg_gen_trunc_i64_i32(t2, t3); \
6699: tcg_temp_free_i64(t3); \
6700: tcg_op(t1, t1, t2); \
6701: tcg_temp_free_i32(t2); \
6702: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6703: tcg_temp_free_i32(t0); \
6704: tcg_temp_free_i32(t1); \
1.1.1.5 root 6705: }
1.1.1.6 root 6706: #else
6707: #define GEN_SPEOP_ARITH2(name, tcg_op) \
1.1.1.8 ! root 6708: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6709: { \
6710: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6711: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6712: return; \
6713: } \
1.1.1.6 root 6714: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6715: cpu_gpr[rB(ctx->opcode)]); \
6716: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6717: cpu_gprh[rB(ctx->opcode)]); \
6718: }
6719: #endif
6720:
1.1.1.8 ! root 6721: static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6722: {
6723: TCGv_i32 t0;
6724: int l1, l2;
6725:
6726: l1 = gen_new_label();
6727: l2 = gen_new_label();
6728: t0 = tcg_temp_local_new_i32();
6729: /* No error here: 6 bits are used */
6730: tcg_gen_andi_i32(t0, arg2, 0x3F);
6731: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6732: tcg_gen_shr_i32(ret, arg1, t0);
6733: tcg_gen_br(l2);
6734: gen_set_label(l1);
6735: tcg_gen_movi_i32(ret, 0);
6736: tcg_gen_br(l2);
6737: tcg_temp_free_i32(t0);
6738: }
6739: GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
1.1.1.8 ! root 6740: static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6741: {
6742: TCGv_i32 t0;
6743: int l1, l2;
6744:
6745: l1 = gen_new_label();
6746: l2 = gen_new_label();
6747: t0 = tcg_temp_local_new_i32();
6748: /* No error here: 6 bits are used */
6749: tcg_gen_andi_i32(t0, arg2, 0x3F);
6750: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6751: tcg_gen_sar_i32(ret, arg1, t0);
6752: tcg_gen_br(l2);
6753: gen_set_label(l1);
6754: tcg_gen_movi_i32(ret, 0);
6755: tcg_gen_br(l2);
6756: tcg_temp_free_i32(t0);
6757: }
6758: GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
1.1.1.8 ! root 6759: static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6760: {
6761: TCGv_i32 t0;
6762: int l1, l2;
6763:
6764: l1 = gen_new_label();
6765: l2 = gen_new_label();
6766: t0 = tcg_temp_local_new_i32();
6767: /* No error here: 6 bits are used */
6768: tcg_gen_andi_i32(t0, arg2, 0x3F);
6769: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6770: tcg_gen_shl_i32(ret, arg1, t0);
6771: tcg_gen_br(l2);
6772: gen_set_label(l1);
6773: tcg_gen_movi_i32(ret, 0);
6774: tcg_gen_br(l2);
6775: tcg_temp_free_i32(t0);
6776: }
6777: GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
1.1.1.8 ! root 6778: static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6779: {
6780: TCGv_i32 t0 = tcg_temp_new_i32();
6781: tcg_gen_andi_i32(t0, arg2, 0x1F);
6782: tcg_gen_rotl_i32(ret, arg1, t0);
6783: tcg_temp_free_i32(t0);
6784: }
6785: GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
1.1.1.8 ! root 6786: static inline void gen_evmergehi(DisasContext *ctx)
1.1.1.6 root 6787: {
6788: if (unlikely(!ctx->spe_enabled)) {
6789: gen_exception(ctx, POWERPC_EXCP_APU);
6790: return;
6791: }
6792: #if defined(TARGET_PPC64)
6793: TCGv t0 = tcg_temp_new();
6794: TCGv t1 = tcg_temp_new();
6795: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6796: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6797: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6798: tcg_temp_free(t0);
6799: tcg_temp_free(t1);
6800: #else
6801: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6802: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6803: #endif
6804: }
6805: GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
1.1.1.8 ! root 6806: static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6807: {
6808: tcg_gen_sub_i32(ret, arg2, arg1);
1.1.1.5 root 6809: }
1.1.1.6 root 6810: GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
1.1.1.5 root 6811:
1.1.1.6 root 6812: /* SPE arithmetic immediate */
6813: #if defined(TARGET_PPC64)
6814: #define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
1.1.1.8 ! root 6815: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6816: { \
6817: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6818: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6819: return; \
6820: } \
1.1.1.6 root 6821: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6822: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6823: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6824: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6825: tcg_op(t0, t0, rA(ctx->opcode)); \
6826: tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6827: tcg_gen_trunc_i64_i32(t1, t2); \
6828: tcg_temp_free_i64(t2); \
6829: tcg_op(t1, t1, rA(ctx->opcode)); \
6830: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6831: tcg_temp_free_i32(t0); \
6832: tcg_temp_free_i32(t1); \
1.1 root 6833: }
1.1.1.6 root 6834: #else
6835: #define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
1.1.1.8 ! root 6836: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6837: { \
6838: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6839: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6840: return; \
6841: } \
1.1.1.6 root 6842: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
6843: rA(ctx->opcode)); \
6844: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
6845: rA(ctx->opcode)); \
1.1.1.5 root 6846: }
1.1.1.6 root 6847: #endif
6848: GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6849: GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
1.1.1.5 root 6850:
1.1.1.6 root 6851: /* SPE comparison */
6852: #if defined(TARGET_PPC64)
6853: #define GEN_SPEOP_COMP(name, tcg_cond) \
1.1.1.8 ! root 6854: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6855: { \
6856: if (unlikely(!ctx->spe_enabled)) { \
6857: gen_exception(ctx, POWERPC_EXCP_APU); \
6858: return; \
6859: } \
6860: int l1 = gen_new_label(); \
6861: int l2 = gen_new_label(); \
6862: int l3 = gen_new_label(); \
6863: int l4 = gen_new_label(); \
6864: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6865: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6866: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6867: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6868: tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
6869: tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
6870: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
6871: tcg_gen_br(l2); \
6872: gen_set_label(l1); \
6873: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6874: CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6875: gen_set_label(l2); \
6876: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6877: tcg_gen_trunc_i64_i32(t0, t2); \
6878: tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6879: tcg_gen_trunc_i64_i32(t1, t2); \
6880: tcg_temp_free_i64(t2); \
6881: tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
6882: tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6883: ~(CRF_CH | CRF_CH_AND_CL)); \
6884: tcg_gen_br(l4); \
6885: gen_set_label(l3); \
6886: tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6887: CRF_CH | CRF_CH_OR_CL); \
6888: gen_set_label(l4); \
6889: tcg_temp_free_i32(t0); \
6890: tcg_temp_free_i32(t1); \
6891: }
6892: #else
6893: #define GEN_SPEOP_COMP(name, tcg_cond) \
1.1.1.8 ! root 6894: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6895: { \
6896: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6897: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6898: return; \
6899: } \
1.1.1.6 root 6900: int l1 = gen_new_label(); \
6901: int l2 = gen_new_label(); \
6902: int l3 = gen_new_label(); \
6903: int l4 = gen_new_label(); \
6904: \
6905: tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
6906: cpu_gpr[rB(ctx->opcode)], l1); \
6907: tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
6908: tcg_gen_br(l2); \
6909: gen_set_label(l1); \
6910: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6911: CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6912: gen_set_label(l2); \
6913: tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
6914: cpu_gprh[rB(ctx->opcode)], l3); \
6915: tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6916: ~(CRF_CH | CRF_CH_AND_CL)); \
6917: tcg_gen_br(l4); \
6918: gen_set_label(l3); \
6919: tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6920: CRF_CH | CRF_CH_OR_CL); \
6921: gen_set_label(l4); \
6922: }
6923: #endif
6924: GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6925: GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6926: GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6927: GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6928: GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
1.1.1.5 root 6929:
1.1.1.6 root 6930: /* SPE misc */
1.1.1.8 ! root 6931: static inline void gen_brinc(DisasContext *ctx)
1.1.1.6 root 6932: {
6933: /* Note: brinc is usable even if SPE is disabled */
6934: gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6935: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6936: }
1.1.1.8 ! root 6937: static inline void gen_evmergelo(DisasContext *ctx)
1.1.1.6 root 6938: {
6939: if (unlikely(!ctx->spe_enabled)) {
6940: gen_exception(ctx, POWERPC_EXCP_APU);
6941: return;
6942: }
6943: #if defined(TARGET_PPC64)
6944: TCGv t0 = tcg_temp_new();
6945: TCGv t1 = tcg_temp_new();
6946: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6947: tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6948: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6949: tcg_temp_free(t0);
6950: tcg_temp_free(t1);
6951: #else
6952: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.7 root 6953: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.6 root 6954: #endif
6955: }
1.1.1.8 ! root 6956: static inline void gen_evmergehilo(DisasContext *ctx)
1.1.1.6 root 6957: {
6958: if (unlikely(!ctx->spe_enabled)) {
6959: gen_exception(ctx, POWERPC_EXCP_APU);
6960: return;
6961: }
6962: #if defined(TARGET_PPC64)
6963: TCGv t0 = tcg_temp_new();
6964: TCGv t1 = tcg_temp_new();
6965: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6966: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6967: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6968: tcg_temp_free(t0);
6969: tcg_temp_free(t1);
6970: #else
6971: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6972: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6973: #endif
6974: }
1.1.1.8 ! root 6975: static inline void gen_evmergelohi(DisasContext *ctx)
1.1.1.6 root 6976: {
6977: if (unlikely(!ctx->spe_enabled)) {
6978: gen_exception(ctx, POWERPC_EXCP_APU);
6979: return;
6980: }
6981: #if defined(TARGET_PPC64)
6982: TCGv t0 = tcg_temp_new();
6983: TCGv t1 = tcg_temp_new();
6984: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6985: tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6986: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6987: tcg_temp_free(t0);
6988: tcg_temp_free(t1);
6989: #else
1.1.1.7 root 6990: if (rD(ctx->opcode) == rA(ctx->opcode)) {
6991: TCGv_i32 tmp = tcg_temp_new_i32();
6992: tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
6993: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6994: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
6995: tcg_temp_free_i32(tmp);
6996: } else {
6997: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6998: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6999: }
1.1.1.6 root 7000: #endif
7001: }
1.1.1.8 ! root 7002: static inline void gen_evsplati(DisasContext *ctx)
1.1.1.5 root 7003: {
1.1.1.6 root 7004: uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
1.1.1.5 root 7005:
1.1.1.6 root 7006: #if defined(TARGET_PPC64)
7007: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7008: #else
7009: tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7010: tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7011: #endif
1.1.1.5 root 7012: }
1.1.1.8 ! root 7013: static inline void gen_evsplatfi(DisasContext *ctx)
1.1.1.5 root 7014: {
1.1.1.6 root 7015: uint64_t imm = rA(ctx->opcode) << 11;
1.1.1.5 root 7016:
1.1.1.6 root 7017: #if defined(TARGET_PPC64)
7018: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7019: #else
7020: tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7021: tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7022: #endif
1.1.1.5 root 7023: }
7024:
1.1.1.8 ! root 7025: static inline void gen_evsel(DisasContext *ctx)
1.1.1.6 root 7026: {
7027: int l1 = gen_new_label();
7028: int l2 = gen_new_label();
7029: int l3 = gen_new_label();
7030: int l4 = gen_new_label();
7031: TCGv_i32 t0 = tcg_temp_local_new_i32();
7032: #if defined(TARGET_PPC64)
7033: TCGv t1 = tcg_temp_local_new();
7034: TCGv t2 = tcg_temp_local_new();
7035: #endif
7036: tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
7037: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
7038: #if defined(TARGET_PPC64)
7039: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7040: #else
7041: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7042: #endif
7043: tcg_gen_br(l2);
7044: gen_set_label(l1);
7045: #if defined(TARGET_PPC64)
7046: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7047: #else
7048: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7049: #endif
7050: gen_set_label(l2);
7051: tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
7052: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
7053: #if defined(TARGET_PPC64)
7054: tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
7055: #else
7056: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7057: #endif
7058: tcg_gen_br(l4);
7059: gen_set_label(l3);
7060: #if defined(TARGET_PPC64)
7061: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
7062: #else
7063: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7064: #endif
7065: gen_set_label(l4);
7066: tcg_temp_free_i32(t0);
7067: #if defined(TARGET_PPC64)
7068: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
7069: tcg_temp_free(t1);
7070: tcg_temp_free(t2);
7071: #endif
7072: }
1.1.1.7 root 7073:
7074: static void gen_evsel0(DisasContext *ctx)
1.1.1.6 root 7075: {
7076: gen_evsel(ctx);
7077: }
1.1.1.7 root 7078:
7079: static void gen_evsel1(DisasContext *ctx)
1.1.1.6 root 7080: {
7081: gen_evsel(ctx);
7082: }
1.1.1.7 root 7083:
7084: static void gen_evsel2(DisasContext *ctx)
1.1.1.6 root 7085: {
7086: gen_evsel(ctx);
7087: }
1.1.1.7 root 7088:
7089: static void gen_evsel3(DisasContext *ctx)
1.1.1.6 root 7090: {
7091: gen_evsel(ctx);
7092: }
1.1.1.5 root 7093:
7094: GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
7095: GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
7096: GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
7097: GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
7098: GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
7099: GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
7100: GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
7101: GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
7102: GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
7103: GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
7104: GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
7105: GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
7106: GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
7107: GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
7108: GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
7109: GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
7110: GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
7111: GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
7112: GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
7113: GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
7114: GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
7115: GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
7116: GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
7117: GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
7118: GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
7119:
1.1.1.6 root 7120: /* SPE load and stores */
1.1.1.8 ! root 7121: static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
1.1 root 7122: {
1.1.1.6 root 7123: target_ulong uimm = rB(ctx->opcode);
7124:
7125: if (rA(ctx->opcode) == 0) {
7126: tcg_gen_movi_tl(EA, uimm << sh);
7127: } else {
7128: tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
7129: #if defined(TARGET_PPC64)
7130: if (!ctx->sf_mode) {
7131: tcg_gen_ext32u_tl(EA, EA);
7132: }
7133: #endif
1.1 root 7134: }
1.1.1.5 root 7135: }
7136:
1.1.1.8 ! root 7137: static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7138: {
1.1.1.6 root 7139: #if defined(TARGET_PPC64)
7140: gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7141: #else
7142: TCGv_i64 t0 = tcg_temp_new_i64();
7143: gen_qemu_ld64(ctx, t0, addr);
7144: tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
7145: tcg_gen_shri_i64(t0, t0, 32);
7146: tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
7147: tcg_temp_free_i64(t0);
7148: #endif
1.1.1.5 root 7149: }
1.1.1.6 root 7150:
1.1.1.8 ! root 7151: static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7152: {
1.1.1.6 root 7153: #if defined(TARGET_PPC64)
7154: TCGv t0 = tcg_temp_new();
7155: gen_qemu_ld32u(ctx, t0, addr);
7156: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7157: gen_addr_add(ctx, addr, addr, 4);
7158: gen_qemu_ld32u(ctx, t0, addr);
7159: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7160: tcg_temp_free(t0);
7161: #else
7162: gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7163: gen_addr_add(ctx, addr, addr, 4);
7164: gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7165: #endif
1.1.1.5 root 7166: }
1.1.1.6 root 7167:
1.1.1.8 ! root 7168: static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7169: {
1.1.1.6 root 7170: TCGv t0 = tcg_temp_new();
7171: #if defined(TARGET_PPC64)
7172: gen_qemu_ld16u(ctx, t0, addr);
7173: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7174: gen_addr_add(ctx, addr, addr, 2);
7175: gen_qemu_ld16u(ctx, t0, addr);
7176: tcg_gen_shli_tl(t0, t0, 32);
7177: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7178: gen_addr_add(ctx, addr, addr, 2);
7179: gen_qemu_ld16u(ctx, t0, addr);
7180: tcg_gen_shli_tl(t0, t0, 16);
7181: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7182: gen_addr_add(ctx, addr, addr, 2);
7183: gen_qemu_ld16u(ctx, t0, addr);
7184: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7185: #else
7186: gen_qemu_ld16u(ctx, t0, addr);
7187: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7188: gen_addr_add(ctx, addr, addr, 2);
7189: gen_qemu_ld16u(ctx, t0, addr);
7190: tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7191: gen_addr_add(ctx, addr, addr, 2);
7192: gen_qemu_ld16u(ctx, t0, addr);
7193: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7194: gen_addr_add(ctx, addr, addr, 2);
7195: gen_qemu_ld16u(ctx, t0, addr);
7196: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7197: #endif
7198: tcg_temp_free(t0);
1.1.1.5 root 7199: }
1.1.1.6 root 7200:
1.1.1.8 ! root 7201: static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7202: {
1.1.1.6 root 7203: TCGv t0 = tcg_temp_new();
7204: gen_qemu_ld16u(ctx, t0, addr);
7205: #if defined(TARGET_PPC64)
7206: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7207: tcg_gen_shli_tl(t0, t0, 16);
7208: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7209: #else
7210: tcg_gen_shli_tl(t0, t0, 16);
7211: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7212: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7213: #endif
7214: tcg_temp_free(t0);
1.1.1.5 root 7215: }
7216:
1.1.1.8 ! root 7217: static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7218: {
7219: TCGv t0 = tcg_temp_new();
7220: gen_qemu_ld16u(ctx, t0, addr);
1.1.1.5 root 7221: #if defined(TARGET_PPC64)
1.1.1.6 root 7222: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7223: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7224: #else
7225: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7226: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7227: #endif
7228: tcg_temp_free(t0);
7229: }
7230:
1.1.1.8 ! root 7231: static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7232: {
7233: TCGv t0 = tcg_temp_new();
7234: gen_qemu_ld16s(ctx, t0, addr);
7235: #if defined(TARGET_PPC64)
7236: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7237: tcg_gen_ext32u_tl(t0, t0);
7238: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7239: #else
7240: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7241: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7242: #endif
7243: tcg_temp_free(t0);
7244: }
7245:
1.1.1.8 ! root 7246: static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7247: {
7248: TCGv t0 = tcg_temp_new();
7249: #if defined(TARGET_PPC64)
7250: gen_qemu_ld16u(ctx, t0, addr);
7251: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7252: gen_addr_add(ctx, addr, addr, 2);
7253: gen_qemu_ld16u(ctx, t0, addr);
7254: tcg_gen_shli_tl(t0, t0, 16);
7255: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7256: #else
7257: gen_qemu_ld16u(ctx, t0, addr);
7258: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7259: gen_addr_add(ctx, addr, addr, 2);
7260: gen_qemu_ld16u(ctx, t0, addr);
7261: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7262: #endif
7263: tcg_temp_free(t0);
7264: }
7265:
1.1.1.8 ! root 7266: static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7267: {
7268: #if defined(TARGET_PPC64)
7269: TCGv t0 = tcg_temp_new();
7270: gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7271: gen_addr_add(ctx, addr, addr, 2);
7272: gen_qemu_ld16u(ctx, t0, addr);
7273: tcg_gen_shli_tl(t0, t0, 32);
7274: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7275: tcg_temp_free(t0);
7276: #else
7277: gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7278: gen_addr_add(ctx, addr, addr, 2);
7279: gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7280: #endif
7281: }
7282:
1.1.1.8 ! root 7283: static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7284: {
7285: #if defined(TARGET_PPC64)
7286: TCGv t0 = tcg_temp_new();
7287: gen_qemu_ld16s(ctx, t0, addr);
7288: tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
7289: gen_addr_add(ctx, addr, addr, 2);
7290: gen_qemu_ld16s(ctx, t0, addr);
7291: tcg_gen_shli_tl(t0, t0, 32);
7292: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7293: tcg_temp_free(t0);
7294: #else
7295: gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7296: gen_addr_add(ctx, addr, addr, 2);
7297: gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7298: #endif
7299: }
7300:
1.1.1.8 ! root 7301: static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7302: {
7303: TCGv t0 = tcg_temp_new();
7304: gen_qemu_ld32u(ctx, t0, addr);
7305: #if defined(TARGET_PPC64)
7306: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7307: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7308: #else
7309: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7310: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7311: #endif
7312: tcg_temp_free(t0);
7313: }
7314:
1.1.1.8 ! root 7315: static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7316: {
7317: TCGv t0 = tcg_temp_new();
7318: #if defined(TARGET_PPC64)
7319: gen_qemu_ld16u(ctx, t0, addr);
7320: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7321: tcg_gen_shli_tl(t0, t0, 32);
7322: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7323: gen_addr_add(ctx, addr, addr, 2);
7324: gen_qemu_ld16u(ctx, t0, addr);
7325: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7326: tcg_gen_shli_tl(t0, t0, 16);
7327: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7328: #else
7329: gen_qemu_ld16u(ctx, t0, addr);
7330: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7331: tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7332: gen_addr_add(ctx, addr, addr, 2);
7333: gen_qemu_ld16u(ctx, t0, addr);
7334: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7335: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7336: #endif
7337: tcg_temp_free(t0);
7338: }
7339:
1.1.1.8 ! root 7340: static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7341: {
7342: #if defined(TARGET_PPC64)
7343: gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7344: #else
7345: TCGv_i64 t0 = tcg_temp_new_i64();
7346: tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
7347: gen_qemu_st64(ctx, t0, addr);
7348: tcg_temp_free_i64(t0);
7349: #endif
7350: }
7351:
1.1.1.8 ! root 7352: static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7353: {
7354: #if defined(TARGET_PPC64)
7355: TCGv t0 = tcg_temp_new();
7356: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7357: gen_qemu_st32(ctx, t0, addr);
7358: tcg_temp_free(t0);
7359: #else
7360: gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7361: #endif
7362: gen_addr_add(ctx, addr, addr, 4);
7363: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
1.1.1.5 root 7364: }
1.1.1.6 root 7365:
1.1.1.8 ! root 7366: static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7367: {
7368: TCGv t0 = tcg_temp_new();
7369: #if defined(TARGET_PPC64)
7370: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
1.1.1.5 root 7371: #else
1.1.1.6 root 7372: tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7373: #endif
7374: gen_qemu_st16(ctx, t0, addr);
7375: gen_addr_add(ctx, addr, addr, 2);
7376: #if defined(TARGET_PPC64)
7377: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7378: gen_qemu_st16(ctx, t0, addr);
7379: #else
7380: gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7381: #endif
7382: gen_addr_add(ctx, addr, addr, 2);
7383: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7384: gen_qemu_st16(ctx, t0, addr);
7385: tcg_temp_free(t0);
7386: gen_addr_add(ctx, addr, addr, 2);
7387: gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7388: }
7389:
1.1.1.8 ! root 7390: static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7391: {
7392: TCGv t0 = tcg_temp_new();
7393: #if defined(TARGET_PPC64)
7394: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7395: #else
7396: tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7397: #endif
7398: gen_qemu_st16(ctx, t0, addr);
7399: gen_addr_add(ctx, addr, addr, 2);
7400: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7401: gen_qemu_st16(ctx, t0, addr);
7402: tcg_temp_free(t0);
7403: }
7404:
1.1.1.8 ! root 7405: static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7406: {
7407: #if defined(TARGET_PPC64)
7408: TCGv t0 = tcg_temp_new();
7409: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7410: gen_qemu_st16(ctx, t0, addr);
7411: tcg_temp_free(t0);
7412: #else
7413: gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7414: #endif
7415: gen_addr_add(ctx, addr, addr, 2);
7416: gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7417: }
7418:
1.1.1.8 ! root 7419: static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7420: {
7421: #if defined(TARGET_PPC64)
7422: TCGv t0 = tcg_temp_new();
7423: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7424: gen_qemu_st32(ctx, t0, addr);
7425: tcg_temp_free(t0);
7426: #else
7427: gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7428: #endif
7429: }
7430:
1.1.1.8 ! root 7431: static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7432: {
7433: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7434: }
7435:
7436: #define GEN_SPEOP_LDST(name, opc2, sh) \
1.1.1.7 root 7437: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 7438: { \
7439: TCGv t0; \
7440: if (unlikely(!ctx->spe_enabled)) { \
7441: gen_exception(ctx, POWERPC_EXCP_APU); \
7442: return; \
7443: } \
7444: gen_set_access_type(ctx, ACCESS_INT); \
7445: t0 = tcg_temp_new(); \
7446: if (Rc(ctx->opcode)) { \
7447: gen_addr_spe_imm_index(ctx, t0, sh); \
7448: } else { \
7449: gen_addr_reg_index(ctx, t0); \
7450: } \
7451: gen_op_##name(ctx, t0); \
7452: tcg_temp_free(t0); \
7453: }
7454:
7455: GEN_SPEOP_LDST(evldd, 0x00, 3);
7456: GEN_SPEOP_LDST(evldw, 0x01, 3);
7457: GEN_SPEOP_LDST(evldh, 0x02, 3);
7458: GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7459: GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7460: GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7461: GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7462: GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7463: GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7464: GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7465: GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7466:
7467: GEN_SPEOP_LDST(evstdd, 0x10, 3);
7468: GEN_SPEOP_LDST(evstdw, 0x11, 3);
7469: GEN_SPEOP_LDST(evstdh, 0x12, 3);
7470: GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7471: GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7472: GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7473: GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
1.1.1.5 root 7474:
7475: /* Multiply and add - TODO */
7476: #if 0
7477: GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
7478: GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
7479: GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
7480: GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
7481: GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
7482: GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
7483: GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
7484: GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
7485: GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
7486: GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
7487: GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
7488: GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
7489:
7490: GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
7491: GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
7492: GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
7493: GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
7494: GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
7495: GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
7496: GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
7497: GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
7498: GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
7499: GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
7500: GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
7501: GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
7502: GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
7503: GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
7504:
7505: GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
7506: GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
7507: GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
7508: GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
7509: GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
7510: GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
7511:
7512: GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
7513: GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
7514: GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
7515: GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
7516: GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
7517: GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
7518: GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
7519: GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
7520: GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
7521: GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
7522: GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
7523: GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
7524:
7525: GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
7526: GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
7527: GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
7528: GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
7529: GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
7530:
7531: GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
7532: GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
7533: GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
7534: GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
7535: GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
7536: GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
7537: GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
7538: GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
7539: GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
7540: GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
7541: GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
7542: GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
7543:
7544: GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
7545: GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
7546: GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
7547: GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
7548: GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
7549: #endif
7550:
7551: /*** SPE floating-point extension ***/
1.1.1.6 root 7552: #if defined(TARGET_PPC64)
7553: #define GEN_SPEFPUOP_CONV_32_32(name) \
1.1.1.8 ! root 7554: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7555: { \
7556: TCGv_i32 t0; \
7557: TCGv t1; \
7558: t0 = tcg_temp_new_i32(); \
7559: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7560: gen_helper_##name(t0, t0); \
7561: t1 = tcg_temp_new(); \
7562: tcg_gen_extu_i32_tl(t1, t0); \
7563: tcg_temp_free_i32(t0); \
7564: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7565: 0xFFFFFFFF00000000ULL); \
7566: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7567: tcg_temp_free(t1); \
7568: }
7569: #define GEN_SPEFPUOP_CONV_32_64(name) \
1.1.1.8 ! root 7570: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7571: { \
7572: TCGv_i32 t0; \
7573: TCGv t1; \
7574: t0 = tcg_temp_new_i32(); \
7575: gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7576: t1 = tcg_temp_new(); \
7577: tcg_gen_extu_i32_tl(t1, t0); \
7578: tcg_temp_free_i32(t0); \
7579: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7580: 0xFFFFFFFF00000000ULL); \
7581: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7582: tcg_temp_free(t1); \
7583: }
7584: #define GEN_SPEFPUOP_CONV_64_32(name) \
1.1.1.8 ! root 7585: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7586: { \
7587: TCGv_i32 t0 = tcg_temp_new_i32(); \
7588: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7589: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7590: tcg_temp_free_i32(t0); \
7591: }
7592: #define GEN_SPEFPUOP_CONV_64_64(name) \
1.1.1.8 ! root 7593: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7594: { \
7595: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7596: }
7597: #define GEN_SPEFPUOP_ARITH2_32_32(name) \
1.1.1.8 ! root 7598: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7599: { \
7600: TCGv_i32 t0, t1; \
7601: TCGv_i64 t2; \
7602: if (unlikely(!ctx->spe_enabled)) { \
7603: gen_exception(ctx, POWERPC_EXCP_APU); \
7604: return; \
7605: } \
7606: t0 = tcg_temp_new_i32(); \
7607: t1 = tcg_temp_new_i32(); \
7608: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7609: tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7610: gen_helper_##name(t0, t0, t1); \
7611: tcg_temp_free_i32(t1); \
7612: t2 = tcg_temp_new(); \
7613: tcg_gen_extu_i32_tl(t2, t0); \
7614: tcg_temp_free_i32(t0); \
7615: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7616: 0xFFFFFFFF00000000ULL); \
7617: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
7618: tcg_temp_free(t2); \
7619: }
7620: #define GEN_SPEFPUOP_ARITH2_64_64(name) \
1.1.1.8 ! root 7621: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 7622: { \
1.1.1.6 root 7623: if (unlikely(!ctx->spe_enabled)) { \
7624: gen_exception(ctx, POWERPC_EXCP_APU); \
7625: return; \
7626: } \
7627: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7628: cpu_gpr[rB(ctx->opcode)]); \
1.1 root 7629: }
1.1.1.6 root 7630: #define GEN_SPEFPUOP_COMP_32(name) \
1.1.1.8 ! root 7631: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7632: { \
7633: TCGv_i32 t0, t1; \
7634: if (unlikely(!ctx->spe_enabled)) { \
7635: gen_exception(ctx, POWERPC_EXCP_APU); \
7636: return; \
7637: } \
7638: t0 = tcg_temp_new_i32(); \
7639: t1 = tcg_temp_new_i32(); \
7640: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7641: tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7642: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7643: tcg_temp_free_i32(t0); \
7644: tcg_temp_free_i32(t1); \
7645: }
7646: #define GEN_SPEFPUOP_COMP_64(name) \
1.1.1.8 ! root 7647: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7648: { \
7649: if (unlikely(!ctx->spe_enabled)) { \
7650: gen_exception(ctx, POWERPC_EXCP_APU); \
7651: return; \
7652: } \
7653: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7654: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7655: }
7656: #else
7657: #define GEN_SPEFPUOP_CONV_32_32(name) \
1.1.1.8 ! root 7658: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7659: { \
7660: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7661: }
7662: #define GEN_SPEFPUOP_CONV_32_64(name) \
1.1.1.8 ! root 7663: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7664: { \
7665: TCGv_i64 t0 = tcg_temp_new_i64(); \
7666: gen_load_gpr64(t0, rB(ctx->opcode)); \
7667: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7668: tcg_temp_free_i64(t0); \
7669: }
7670: #define GEN_SPEFPUOP_CONV_64_32(name) \
1.1.1.8 ! root 7671: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7672: { \
7673: TCGv_i64 t0 = tcg_temp_new_i64(); \
7674: gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7675: gen_store_gpr64(rD(ctx->opcode), t0); \
7676: tcg_temp_free_i64(t0); \
7677: }
7678: #define GEN_SPEFPUOP_CONV_64_64(name) \
1.1.1.8 ! root 7679: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7680: { \
7681: TCGv_i64 t0 = tcg_temp_new_i64(); \
7682: gen_load_gpr64(t0, rB(ctx->opcode)); \
7683: gen_helper_##name(t0, t0); \
7684: gen_store_gpr64(rD(ctx->opcode), t0); \
7685: tcg_temp_free_i64(t0); \
7686: }
7687: #define GEN_SPEFPUOP_ARITH2_32_32(name) \
1.1.1.8 ! root 7688: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7689: { \
7690: if (unlikely(!ctx->spe_enabled)) { \
7691: gen_exception(ctx, POWERPC_EXCP_APU); \
7692: return; \
7693: } \
7694: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \
7695: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7696: }
7697: #define GEN_SPEFPUOP_ARITH2_64_64(name) \
1.1.1.8 ! root 7698: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7699: { \
7700: TCGv_i64 t0, t1; \
7701: if (unlikely(!ctx->spe_enabled)) { \
7702: gen_exception(ctx, POWERPC_EXCP_APU); \
7703: return; \
7704: } \
7705: t0 = tcg_temp_new_i64(); \
7706: t1 = tcg_temp_new_i64(); \
7707: gen_load_gpr64(t0, rA(ctx->opcode)); \
7708: gen_load_gpr64(t1, rB(ctx->opcode)); \
7709: gen_helper_##name(t0, t0, t1); \
7710: gen_store_gpr64(rD(ctx->opcode), t0); \
7711: tcg_temp_free_i64(t0); \
7712: tcg_temp_free_i64(t1); \
7713: }
7714: #define GEN_SPEFPUOP_COMP_32(name) \
1.1.1.8 ! root 7715: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7716: { \
7717: if (unlikely(!ctx->spe_enabled)) { \
7718: gen_exception(ctx, POWERPC_EXCP_APU); \
7719: return; \
7720: } \
7721: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7722: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7723: }
7724: #define GEN_SPEFPUOP_COMP_64(name) \
1.1.1.8 ! root 7725: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7726: { \
7727: TCGv_i64 t0, t1; \
7728: if (unlikely(!ctx->spe_enabled)) { \
7729: gen_exception(ctx, POWERPC_EXCP_APU); \
7730: return; \
7731: } \
7732: t0 = tcg_temp_new_i64(); \
7733: t1 = tcg_temp_new_i64(); \
7734: gen_load_gpr64(t0, rA(ctx->opcode)); \
7735: gen_load_gpr64(t1, rB(ctx->opcode)); \
7736: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7737: tcg_temp_free_i64(t0); \
7738: tcg_temp_free_i64(t1); \
7739: }
7740: #endif
1.1 root 7741:
1.1.1.5 root 7742: /* Single precision floating-point vectors operations */
7743: /* Arithmetic */
1.1.1.6 root 7744: GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7745: GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7746: GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7747: GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
1.1.1.8 ! root 7748: static inline void gen_evfsabs(DisasContext *ctx)
1.1.1.6 root 7749: {
7750: if (unlikely(!ctx->spe_enabled)) {
7751: gen_exception(ctx, POWERPC_EXCP_APU);
7752: return;
7753: }
7754: #if defined(TARGET_PPC64)
7755: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7756: #else
7757: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7758: tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7759: #endif
7760: }
1.1.1.8 ! root 7761: static inline void gen_evfsnabs(DisasContext *ctx)
1.1.1.6 root 7762: {
7763: if (unlikely(!ctx->spe_enabled)) {
7764: gen_exception(ctx, POWERPC_EXCP_APU);
7765: return;
7766: }
7767: #if defined(TARGET_PPC64)
7768: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7769: #else
7770: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7771: tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7772: #endif
7773: }
1.1.1.8 ! root 7774: static inline void gen_evfsneg(DisasContext *ctx)
1.1.1.6 root 7775: {
7776: if (unlikely(!ctx->spe_enabled)) {
7777: gen_exception(ctx, POWERPC_EXCP_APU);
7778: return;
7779: }
7780: #if defined(TARGET_PPC64)
7781: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7782: #else
7783: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7784: tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7785: #endif
7786: }
7787:
1.1.1.5 root 7788: /* Conversion */
1.1.1.6 root 7789: GEN_SPEFPUOP_CONV_64_64(evfscfui);
7790: GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7791: GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7792: GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7793: GEN_SPEFPUOP_CONV_64_64(evfsctui);
7794: GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7795: GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7796: GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7797: GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7798: GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7799:
1.1.1.5 root 7800: /* Comparison */
1.1.1.6 root 7801: GEN_SPEFPUOP_COMP_64(evfscmpgt);
7802: GEN_SPEFPUOP_COMP_64(evfscmplt);
7803: GEN_SPEFPUOP_COMP_64(evfscmpeq);
7804: GEN_SPEFPUOP_COMP_64(evfststgt);
7805: GEN_SPEFPUOP_COMP_64(evfststlt);
7806: GEN_SPEFPUOP_COMP_64(evfststeq);
1.1.1.5 root 7807:
7808: /* Opcodes definitions */
1.1.1.6 root 7809: GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7810: GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7811: GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7812: GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7813: GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7814: GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7815: GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7816: GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7817: GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7818: GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7819: GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7820: GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7821: GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7822: GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
1.1.1.5 root 7823:
7824: /* Single precision floating-point operations */
7825: /* Arithmetic */
1.1.1.6 root 7826: GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7827: GEN_SPEFPUOP_ARITH2_32_32(efssub);
7828: GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7829: GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
1.1.1.8 ! root 7830: static inline void gen_efsabs(DisasContext *ctx)
1.1.1.6 root 7831: {
7832: if (unlikely(!ctx->spe_enabled)) {
7833: gen_exception(ctx, POWERPC_EXCP_APU);
7834: return;
7835: }
7836: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7837: }
1.1.1.8 ! root 7838: static inline void gen_efsnabs(DisasContext *ctx)
1.1.1.6 root 7839: {
7840: if (unlikely(!ctx->spe_enabled)) {
7841: gen_exception(ctx, POWERPC_EXCP_APU);
7842: return;
7843: }
7844: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7845: }
1.1.1.8 ! root 7846: static inline void gen_efsneg(DisasContext *ctx)
1.1.1.6 root 7847: {
7848: if (unlikely(!ctx->spe_enabled)) {
7849: gen_exception(ctx, POWERPC_EXCP_APU);
7850: return;
7851: }
7852: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7853: }
7854:
1.1.1.5 root 7855: /* Conversion */
1.1.1.6 root 7856: GEN_SPEFPUOP_CONV_32_32(efscfui);
7857: GEN_SPEFPUOP_CONV_32_32(efscfsi);
7858: GEN_SPEFPUOP_CONV_32_32(efscfuf);
7859: GEN_SPEFPUOP_CONV_32_32(efscfsf);
7860: GEN_SPEFPUOP_CONV_32_32(efsctui);
7861: GEN_SPEFPUOP_CONV_32_32(efsctsi);
7862: GEN_SPEFPUOP_CONV_32_32(efsctuf);
7863: GEN_SPEFPUOP_CONV_32_32(efsctsf);
7864: GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7865: GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7866: GEN_SPEFPUOP_CONV_32_64(efscfd);
7867:
1.1.1.5 root 7868: /* Comparison */
1.1.1.6 root 7869: GEN_SPEFPUOP_COMP_32(efscmpgt);
7870: GEN_SPEFPUOP_COMP_32(efscmplt);
7871: GEN_SPEFPUOP_COMP_32(efscmpeq);
7872: GEN_SPEFPUOP_COMP_32(efststgt);
7873: GEN_SPEFPUOP_COMP_32(efststlt);
7874: GEN_SPEFPUOP_COMP_32(efststeq);
1.1.1.5 root 7875:
7876: /* Opcodes definitions */
1.1.1.6 root 7877: GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7878: GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7879: GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7880: GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7881: GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7882: GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7883: GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7884: GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7885: GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7886: GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7887: GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7888: GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7889: GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7890: GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
1.1.1.5 root 7891:
7892: /* Double precision floating-point operations */
7893: /* Arithmetic */
1.1.1.6 root 7894: GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7895: GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7896: GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7897: GEN_SPEFPUOP_ARITH2_64_64(efddiv);
1.1.1.8 ! root 7898: static inline void gen_efdabs(DisasContext *ctx)
1.1.1.6 root 7899: {
7900: if (unlikely(!ctx->spe_enabled)) {
7901: gen_exception(ctx, POWERPC_EXCP_APU);
7902: return;
7903: }
7904: #if defined(TARGET_PPC64)
7905: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7906: #else
7907: tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7908: #endif
7909: }
1.1.1.8 ! root 7910: static inline void gen_efdnabs(DisasContext *ctx)
1.1.1.6 root 7911: {
7912: if (unlikely(!ctx->spe_enabled)) {
7913: gen_exception(ctx, POWERPC_EXCP_APU);
7914: return;
7915: }
7916: #if defined(TARGET_PPC64)
7917: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7918: #else
7919: tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7920: #endif
7921: }
1.1.1.8 ! root 7922: static inline void gen_efdneg(DisasContext *ctx)
1.1.1.6 root 7923: {
7924: if (unlikely(!ctx->spe_enabled)) {
7925: gen_exception(ctx, POWERPC_EXCP_APU);
7926: return;
7927: }
7928: #if defined(TARGET_PPC64)
7929: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7930: #else
7931: tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7932: #endif
7933: }
7934:
1.1.1.5 root 7935: /* Conversion */
1.1.1.6 root 7936: GEN_SPEFPUOP_CONV_64_32(efdcfui);
7937: GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7938: GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7939: GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7940: GEN_SPEFPUOP_CONV_32_64(efdctui);
7941: GEN_SPEFPUOP_CONV_32_64(efdctsi);
7942: GEN_SPEFPUOP_CONV_32_64(efdctuf);
7943: GEN_SPEFPUOP_CONV_32_64(efdctsf);
7944: GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7945: GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7946: GEN_SPEFPUOP_CONV_64_32(efdcfs);
7947: GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7948: GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7949: GEN_SPEFPUOP_CONV_64_64(efdctuidz);
7950: GEN_SPEFPUOP_CONV_64_64(efdctsidz);
1.1.1.5 root 7951:
7952: /* Comparison */
1.1.1.6 root 7953: GEN_SPEFPUOP_COMP_64(efdcmpgt);
7954: GEN_SPEFPUOP_COMP_64(efdcmplt);
7955: GEN_SPEFPUOP_COMP_64(efdcmpeq);
7956: GEN_SPEFPUOP_COMP_64(efdtstgt);
7957: GEN_SPEFPUOP_COMP_64(efdtstlt);
7958: GEN_SPEFPUOP_COMP_64(efdtsteq);
1.1.1.5 root 7959:
7960: /* Opcodes definitions */
1.1.1.6 root 7961: GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
7962: GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7963: GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
7964: GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
7965: GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
7966: GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7967: GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7968: GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7969: GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7970: GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7971: GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7972: GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7973: GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7974: GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7975: GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7976: GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
1.1.1.5 root 7977:
1.1.1.7 root 7978: static opcode_t opcodes[] = {
7979: GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
7980: GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
7981: GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
7982: GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
7983: GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
7984: GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
7985: GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7986: GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7987: GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7988: GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7989: GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
7990: GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
7991: GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
7992: GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
7993: GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7994: #if defined(TARGET_PPC64)
7995: GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
7996: #endif
7997: GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
7998: GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
7999: GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8000: GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8001: GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8002: GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
8003: GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
8004: GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
8005: GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8006: GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8007: GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8008: GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8009: GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
8010: #if defined(TARGET_PPC64)
8011: GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
8012: #endif
8013: GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8014: GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8015: GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8016: GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
8017: GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
8018: GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
8019: GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
8020: #if defined(TARGET_PPC64)
8021: GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
8022: GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
8023: GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
8024: GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
8025: GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
8026: #endif
8027: GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
8028: GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8029: GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8030: GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
8031: GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
8032: GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
8033: GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
8034: GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
8035: GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
8036: GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
8037: GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
8038: GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
8039: #if defined(TARGET_PPC64)
8040: GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
8041: GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
8042: GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
8043: #endif
8044: GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8045: GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8046: GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
8047: GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
8048: GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
8049: GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
8050: GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
8051: GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
8052: GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES),
8053: GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
8054: #if defined(TARGET_PPC64)
8055: GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B),
8056: GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
8057: #endif
8058: GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
8059: GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
8060: GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8061: GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8062: GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
8063: GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
8064: GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
8065: GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
8066: #if defined(TARGET_PPC64)
8067: GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
8068: GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
8069: #endif
8070: GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
8071: GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
8072: GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8073: #if defined(TARGET_PPC64)
8074: GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
8075: GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
8076: #endif
8077: GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
8078: GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
8079: GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
8080: GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
8081: GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
8082: GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
8083: #if defined(TARGET_PPC64)
8084: GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
8085: #endif
8086: GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
8087: GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC),
8088: GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
8089: GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
8090: GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
8091: GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE),
8092: GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE),
8093: GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ),
8094: GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT),
8095: GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
8096: GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
8097: GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
8098: GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
8099: GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
8100: GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
8101: GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
8102: GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
8103: GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
8104: #if defined(TARGET_PPC64)
8105: GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
8106: GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
8107: PPC_SEGMENT_64B),
8108: GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
8109: GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
8110: PPC_SEGMENT_64B),
8111: GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B),
8112: #endif
8113: GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
8114: GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
8115: GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
8116: GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
8117: #if defined(TARGET_PPC64)
8118: GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
8119: GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
8120: #endif
8121: GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
8122: GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
8123: GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
8124: GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
8125: GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
8126: GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
8127: GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
8128: GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
8129: GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
8130: GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
8131: GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
8132: GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8133: GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
8134: GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
8135: GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
8136: GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
8137: GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
8138: GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
8139: GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
8140: GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8141: GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
8142: GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
8143: GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
8144: GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
8145: GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
8146: GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
8147: GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
8148: GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
8149: GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
8150: GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
8151: GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
8152: GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
8153: GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
8154: GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
8155: GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
8156: GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
8157: GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
8158: GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
8159: GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
8160: GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
8161: GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
8162: GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
8163: GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
8164: GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
8165: GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
8166: GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
8167: GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
8168: GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
8169: GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
8170: GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8171: GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8172: GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
8173: GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
8174: GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8175: GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8176: GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
8177: GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
8178: GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
8179: GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
8180: GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
8181: GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
8182: GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
8183: GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
8184: GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
8185: GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
8186: GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
8187: GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
8188: GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
8189: GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
8190: GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
8191: GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
8192: GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE),
8193: GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
8194: GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
8195: GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
8196: GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
8197: GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
8198: GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
8199: GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
8200: GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
8201: GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8202: GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8203: GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
8204: GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE),
8205: GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
8206: GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE),
8207: GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
8208: GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
8209: GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
8210: GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
8211: GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC),
8212: GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
8213: GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
8214: GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
8215: GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
8216: GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
8217:
8218: #undef GEN_INT_ARITH_ADD
8219: #undef GEN_INT_ARITH_ADD_CONST
8220: #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
8221: GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
8222: #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
8223: add_ca, compute_ca, compute_ov) \
8224: GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
8225: GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
8226: GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
8227: GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
8228: GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
8229: GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
8230: GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
8231: GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
8232: GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
8233: GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
8234: GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
8235:
8236: #undef GEN_INT_ARITH_DIVW
8237: #define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
8238: GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
8239: GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
8240: GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
8241: GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
8242: GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
8243:
8244: #if defined(TARGET_PPC64)
8245: #undef GEN_INT_ARITH_DIVD
8246: #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
8247: GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8248: GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
8249: GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
8250: GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
8251: GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
8252:
8253: #undef GEN_INT_ARITH_MUL_HELPER
8254: #define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
8255: GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8256: GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
8257: GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
8258: GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
8259: #endif
8260:
8261: #undef GEN_INT_ARITH_SUBF
8262: #undef GEN_INT_ARITH_SUBF_CONST
8263: #define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
8264: GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
8265: #define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
8266: add_ca, compute_ca, compute_ov) \
8267: GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
8268: GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
8269: GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
8270: GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
8271: GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
8272: GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
8273: GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
8274: GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
8275: GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
8276: GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
8277: GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
8278:
8279: #undef GEN_LOGICAL1
8280: #undef GEN_LOGICAL2
8281: #define GEN_LOGICAL2(name, tcg_op, opc, type) \
8282: GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
8283: #define GEN_LOGICAL1(name, tcg_op, opc, type) \
8284: GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
8285: GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
8286: GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
8287: GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
8288: GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
8289: GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
8290: GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
8291: GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
8292: GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
8293: #if defined(TARGET_PPC64)
8294: GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
8295: #endif
8296:
8297: #if defined(TARGET_PPC64)
8298: #undef GEN_PPC64_R2
8299: #undef GEN_PPC64_R4
8300: #define GEN_PPC64_R2(name, opc1, opc2) \
8301: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8302: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8303: PPC_64B)
8304: #define GEN_PPC64_R4(name, opc1, opc2) \
8305: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8306: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
8307: PPC_64B), \
8308: GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8309: PPC_64B), \
8310: GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
8311: PPC_64B)
8312: GEN_PPC64_R4(rldicl, 0x1E, 0x00),
8313: GEN_PPC64_R4(rldicr, 0x1E, 0x02),
8314: GEN_PPC64_R4(rldic, 0x1E, 0x04),
8315: GEN_PPC64_R2(rldcl, 0x1E, 0x08),
8316: GEN_PPC64_R2(rldcr, 0x1E, 0x09),
8317: GEN_PPC64_R4(rldimi, 0x1E, 0x06),
8318: #endif
8319:
8320: #undef _GEN_FLOAT_ACB
8321: #undef GEN_FLOAT_ACB
8322: #undef _GEN_FLOAT_AB
8323: #undef GEN_FLOAT_AB
8324: #undef _GEN_FLOAT_AC
8325: #undef GEN_FLOAT_AC
8326: #undef GEN_FLOAT_B
8327: #undef GEN_FLOAT_BS
8328: #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
8329: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
8330: #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
8331: _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type), \
8332: _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
8333: #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8334: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8335: #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
8336: _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8337: _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8338: #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8339: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8340: #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
8341: _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8342: _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8343: #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
8344: GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
8345: #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
8346: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
8347:
8348: GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
8349: GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
8350: GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
8351: GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
8352: GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
8353: GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
8354: _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
8355: GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
8356: GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
8357: GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
8358: GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
8359: GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
8360: GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
8361: GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
8362: GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
8363: #if defined(TARGET_PPC64)
8364: GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
8365: GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
8366: GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
8367: #endif
8368: GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
8369: GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
8370: GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
8371: GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
8372: GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT),
8373: GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT),
8374: GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
8375:
8376: #undef GEN_LD
8377: #undef GEN_LDU
8378: #undef GEN_LDUX
8379: #undef GEN_LDX
8380: #undef GEN_LDS
8381: #define GEN_LD(name, ldop, opc, type) \
8382: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8383: #define GEN_LDU(name, ldop, opc, type) \
8384: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8385: #define GEN_LDUX(name, ldop, opc2, opc3, type) \
8386: GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8387: #define GEN_LDX(name, ldop, opc2, opc3, type) \
8388: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8389: #define GEN_LDS(name, ldop, op, type) \
8390: GEN_LD(name, ldop, op | 0x20, type) \
8391: GEN_LDU(name, ldop, op | 0x21, type) \
8392: GEN_LDUX(name, ldop, 0x17, op | 0x01, type) \
8393: GEN_LDX(name, ldop, 0x17, op | 0x00, type)
8394:
8395: GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
8396: GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
8397: GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
8398: GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
8399: #if defined(TARGET_PPC64)
8400: GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
8401: GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
8402: GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
8403: GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
8404: #endif
8405: GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
8406: GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
8407:
8408: #undef GEN_ST
8409: #undef GEN_STU
8410: #undef GEN_STUX
8411: #undef GEN_STX
8412: #undef GEN_STS
8413: #define GEN_ST(name, stop, opc, type) \
8414: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8415: #define GEN_STU(name, stop, opc, type) \
8416: GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
8417: #define GEN_STUX(name, stop, opc2, opc3, type) \
8418: GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8419: #define GEN_STX(name, stop, opc2, opc3, type) \
8420: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8421: #define GEN_STS(name, stop, op, type) \
8422: GEN_ST(name, stop, op | 0x20, type) \
8423: GEN_STU(name, stop, op | 0x21, type) \
8424: GEN_STUX(name, stop, 0x17, op | 0x01, type) \
8425: GEN_STX(name, stop, 0x17, op | 0x00, type)
8426:
8427: GEN_STS(stb, st8, 0x06, PPC_INTEGER)
8428: GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
8429: GEN_STS(stw, st32, 0x04, PPC_INTEGER)
8430: #if defined(TARGET_PPC64)
8431: GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
8432: GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
8433: #endif
8434: GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
8435: GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
8436:
8437: #undef GEN_LDF
8438: #undef GEN_LDUF
8439: #undef GEN_LDUXF
8440: #undef GEN_LDXF
8441: #undef GEN_LDFS
8442: #define GEN_LDF(name, ldop, opc, type) \
8443: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8444: #define GEN_LDUF(name, ldop, opc, type) \
8445: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8446: #define GEN_LDUXF(name, ldop, opc, type) \
8447: GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8448: #define GEN_LDXF(name, ldop, opc2, opc3, type) \
8449: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8450: #define GEN_LDFS(name, ldop, op, type) \
8451: GEN_LDF(name, ldop, op | 0x20, type) \
8452: GEN_LDUF(name, ldop, op | 0x21, type) \
8453: GEN_LDUXF(name, ldop, op | 0x01, type) \
8454: GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
8455:
8456: GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
8457: GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
8458:
8459: #undef GEN_STF
8460: #undef GEN_STUF
8461: #undef GEN_STUXF
8462: #undef GEN_STXF
8463: #undef GEN_STFS
8464: #define GEN_STF(name, stop, opc, type) \
8465: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8466: #define GEN_STUF(name, stop, opc, type) \
8467: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8468: #define GEN_STUXF(name, stop, opc, type) \
8469: GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8470: #define GEN_STXF(name, stop, opc2, opc3, type) \
8471: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8472: #define GEN_STFS(name, stop, op, type) \
8473: GEN_STF(name, stop, op | 0x20, type) \
8474: GEN_STUF(name, stop, op | 0x21, type) \
8475: GEN_STUXF(name, stop, op | 0x01, type) \
8476: GEN_STXF(name, stop, 0x17, op | 0x00, type)
8477:
8478: GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
8479: GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
8480: GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
8481:
8482: #undef GEN_CRLOGIC
8483: #define GEN_CRLOGIC(name, tcg_op, opc) \
8484: GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
8485: GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
8486: GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
8487: GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
8488: GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
8489: GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
8490: GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
8491: GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
8492: GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
8493:
8494: #undef GEN_MAC_HANDLER
8495: #define GEN_MAC_HANDLER(name, opc2, opc3) \
8496: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
8497: GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
8498: GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
8499: GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
8500: GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
8501: GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
8502: GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
8503: GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
8504: GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
8505: GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
8506: GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
8507: GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
8508: GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
8509: GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
8510: GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
8511: GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
8512: GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
8513: GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
8514: GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
8515: GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
8516: GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
8517: GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
8518: GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
8519: GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
8520: GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
8521: GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
8522: GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
8523: GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
8524: GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
8525: GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
8526: GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
8527: GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
8528: GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
8529: GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
8530: GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
8531: GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
8532: GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
8533: GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
8534: GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
8535: GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
8536: GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
8537: GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
8538: GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
8539:
8540: #undef GEN_VR_LDX
8541: #undef GEN_VR_STX
8542: #undef GEN_VR_LVE
8543: #undef GEN_VR_STVE
8544: #define GEN_VR_LDX(name, opc2, opc3) \
8545: GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8546: #define GEN_VR_STX(name, opc2, opc3) \
8547: GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8548: #define GEN_VR_LVE(name, opc2, opc3) \
8549: GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8550: #define GEN_VR_STVE(name, opc2, opc3) \
8551: GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8552: GEN_VR_LDX(lvx, 0x07, 0x03),
8553: GEN_VR_LDX(lvxl, 0x07, 0x0B),
8554: GEN_VR_LVE(bx, 0x07, 0x00),
8555: GEN_VR_LVE(hx, 0x07, 0x01),
8556: GEN_VR_LVE(wx, 0x07, 0x02),
8557: GEN_VR_STX(svx, 0x07, 0x07),
8558: GEN_VR_STX(svxl, 0x07, 0x0F),
8559: GEN_VR_STVE(bx, 0x07, 0x04),
8560: GEN_VR_STVE(hx, 0x07, 0x05),
8561: GEN_VR_STVE(wx, 0x07, 0x06),
8562:
8563: #undef GEN_VX_LOGICAL
8564: #define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
8565: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8566: GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
8567: GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
8568: GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
8569: GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
8570: GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
8571:
8572: #undef GEN_VXFORM
8573: #define GEN_VXFORM(name, opc2, opc3) \
8574: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8575: GEN_VXFORM(vaddubm, 0, 0),
8576: GEN_VXFORM(vadduhm, 0, 1),
8577: GEN_VXFORM(vadduwm, 0, 2),
8578: GEN_VXFORM(vsububm, 0, 16),
8579: GEN_VXFORM(vsubuhm, 0, 17),
8580: GEN_VXFORM(vsubuwm, 0, 18),
8581: GEN_VXFORM(vmaxub, 1, 0),
8582: GEN_VXFORM(vmaxuh, 1, 1),
8583: GEN_VXFORM(vmaxuw, 1, 2),
8584: GEN_VXFORM(vmaxsb, 1, 4),
8585: GEN_VXFORM(vmaxsh, 1, 5),
8586: GEN_VXFORM(vmaxsw, 1, 6),
8587: GEN_VXFORM(vminub, 1, 8),
8588: GEN_VXFORM(vminuh, 1, 9),
8589: GEN_VXFORM(vminuw, 1, 10),
8590: GEN_VXFORM(vminsb, 1, 12),
8591: GEN_VXFORM(vminsh, 1, 13),
8592: GEN_VXFORM(vminsw, 1, 14),
8593: GEN_VXFORM(vavgub, 1, 16),
8594: GEN_VXFORM(vavguh, 1, 17),
8595: GEN_VXFORM(vavguw, 1, 18),
8596: GEN_VXFORM(vavgsb, 1, 20),
8597: GEN_VXFORM(vavgsh, 1, 21),
8598: GEN_VXFORM(vavgsw, 1, 22),
8599: GEN_VXFORM(vmrghb, 6, 0),
8600: GEN_VXFORM(vmrghh, 6, 1),
8601: GEN_VXFORM(vmrghw, 6, 2),
8602: GEN_VXFORM(vmrglb, 6, 4),
8603: GEN_VXFORM(vmrglh, 6, 5),
8604: GEN_VXFORM(vmrglw, 6, 6),
8605: GEN_VXFORM(vmuloub, 4, 0),
8606: GEN_VXFORM(vmulouh, 4, 1),
8607: GEN_VXFORM(vmulosb, 4, 4),
8608: GEN_VXFORM(vmulosh, 4, 5),
8609: GEN_VXFORM(vmuleub, 4, 8),
8610: GEN_VXFORM(vmuleuh, 4, 9),
8611: GEN_VXFORM(vmulesb, 4, 12),
8612: GEN_VXFORM(vmulesh, 4, 13),
8613: GEN_VXFORM(vslb, 2, 4),
8614: GEN_VXFORM(vslh, 2, 5),
8615: GEN_VXFORM(vslw, 2, 6),
8616: GEN_VXFORM(vsrb, 2, 8),
8617: GEN_VXFORM(vsrh, 2, 9),
8618: GEN_VXFORM(vsrw, 2, 10),
8619: GEN_VXFORM(vsrab, 2, 12),
8620: GEN_VXFORM(vsrah, 2, 13),
8621: GEN_VXFORM(vsraw, 2, 14),
8622: GEN_VXFORM(vslo, 6, 16),
8623: GEN_VXFORM(vsro, 6, 17),
8624: GEN_VXFORM(vaddcuw, 0, 6),
8625: GEN_VXFORM(vsubcuw, 0, 22),
8626: GEN_VXFORM(vaddubs, 0, 8),
8627: GEN_VXFORM(vadduhs, 0, 9),
8628: GEN_VXFORM(vadduws, 0, 10),
8629: GEN_VXFORM(vaddsbs, 0, 12),
8630: GEN_VXFORM(vaddshs, 0, 13),
8631: GEN_VXFORM(vaddsws, 0, 14),
8632: GEN_VXFORM(vsububs, 0, 24),
8633: GEN_VXFORM(vsubuhs, 0, 25),
8634: GEN_VXFORM(vsubuws, 0, 26),
8635: GEN_VXFORM(vsubsbs, 0, 28),
8636: GEN_VXFORM(vsubshs, 0, 29),
8637: GEN_VXFORM(vsubsws, 0, 30),
8638: GEN_VXFORM(vrlb, 2, 0),
8639: GEN_VXFORM(vrlh, 2, 1),
8640: GEN_VXFORM(vrlw, 2, 2),
8641: GEN_VXFORM(vsl, 2, 7),
8642: GEN_VXFORM(vsr, 2, 11),
8643: GEN_VXFORM(vpkuhum, 7, 0),
8644: GEN_VXFORM(vpkuwum, 7, 1),
8645: GEN_VXFORM(vpkuhus, 7, 2),
8646: GEN_VXFORM(vpkuwus, 7, 3),
8647: GEN_VXFORM(vpkshus, 7, 4),
8648: GEN_VXFORM(vpkswus, 7, 5),
8649: GEN_VXFORM(vpkshss, 7, 6),
8650: GEN_VXFORM(vpkswss, 7, 7),
8651: GEN_VXFORM(vpkpx, 7, 12),
8652: GEN_VXFORM(vsum4ubs, 4, 24),
8653: GEN_VXFORM(vsum4sbs, 4, 28),
8654: GEN_VXFORM(vsum4shs, 4, 25),
8655: GEN_VXFORM(vsum2sws, 4, 26),
8656: GEN_VXFORM(vsumsws, 4, 30),
8657: GEN_VXFORM(vaddfp, 5, 0),
8658: GEN_VXFORM(vsubfp, 5, 1),
8659: GEN_VXFORM(vmaxfp, 5, 16),
8660: GEN_VXFORM(vminfp, 5, 17),
8661:
8662: #undef GEN_VXRFORM1
8663: #undef GEN_VXRFORM
8664: #define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
8665: GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
8666: #define GEN_VXRFORM(name, opc2, opc3) \
8667: GEN_VXRFORM1(name, name, #name, opc2, opc3) \
8668: GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
8669: GEN_VXRFORM(vcmpequb, 3, 0)
8670: GEN_VXRFORM(vcmpequh, 3, 1)
8671: GEN_VXRFORM(vcmpequw, 3, 2)
8672: GEN_VXRFORM(vcmpgtsb, 3, 12)
8673: GEN_VXRFORM(vcmpgtsh, 3, 13)
8674: GEN_VXRFORM(vcmpgtsw, 3, 14)
8675: GEN_VXRFORM(vcmpgtub, 3, 8)
8676: GEN_VXRFORM(vcmpgtuh, 3, 9)
8677: GEN_VXRFORM(vcmpgtuw, 3, 10)
8678: GEN_VXRFORM(vcmpeqfp, 3, 3)
8679: GEN_VXRFORM(vcmpgefp, 3, 7)
8680: GEN_VXRFORM(vcmpgtfp, 3, 11)
8681: GEN_VXRFORM(vcmpbfp, 3, 15)
8682:
8683: #undef GEN_VXFORM_SIMM
8684: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
8685: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8686: GEN_VXFORM_SIMM(vspltisb, 6, 12),
8687: GEN_VXFORM_SIMM(vspltish, 6, 13),
8688: GEN_VXFORM_SIMM(vspltisw, 6, 14),
8689:
8690: #undef GEN_VXFORM_NOA
8691: #define GEN_VXFORM_NOA(name, opc2, opc3) \
8692: GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
8693: GEN_VXFORM_NOA(vupkhsb, 7, 8),
8694: GEN_VXFORM_NOA(vupkhsh, 7, 9),
8695: GEN_VXFORM_NOA(vupklsb, 7, 10),
8696: GEN_VXFORM_NOA(vupklsh, 7, 11),
8697: GEN_VXFORM_NOA(vupkhpx, 7, 13),
8698: GEN_VXFORM_NOA(vupklpx, 7, 15),
8699: GEN_VXFORM_NOA(vrefp, 5, 4),
8700: GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
8701: GEN_VXFORM_NOA(vlogefp, 5, 7),
8702: GEN_VXFORM_NOA(vrfim, 5, 8),
8703: GEN_VXFORM_NOA(vrfin, 5, 9),
8704: GEN_VXFORM_NOA(vrfip, 5, 10),
8705: GEN_VXFORM_NOA(vrfiz, 5, 11),
8706:
8707: #undef GEN_VXFORM_UIMM
8708: #define GEN_VXFORM_UIMM(name, opc2, opc3) \
8709: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8710: GEN_VXFORM_UIMM(vspltb, 6, 8),
8711: GEN_VXFORM_UIMM(vsplth, 6, 9),
8712: GEN_VXFORM_UIMM(vspltw, 6, 10),
8713: GEN_VXFORM_UIMM(vcfux, 5, 12),
8714: GEN_VXFORM_UIMM(vcfsx, 5, 13),
8715: GEN_VXFORM_UIMM(vctuxs, 5, 14),
8716: GEN_VXFORM_UIMM(vctsxs, 5, 15),
8717:
8718: #undef GEN_VAFORM_PAIRED
8719: #define GEN_VAFORM_PAIRED(name0, name1, opc2) \
8720: GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
8721: GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
8722: GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
8723: GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
8724: GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
8725: GEN_VAFORM_PAIRED(vsel, vperm, 21),
8726: GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
8727:
8728: #undef GEN_SPE
8729: #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
8730: GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)
8731: GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE),
8732: GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE),
8733: GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE),
8734: GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE),
8735: GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE),
8736: GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE),
8737: GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE),
8738: GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE),
8739: GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE),
8740: GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE),
8741: GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE),
8742: GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE),
8743: GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE),
8744: GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE),
8745: GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE),
8746: GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE),
8747: GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE),
8748: GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE),
8749: GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE),
8750: GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE),
8751: GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE),
8752: GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE),
8753: GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE),
8754: GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE),
8755: GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE),
8756:
8757: GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE),
8758: GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
8759: GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
8760: GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE),
8761: GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8762: GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8763: GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8764: GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8765: GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8766: GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8767: GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8768: GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8769: GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8770: GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8771:
8772: GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE),
8773: GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
8774: GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
8775: GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE),
8776: GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8777: GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8778: GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8779: GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8780: GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8781: GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8782: GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8783: GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8784: GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8785: GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8786:
8787: GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
8788: GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8789: GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
8790: GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
8791: GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
8792: GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8793: GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8794: GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8795: GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8796: GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8797: GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8798: GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8799: GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8800: GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8801: GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8802: GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8803:
8804: #undef GEN_SPEOP_LDST
8805: #define GEN_SPEOP_LDST(name, opc2, sh) \
8806: GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
8807: GEN_SPEOP_LDST(evldd, 0x00, 3),
8808: GEN_SPEOP_LDST(evldw, 0x01, 3),
8809: GEN_SPEOP_LDST(evldh, 0x02, 3),
8810: GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
8811: GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
8812: GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
8813: GEN_SPEOP_LDST(evlwhe, 0x08, 2),
8814: GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
8815: GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
8816: GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
8817: GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
8818:
8819: GEN_SPEOP_LDST(evstdd, 0x10, 3),
8820: GEN_SPEOP_LDST(evstdw, 0x11, 3),
8821: GEN_SPEOP_LDST(evstdh, 0x12, 3),
8822: GEN_SPEOP_LDST(evstwhe, 0x18, 2),
8823: GEN_SPEOP_LDST(evstwho, 0x1A, 2),
8824: GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
8825: GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
8826: };
1.1 root 8827:
8828: #include "translate_init.c"
1.1.1.5 root 8829: #include "helper_regs.h"
1.1 root 8830:
8831: /*****************************************************************************/
8832: /* Misc PowerPC helpers */
1.1.1.5 root 8833: void cpu_dump_state (CPUState *env, FILE *f,
8834: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8835: int flags)
8836: {
1.1 root 8837: #define RGPL 4
8838: #define RFPL 4
8839:
8840: int i;
8841:
1.1.1.8 ! root 8842: cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR "
! 8843: TARGET_FMT_lx " XER %08x\n", env->nip, env->lr, env->ctr,
! 8844: env->xer);
! 8845: cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF "
! 8846: TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0],
! 8847: env->hflags, env->mmu_idx);
1.1.1.5 root 8848: #if !defined(NO_TIMER_DUMP)
8849: cpu_fprintf(f, "TB %08x %08x "
8850: #if !defined(CONFIG_USER_ONLY)
8851: "DECR %08x"
8852: #endif
8853: "\n",
8854: cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
8855: #if !defined(CONFIG_USER_ONLY)
8856: , cpu_ppc_load_decr(env)
8857: #endif
8858: );
8859: #endif
8860: for (i = 0; i < 32; i++) {
1.1 root 8861: if ((i & (RGPL - 1)) == 0)
8862: cpu_fprintf(f, "GPR%02d", i);
1.1.1.8 ! root 8863: cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
1.1 root 8864: if ((i & (RGPL - 1)) == (RGPL - 1))
8865: cpu_fprintf(f, "\n");
1.1.1.5 root 8866: }
1.1 root 8867: cpu_fprintf(f, "CR ");
1.1.1.5 root 8868: for (i = 0; i < 8; i++)
1.1 root 8869: cpu_fprintf(f, "%01x", env->crf[i]);
8870: cpu_fprintf(f, " [");
1.1.1.5 root 8871: for (i = 0; i < 8; i++) {
8872: char a = '-';
8873: if (env->crf[i] & 0x08)
8874: a = 'L';
8875: else if (env->crf[i] & 0x04)
8876: a = 'G';
8877: else if (env->crf[i] & 0x02)
8878: a = 'E';
1.1 root 8879: cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
1.1.1.5 root 8880: }
1.1.1.8 ! root 8881: cpu_fprintf(f, " ] RES " TARGET_FMT_lx "\n",
! 8882: env->reserve_addr);
1.1 root 8883: for (i = 0; i < 32; i++) {
8884: if ((i & (RFPL - 1)) == 0)
8885: cpu_fprintf(f, "FPR%02d", i);
1.1.1.3 root 8886: cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
1.1 root 8887: if ((i & (RFPL - 1)) == (RFPL - 1))
8888: cpu_fprintf(f, "\n");
8889: }
1.1.1.6 root 8890: cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
1.1.1.5 root 8891: #if !defined(CONFIG_USER_ONLY)
1.1.1.8 ! root 8892: cpu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " SDR1 "
! 8893: TARGET_FMT_lx "\n", env->spr[SPR_SRR0], env->spr[SPR_SRR1],
! 8894: env->sdr1);
1.1.1.5 root 8895: #endif
1.1 root 8896:
8897: #undef RGPL
8898: #undef RFPL
1.1.1.5 root 8899: }
8900:
8901: void cpu_dump_statistics (CPUState *env, FILE*f,
8902: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8903: int flags)
8904: {
8905: #if defined(DO_PPC_STATISTICS)
8906: opc_handler_t **t1, **t2, **t3, *handler;
8907: int op1, op2, op3;
8908:
8909: t1 = env->opcodes;
8910: for (op1 = 0; op1 < 64; op1++) {
8911: handler = t1[op1];
8912: if (is_indirect_opcode(handler)) {
8913: t2 = ind_table(handler);
8914: for (op2 = 0; op2 < 32; op2++) {
8915: handler = t2[op2];
8916: if (is_indirect_opcode(handler)) {
8917: t3 = ind_table(handler);
8918: for (op3 = 0; op3 < 32; op3++) {
8919: handler = t3[op3];
8920: if (handler->count == 0)
8921: continue;
8922: cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
8923: "%016llx %lld\n",
8924: op1, op2, op3, op1, (op3 << 5) | op2,
8925: handler->oname,
8926: handler->count, handler->count);
8927: }
8928: } else {
8929: if (handler->count == 0)
8930: continue;
8931: cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
8932: "%016llx %lld\n",
8933: op1, op2, op1, op2, handler->oname,
8934: handler->count, handler->count);
8935: }
8936: }
8937: } else {
8938: if (handler->count == 0)
8939: continue;
8940: cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
8941: op1, op1, handler->oname,
8942: handler->count, handler->count);
8943: }
8944: }
8945: #endif
1.1 root 8946: }
8947:
8948: /*****************************************************************************/
1.1.1.8 ! root 8949: static inline void gen_intermediate_code_internal(CPUState *env,
! 8950: TranslationBlock *tb,
! 8951: int search_pc)
1.1 root 8952: {
8953: DisasContext ctx, *ctxp = &ctx;
8954: opc_handler_t **table, *handler;
8955: target_ulong pc_start;
8956: uint16_t *gen_opc_end;
1.1.1.6 root 8957: CPUBreakpoint *bp;
1.1 root 8958: int j, lj = -1;
1.1.1.6 root 8959: int num_insns;
8960: int max_insns;
1.1 root 8961:
8962: pc_start = tb->pc;
8963: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8964: ctx.nip = pc_start;
8965: ctx.tb = tb;
1.1.1.5 root 8966: ctx.exception = POWERPC_EXCP_NONE;
1.1 root 8967: ctx.spr_cb = env->spr_cb;
1.1.1.6 root 8968: ctx.mem_idx = env->mmu_idx;
8969: ctx.access_type = -1;
8970: ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
1.1.1.5 root 8971: #if defined(TARGET_PPC64)
8972: ctx.sf_mode = msr_sf;
1.1 root 8973: #endif
8974: ctx.fpu_enabled = msr_fp;
1.1.1.5 root 8975: if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
8976: ctx.spe_enabled = msr_spe;
8977: else
8978: ctx.spe_enabled = 0;
8979: if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
8980: ctx.altivec_enabled = msr_vr;
8981: else
8982: ctx.altivec_enabled = 0;
8983: if ((env->flags & POWERPC_FLAG_SE) && msr_se)
1.1.1.6 root 8984: ctx.singlestep_enabled = CPU_SINGLE_STEP;
1.1.1.5 root 8985: else
1.1.1.6 root 8986: ctx.singlestep_enabled = 0;
1.1.1.5 root 8987: if ((env->flags & POWERPC_FLAG_BE) && msr_be)
1.1.1.6 root 8988: ctx.singlestep_enabled |= CPU_BRANCH_STEP;
8989: if (unlikely(env->singlestep_enabled))
8990: ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
1.1 root 8991: #if defined (DO_SINGLE_STEP) && 0
8992: /* Single step trace mode */
8993: msr_se = 1;
8994: #endif
1.1.1.6 root 8995: num_insns = 0;
8996: max_insns = tb->cflags & CF_COUNT_MASK;
8997: if (max_insns == 0)
8998: max_insns = CF_COUNT_MASK;
8999:
9000: gen_icount_start();
1.1 root 9001: /* Set env in case of segfault during code fetch */
1.1.1.5 root 9002: while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
1.1.1.8 ! root 9003: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
! 9004: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.6 root 9005: if (bp->pc == ctx.nip) {
9006: gen_debug_exception(ctxp);
1.1.1.3 root 9007: break;
9008: }
9009: }
9010: }
1.1.1.5 root 9011: if (unlikely(search_pc)) {
1.1 root 9012: j = gen_opc_ptr - gen_opc_buf;
9013: if (lj < j) {
9014: lj++;
9015: while (lj < j)
9016: gen_opc_instr_start[lj++] = 0;
9017: }
1.1.1.7 root 9018: gen_opc_pc[lj] = ctx.nip;
9019: gen_opc_instr_start[lj] = 1;
9020: gen_opc_icount[lj] = num_insns;
1.1 root 9021: }
1.1.1.6 root 9022: LOG_DISAS("----------------\n");
1.1.1.8 ! root 9023: LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
1.1.1.6 root 9024: ctx.nip, ctx.mem_idx, (int)msr_ir);
9025: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9026: gen_io_start();
9027: if (unlikely(ctx.le_mode)) {
1.1.1.5 root 9028: ctx.opcode = bswap32(ldl_code(ctx.nip));
9029: } else {
9030: ctx.opcode = ldl_code(ctx.nip);
1.1 root 9031: }
1.1.1.6 root 9032: LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
1.1 root 9033: ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
1.1.1.5 root 9034: opc3(ctx.opcode), little_endian ? "little" : "big");
1.1.1.8 ! root 9035: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
! 9036: tcg_gen_debug_insn_start(ctx.nip);
1.1 root 9037: ctx.nip += 4;
9038: table = env->opcodes;
1.1.1.6 root 9039: num_insns++;
1.1 root 9040: handler = table[opc1(ctx.opcode)];
9041: if (is_indirect_opcode(handler)) {
9042: table = ind_table(handler);
9043: handler = table[opc2(ctx.opcode)];
9044: if (is_indirect_opcode(handler)) {
9045: table = ind_table(handler);
9046: handler = table[opc3(ctx.opcode)];
9047: }
9048: }
9049: /* Is opcode *REALLY* valid ? */
1.1.1.5 root 9050: if (unlikely(handler->handler == &gen_invalid)) {
1.1.1.6 root 9051: if (qemu_log_enabled()) {
9052: qemu_log("invalid/unsupported opcode: "
1.1.1.8 ! root 9053: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
! 9054: opc1(ctx.opcode), opc2(ctx.opcode),
! 9055: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
1.1 root 9056: } else {
9057: printf("invalid/unsupported opcode: "
1.1.1.8 ! root 9058: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
1.1 root 9059: opc1(ctx.opcode), opc2(ctx.opcode),
1.1.1.5 root 9060: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
1.1 root 9061: }
1.1.1.5 root 9062: } else {
9063: if (unlikely((ctx.opcode & handler->inval) != 0)) {
1.1.1.6 root 9064: if (qemu_log_enabled()) {
9065: qemu_log("invalid bits: %08x for opcode: "
1.1.1.8 ! root 9066: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
! 9067: ctx.opcode & handler->inval, opc1(ctx.opcode),
! 9068: opc2(ctx.opcode), opc3(ctx.opcode),
! 9069: ctx.opcode, ctx.nip - 4);
1.1 root 9070: } else {
9071: printf("invalid bits: %08x for opcode: "
1.1.1.8 ! root 9072: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
1.1.1.5 root 9073: ctx.opcode & handler->inval, opc1(ctx.opcode),
9074: opc2(ctx.opcode), opc3(ctx.opcode),
1.1 root 9075: ctx.opcode, ctx.nip - 4);
1.1.1.5 root 9076: }
1.1.1.6 root 9077: gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
1.1 root 9078: break;
9079: }
9080: }
9081: (*(handler->handler))(&ctx);
1.1.1.5 root 9082: #if defined(DO_PPC_STATISTICS)
9083: handler->count++;
9084: #endif
1.1 root 9085: /* Check trace mode exceptions */
1.1.1.6 root 9086: if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
9087: (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
9088: ctx.exception != POWERPC_SYSCALL &&
9089: ctx.exception != POWERPC_EXCP_TRAP &&
9090: ctx.exception != POWERPC_EXCP_BRANCH)) {
9091: gen_exception(ctxp, POWERPC_EXCP_TRACE);
1.1.1.5 root 9092: } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
1.1.1.6 root 9093: (env->singlestep_enabled) ||
1.1.1.7 root 9094: singlestep ||
1.1.1.6 root 9095: num_insns >= max_insns)) {
1.1.1.5 root 9096: /* if we reach a page boundary or are single stepping, stop
9097: * generation
1.1 root 9098: */
9099: break;
1.1.1.5 root 9100: }
1.1 root 9101: }
1.1.1.6 root 9102: if (tb->cflags & CF_LAST_IO)
9103: gen_io_end();
1.1.1.5 root 9104: if (ctx.exception == POWERPC_EXCP_NONE) {
1.1.1.2 root 9105: gen_goto_tb(&ctx, 0, ctx.nip);
1.1.1.5 root 9106: } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
1.1.1.6 root 9107: if (unlikely(env->singlestep_enabled)) {
9108: gen_debug_exception(ctxp);
9109: }
1.1.1.5 root 9110: /* Generate the return instruction */
1.1.1.6 root 9111: tcg_gen_exit_tb(0);
1.1 root 9112: }
1.1.1.6 root 9113: gen_icount_end(tb, num_insns);
1.1 root 9114: *gen_opc_ptr = INDEX_op_end;
1.1.1.5 root 9115: if (unlikely(search_pc)) {
1.1 root 9116: j = gen_opc_ptr - gen_opc_buf;
9117: lj++;
9118: while (lj <= j)
9119: gen_opc_instr_start[lj++] = 0;
9120: } else {
9121: tb->size = ctx.nip - pc_start;
1.1.1.6 root 9122: tb->icount = num_insns;
1.1 root 9123: }
1.1.1.5 root 9124: #if defined(DEBUG_DISAS)
1.1.1.6 root 9125: qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);
9126: log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
9127: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1.1.1.5 root 9128: int flags;
9129: flags = env->bfd_mach;
1.1.1.6 root 9130: flags |= ctx.le_mode << 16;
9131: qemu_log("IN: %s\n", lookup_symbol(pc_start));
9132: log_target_disas(pc_start, ctx.nip - pc_start, flags);
9133: qemu_log("\n");
1.1 root 9134: }
9135: #endif
9136: }
9137:
1.1.1.6 root 9138: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
9139: {
9140: gen_intermediate_code_internal(env, tb, 0);
9141: }
9142:
9143: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 9144: {
1.1.1.6 root 9145: gen_intermediate_code_internal(env, tb, 1);
1.1 root 9146: }
9147:
1.1.1.6 root 9148: void gen_pc_load(CPUState *env, TranslationBlock *tb,
9149: unsigned long searched_pc, int pc_pos, void *puc)
1.1 root 9150: {
1.1.1.6 root 9151: env->nip = gen_opc_pc[pc_pos];
1.1 root 9152: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.