|
|
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.9 ! root 3401: int l1;
1.1.1.6 root 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.9 ! root 3722: static void spr_noaccess(void *opaque, int gprn, int sprn)
1.1 root 3723: {
1.1.1.9 ! root 3724: #if 0
1.1 root 3725: sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3726: printf("ERROR: try to access SPR %d !\n", sprn);
1.1.1.9 ! root 3727: #endif
1.1 root 3728: }
3729: #define SPR_NOACCESS (&spr_noaccess)
3730:
3731: /* mfspr */
1.1.1.8 root 3732: static inline void gen_op_mfspr(DisasContext *ctx)
1.1 root 3733: {
1.1.1.6 root 3734: void (*read_cb)(void *opaque, int gprn, int sprn);
1.1 root 3735: uint32_t sprn = SPR(ctx->opcode);
3736:
3737: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 root 3738: if (ctx->mem_idx == 2)
1.1.1.5 root 3739: read_cb = ctx->spr_cb[sprn].hea_read;
1.1.1.6 root 3740: else if (ctx->mem_idx)
1.1 root 3741: read_cb = ctx->spr_cb[sprn].oea_read;
3742: else
3743: #endif
3744: read_cb = ctx->spr_cb[sprn].uea_read;
1.1.1.5 root 3745: if (likely(read_cb != NULL)) {
3746: if (likely(read_cb != SPR_NOACCESS)) {
1.1.1.6 root 3747: (*read_cb)(ctx, rD(ctx->opcode), sprn);
1.1 root 3748: } else {
3749: /* Privilege exception */
1.1.1.5 root 3750: /* This is a hack to avoid warnings when running Linux:
3751: * this OS breaks the PowerPC virtualisation model,
3752: * allowing userland application to read the PVR
3753: */
3754: if (sprn != SPR_PVR) {
1.1.1.6 root 3755: qemu_log("Trying to read privileged spr %d %03x at "
1.1.1.8 root 3756: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3757: printf("Trying to read privileged spr %d %03x at "
3758: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
1.1.1.2 root 3759: }
1.1.1.6 root 3760: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3761: }
3762: } else {
3763: /* Not defined */
1.1.1.6 root 3764: qemu_log("Trying to read invalid spr %d %03x at "
1.1.1.8 root 3765: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3766: printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
1.1.1.5 root 3767: sprn, sprn, ctx->nip);
1.1.1.6 root 3768: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
1.1 root 3769: }
3770: }
3771:
1.1.1.7 root 3772: static void gen_mfspr(DisasContext *ctx)
1.1 root 3773: {
3774: gen_op_mfspr(ctx);
1.1.1.5 root 3775: }
1.1 root 3776:
3777: /* mftb */
1.1.1.7 root 3778: static void gen_mftb(DisasContext *ctx)
1.1 root 3779: {
3780: gen_op_mfspr(ctx);
3781: }
3782:
1.1.1.6 root 3783: /* mtcrf mtocrf*/
1.1.1.7 root 3784: static void gen_mtcrf(DisasContext *ctx)
1.1 root 3785: {
1.1.1.5 root 3786: uint32_t crm, crn;
3787:
3788: crm = CRM(ctx->opcode);
1.1.1.6 root 3789: if (likely((ctx->opcode & 0x00100000))) {
3790: if (crm && ((crm & (crm - 1)) == 0)) {
3791: TCGv_i32 temp = tcg_temp_new_i32();
3792: crn = ctz32 (crm);
3793: tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3794: tcg_gen_shri_i32(temp, temp, crn * 4);
3795: tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
3796: tcg_temp_free_i32(temp);
3797: }
1.1.1.5 root 3798: } else {
1.1.1.7 root 3799: TCGv_i32 temp = tcg_temp_new_i32();
3800: tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3801: for (crn = 0 ; crn < 8 ; crn++) {
3802: if (crm & (1 << crn)) {
3803: tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3804: tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3805: }
3806: }
1.1.1.6 root 3807: tcg_temp_free_i32(temp);
1.1.1.5 root 3808: }
1.1 root 3809: }
3810:
3811: /* mtmsr */
1.1.1.5 root 3812: #if defined(TARGET_PPC64)
1.1.1.7 root 3813: static void gen_mtmsrd(DisasContext *ctx)
1.1.1.5 root 3814: {
3815: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3816: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3817: #else
1.1.1.6 root 3818: if (unlikely(!ctx->mem_idx)) {
3819: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3820: return;
3821: }
3822: if (ctx->opcode & 0x00010000) {
3823: /* Special form that does not need any synchronisation */
1.1.1.6 root 3824: TCGv t0 = tcg_temp_new();
3825: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3826: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3827: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3828: tcg_temp_free(t0);
1.1.1.5 root 3829: } else {
3830: /* XXX: we need to update nip before the store
3831: * if we enter power saving mode, we will exit the loop
3832: * directly from ppc_store_msr
3833: */
3834: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3835: gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 3836: /* Must stop the translation as machine state (may have) changed */
3837: /* Note that mtmsr is not always defined as context-synchronizing */
1.1.1.6 root 3838: gen_stop_exception(ctx);
1.1.1.5 root 3839: }
3840: #endif
3841: }
3842: #endif
3843:
1.1.1.7 root 3844: static void gen_mtmsr(DisasContext *ctx)
1.1 root 3845: {
3846: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3847: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3848: #else
1.1.1.6 root 3849: if (unlikely(!ctx->mem_idx)) {
3850: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3851: return;
3852: }
1.1.1.5 root 3853: if (ctx->opcode & 0x00010000) {
3854: /* Special form that does not need any synchronisation */
1.1.1.6 root 3855: TCGv t0 = tcg_temp_new();
3856: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3857: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3858: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3859: tcg_temp_free(t0);
1.1.1.5 root 3860: } else {
3861: /* XXX: we need to update nip before the store
3862: * if we enter power saving mode, we will exit the loop
3863: * directly from ppc_store_msr
3864: */
3865: gen_update_nip(ctx, ctx->nip);
3866: #if defined(TARGET_PPC64)
1.1.1.6 root 3867: if (!ctx->sf_mode) {
3868: TCGv t0 = tcg_temp_new();
3869: TCGv t1 = tcg_temp_new();
3870: tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
3871: tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
3872: tcg_gen_or_tl(t0, t0, t1);
3873: tcg_temp_free(t1);
3874: gen_helper_store_msr(t0);
3875: tcg_temp_free(t0);
3876: } else
1.1.1.5 root 3877: #endif
1.1.1.6 root 3878: gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 3879: /* Must stop the translation as machine state (may have) changed */
1.1.1.6 root 3880: /* Note that mtmsr is not always defined as context-synchronizing */
3881: gen_stop_exception(ctx);
1.1.1.5 root 3882: }
1.1 root 3883: #endif
3884: }
3885:
3886: /* mtspr */
1.1.1.7 root 3887: static void gen_mtspr(DisasContext *ctx)
1.1 root 3888: {
1.1.1.6 root 3889: void (*write_cb)(void *opaque, int sprn, int gprn);
1.1 root 3890: uint32_t sprn = SPR(ctx->opcode);
3891:
3892: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 root 3893: if (ctx->mem_idx == 2)
1.1.1.5 root 3894: write_cb = ctx->spr_cb[sprn].hea_write;
1.1.1.6 root 3895: else if (ctx->mem_idx)
1.1 root 3896: write_cb = ctx->spr_cb[sprn].oea_write;
3897: else
3898: #endif
3899: write_cb = ctx->spr_cb[sprn].uea_write;
1.1.1.5 root 3900: if (likely(write_cb != NULL)) {
3901: if (likely(write_cb != SPR_NOACCESS)) {
1.1.1.6 root 3902: (*write_cb)(ctx, sprn, rS(ctx->opcode));
1.1 root 3903: } else {
3904: /* Privilege exception */
1.1.1.6 root 3905: qemu_log("Trying to write privileged spr %d %03x at "
1.1.1.8 root 3906: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3907: printf("Trying to write privileged spr %d %03x at " TARGET_FMT_lx
3908: "\n", sprn, sprn, ctx->nip);
1.1.1.6 root 3909: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3910: }
1.1 root 3911: } else {
3912: /* Not defined */
1.1.1.6 root 3913: qemu_log("Trying to write invalid spr %d %03x at "
1.1.1.8 root 3914: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3915: printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
1.1.1.5 root 3916: sprn, sprn, ctx->nip);
1.1.1.6 root 3917: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
1.1 root 3918: }
3919: }
3920:
3921: /*** Cache management ***/
1.1.1.7 root 3922:
1.1 root 3923: /* dcbf */
1.1.1.7 root 3924: static void gen_dcbf(DisasContext *ctx)
1.1 root 3925: {
1.1.1.5 root 3926: /* XXX: specification says this is treated as a load by the MMU */
1.1.1.6 root 3927: TCGv t0;
3928: gen_set_access_type(ctx, ACCESS_CACHE);
3929: t0 = tcg_temp_new();
3930: gen_addr_reg_index(ctx, t0);
3931: gen_qemu_ld8u(ctx, t0, t0);
3932: tcg_temp_free(t0);
1.1 root 3933: }
3934:
3935: /* dcbi (Supervisor only) */
1.1.1.7 root 3936: static void gen_dcbi(DisasContext *ctx)
1.1 root 3937: {
3938: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3939: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3940: #else
1.1.1.6 root 3941: TCGv EA, val;
3942: if (unlikely(!ctx->mem_idx)) {
3943: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3944: return;
3945: }
1.1.1.6 root 3946: EA = tcg_temp_new();
3947: gen_set_access_type(ctx, ACCESS_CACHE);
3948: gen_addr_reg_index(ctx, EA);
3949: val = tcg_temp_new();
1.1.1.5 root 3950: /* XXX: specification says this should be treated as a store by the MMU */
1.1.1.6 root 3951: gen_qemu_ld8u(ctx, val, EA);
3952: gen_qemu_st8(ctx, val, EA);
3953: tcg_temp_free(val);
3954: tcg_temp_free(EA);
1.1 root 3955: #endif
3956: }
3957:
3958: /* dcdst */
1.1.1.7 root 3959: static void gen_dcbst(DisasContext *ctx)
1.1 root 3960: {
1.1.1.5 root 3961: /* XXX: specification say this is treated as a load by the MMU */
1.1.1.6 root 3962: TCGv t0;
3963: gen_set_access_type(ctx, ACCESS_CACHE);
3964: t0 = tcg_temp_new();
3965: gen_addr_reg_index(ctx, t0);
3966: gen_qemu_ld8u(ctx, t0, t0);
3967: tcg_temp_free(t0);
1.1 root 3968: }
3969:
3970: /* dcbt */
1.1.1.7 root 3971: static void gen_dcbt(DisasContext *ctx)
1.1 root 3972: {
1.1.1.5 root 3973: /* interpreted as no-op */
3974: /* XXX: specification say this is treated as a load by the MMU
3975: * but does not generate any exception
3976: */
1.1 root 3977: }
3978:
3979: /* dcbtst */
1.1.1.7 root 3980: static void gen_dcbtst(DisasContext *ctx)
1.1 root 3981: {
1.1.1.5 root 3982: /* interpreted as no-op */
3983: /* XXX: specification say this is treated as a load by the MMU
3984: * but does not generate any exception
3985: */
1.1 root 3986: }
3987:
3988: /* dcbz */
1.1.1.7 root 3989: static void gen_dcbz(DisasContext *ctx)
1.1.1.6 root 3990: {
3991: TCGv t0;
3992: gen_set_access_type(ctx, ACCESS_CACHE);
3993: /* NIP cannot be restored if the memory exception comes from an helper */
3994: gen_update_nip(ctx, ctx->nip - 4);
3995: t0 = tcg_temp_new();
3996: gen_addr_reg_index(ctx, t0);
3997: gen_helper_dcbz(t0);
3998: tcg_temp_free(t0);
3999: }
1.1 root 4000:
1.1.1.7 root 4001: static void gen_dcbz_970(DisasContext *ctx)
1.1 root 4002: {
1.1.1.6 root 4003: TCGv t0;
4004: gen_set_access_type(ctx, ACCESS_CACHE);
4005: /* NIP cannot be restored if the memory exception comes from an helper */
4006: gen_update_nip(ctx, ctx->nip - 4);
4007: t0 = tcg_temp_new();
4008: gen_addr_reg_index(ctx, t0);
4009: if (ctx->opcode & 0x00200000)
4010: gen_helper_dcbz(t0);
4011: else
4012: gen_helper_dcbz_970(t0);
4013: tcg_temp_free(t0);
4014: }
1.1.1.5 root 4015:
1.1.1.6 root 4016: /* dst / dstt */
1.1.1.7 root 4017: static void gen_dst(DisasContext *ctx)
1.1.1.6 root 4018: {
4019: if (rA(ctx->opcode) == 0) {
4020: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4021: } else {
4022: /* interpreted as no-op */
1.1 root 4023: }
1.1.1.5 root 4024: }
4025:
1.1.1.6 root 4026: /* dstst /dststt */
1.1.1.7 root 4027: static void gen_dstst(DisasContext *ctx)
1.1.1.5 root 4028: {
1.1.1.6 root 4029: if (rA(ctx->opcode) == 0) {
4030: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4031: } else {
4032: /* interpreted as no-op */
4033: }
4034:
1.1.1.5 root 4035: }
4036:
1.1.1.6 root 4037: /* dss / dssall */
1.1.1.7 root 4038: static void gen_dss(DisasContext *ctx)
1.1.1.5 root 4039: {
1.1.1.6 root 4040: /* interpreted as no-op */
1.1 root 4041: }
4042:
4043: /* icbi */
1.1.1.7 root 4044: static void gen_icbi(DisasContext *ctx)
1.1 root 4045: {
1.1.1.6 root 4046: TCGv t0;
4047: gen_set_access_type(ctx, ACCESS_CACHE);
1.1.1.5 root 4048: /* NIP cannot be restored if the memory exception comes from an helper */
4049: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 4050: t0 = tcg_temp_new();
4051: gen_addr_reg_index(ctx, t0);
4052: gen_helper_icbi(t0);
4053: tcg_temp_free(t0);
1.1 root 4054: }
4055:
4056: /* Optional: */
4057: /* dcba */
1.1.1.7 root 4058: static void gen_dcba(DisasContext *ctx)
1.1 root 4059: {
1.1.1.5 root 4060: /* interpreted as no-op */
4061: /* XXX: specification say this is treated as a store by the MMU
4062: * but does not generate any exception
4063: */
1.1 root 4064: }
4065:
4066: /*** Segment register manipulation ***/
4067: /* Supervisor only: */
1.1.1.7 root 4068:
1.1 root 4069: /* mfsr */
1.1.1.7 root 4070: static void gen_mfsr(DisasContext *ctx)
1.1 root 4071: {
4072: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4073: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4074: #else
1.1.1.6 root 4075: TCGv t0;
4076: if (unlikely(!ctx->mem_idx)) {
4077: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4078: return;
4079: }
1.1.1.6 root 4080: t0 = tcg_const_tl(SR(ctx->opcode));
4081: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4082: tcg_temp_free(t0);
1.1 root 4083: #endif
4084: }
4085:
4086: /* mfsrin */
1.1.1.7 root 4087: static void gen_mfsrin(DisasContext *ctx)
1.1 root 4088: {
4089: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4090: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4091: #else
1.1.1.6 root 4092: TCGv t0;
4093: if (unlikely(!ctx->mem_idx)) {
4094: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4095: return;
4096: }
1.1.1.6 root 4097: t0 = tcg_temp_new();
4098: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4099: tcg_gen_andi_tl(t0, t0, 0xF);
4100: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4101: tcg_temp_free(t0);
1.1 root 4102: #endif
4103: }
4104:
4105: /* mtsr */
1.1.1.7 root 4106: static void gen_mtsr(DisasContext *ctx)
1.1 root 4107: {
4108: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4109: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4110: #else
1.1.1.6 root 4111: TCGv t0;
4112: if (unlikely(!ctx->mem_idx)) {
4113: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4114: return;
4115: }
1.1.1.6 root 4116: t0 = tcg_const_tl(SR(ctx->opcode));
4117: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4118: tcg_temp_free(t0);
1.1 root 4119: #endif
4120: }
4121:
4122: /* mtsrin */
1.1.1.7 root 4123: static void gen_mtsrin(DisasContext *ctx)
1.1 root 4124: {
4125: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4126: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4127: #else
1.1.1.6 root 4128: TCGv t0;
4129: if (unlikely(!ctx->mem_idx)) {
4130: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4131: return;
4132: }
1.1.1.6 root 4133: t0 = tcg_temp_new();
4134: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4135: tcg_gen_andi_tl(t0, t0, 0xF);
4136: gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4137: tcg_temp_free(t0);
1.1 root 4138: #endif
4139: }
4140:
1.1.1.5 root 4141: #if defined(TARGET_PPC64)
4142: /* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
1.1.1.7 root 4143:
1.1.1.5 root 4144: /* mfsr */
1.1.1.7 root 4145: static void gen_mfsr_64b(DisasContext *ctx)
1.1 root 4146: {
4147: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4148: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4149: #else
1.1.1.6 root 4150: TCGv t0;
4151: if (unlikely(!ctx->mem_idx)) {
4152: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4153: return;
4154: }
1.1.1.6 root 4155: t0 = tcg_const_tl(SR(ctx->opcode));
1.1.1.7 root 4156: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.6 root 4157: tcg_temp_free(t0);
1.1.1.5 root 4158: #endif
4159: }
4160:
4161: /* mfsrin */
1.1.1.7 root 4162: static void gen_mfsrin_64b(DisasContext *ctx)
1.1.1.5 root 4163: {
4164: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4165: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4166: #else
1.1.1.6 root 4167: TCGv t0;
4168: if (unlikely(!ctx->mem_idx)) {
4169: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4170: return;
4171: }
1.1.1.6 root 4172: t0 = tcg_temp_new();
4173: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4174: tcg_gen_andi_tl(t0, t0, 0xF);
1.1.1.7 root 4175: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.6 root 4176: tcg_temp_free(t0);
1.1.1.5 root 4177: #endif
4178: }
4179:
4180: /* mtsr */
1.1.1.7 root 4181: static void gen_mtsr_64b(DisasContext *ctx)
1.1.1.5 root 4182: {
4183: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4184: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4185: #else
1.1.1.6 root 4186: TCGv t0;
4187: if (unlikely(!ctx->mem_idx)) {
4188: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4189: return;
4190: }
1.1.1.6 root 4191: t0 = tcg_const_tl(SR(ctx->opcode));
1.1.1.7 root 4192: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
1.1.1.6 root 4193: tcg_temp_free(t0);
1.1.1.5 root 4194: #endif
4195: }
4196:
4197: /* mtsrin */
1.1.1.7 root 4198: static void gen_mtsrin_64b(DisasContext *ctx)
1.1.1.5 root 4199: {
4200: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4201: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4202: #else
1.1.1.6 root 4203: TCGv t0;
4204: if (unlikely(!ctx->mem_idx)) {
4205: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4206: return;
4207: }
1.1.1.6 root 4208: t0 = tcg_temp_new();
4209: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4210: tcg_gen_andi_tl(t0, t0, 0xF);
1.1.1.7 root 4211: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
1.1.1.6 root 4212: tcg_temp_free(t0);
1.1.1.5 root 4213: #endif
4214: }
1.1.1.7 root 4215:
4216: /* slbmte */
4217: static void gen_slbmte(DisasContext *ctx)
4218: {
4219: #if defined(CONFIG_USER_ONLY)
4220: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4221: #else
4222: if (unlikely(!ctx->mem_idx)) {
4223: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4224: return;
4225: }
4226: gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
4227: #endif
4228: }
4229:
1.1.1.5 root 4230: #endif /* defined(TARGET_PPC64) */
4231:
4232: /*** Lookaside buffer management ***/
1.1.1.6 root 4233: /* Optional & mem_idx only: */
1.1.1.7 root 4234:
1.1.1.5 root 4235: /* tlbia */
1.1.1.7 root 4236: static void gen_tlbia(DisasContext *ctx)
1.1.1.5 root 4237: {
4238: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4239: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4240: #else
1.1.1.6 root 4241: if (unlikely(!ctx->mem_idx)) {
4242: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4243: return;
4244: }
1.1.1.6 root 4245: gen_helper_tlbia();
1.1 root 4246: #endif
4247: }
4248:
1.1.1.7 root 4249: /* tlbiel */
4250: static void gen_tlbiel(DisasContext *ctx)
4251: {
4252: #if defined(CONFIG_USER_ONLY)
4253: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4254: #else
4255: if (unlikely(!ctx->mem_idx)) {
4256: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4257: return;
4258: }
4259: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4260: #endif
4261: }
4262:
1.1 root 4263: /* tlbie */
1.1.1.7 root 4264: static void gen_tlbie(DisasContext *ctx)
1.1.1.5 root 4265: {
4266: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4267: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4268: #else
1.1.1.6 root 4269: if (unlikely(!ctx->mem_idx)) {
4270: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4271: return;
4272: }
4273: #if defined(TARGET_PPC64)
1.1.1.6 root 4274: if (!ctx->sf_mode) {
4275: TCGv t0 = tcg_temp_new();
4276: tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4277: gen_helper_tlbie(t0);
4278: tcg_temp_free(t0);
4279: } else
1.1.1.5 root 4280: #endif
1.1.1.6 root 4281: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4282: #endif
4283: }
4284:
4285: /* tlbsync */
1.1.1.7 root 4286: static void gen_tlbsync(DisasContext *ctx)
1.1.1.5 root 4287: {
4288: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4289: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4290: #else
1.1.1.6 root 4291: if (unlikely(!ctx->mem_idx)) {
4292: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4293: return;
4294: }
4295: /* This has no effect: it should ensure that all previous
4296: * tlbie have completed
4297: */
1.1.1.6 root 4298: gen_stop_exception(ctx);
1.1.1.5 root 4299: #endif
4300: }
4301:
4302: #if defined(TARGET_PPC64)
4303: /* slbia */
1.1.1.7 root 4304: static void gen_slbia(DisasContext *ctx)
1.1.1.5 root 4305: {
4306: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4307: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4308: #else
1.1.1.6 root 4309: if (unlikely(!ctx->mem_idx)) {
4310: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4311: return;
4312: }
1.1.1.6 root 4313: gen_helper_slbia();
1.1.1.5 root 4314: #endif
4315: }
4316:
4317: /* slbie */
1.1.1.7 root 4318: static void gen_slbie(DisasContext *ctx)
1.1.1.5 root 4319: {
4320: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4321: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4322: #else
1.1.1.6 root 4323: if (unlikely(!ctx->mem_idx)) {
4324: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4325: return;
4326: }
1.1.1.6 root 4327: gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4328: #endif
4329: }
4330: #endif
4331:
4332: /*** External control ***/
4333: /* Optional: */
1.1.1.7 root 4334:
1.1.1.5 root 4335: /* eciwx */
1.1.1.7 root 4336: static void gen_eciwx(DisasContext *ctx)
1.1.1.5 root 4337: {
1.1.1.6 root 4338: TCGv t0;
4339: /* Should check EAR[E] ! */
4340: gen_set_access_type(ctx, ACCESS_EXT);
4341: t0 = tcg_temp_new();
4342: gen_addr_reg_index(ctx, t0);
4343: gen_check_align(ctx, t0, 0x03);
4344: gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4345: tcg_temp_free(t0);
1.1.1.5 root 4346: }
4347:
4348: /* ecowx */
1.1.1.7 root 4349: static void gen_ecowx(DisasContext *ctx)
1.1.1.5 root 4350: {
1.1.1.6 root 4351: TCGv t0;
4352: /* Should check EAR[E] ! */
4353: gen_set_access_type(ctx, ACCESS_EXT);
4354: t0 = tcg_temp_new();
4355: gen_addr_reg_index(ctx, t0);
4356: gen_check_align(ctx, t0, 0x03);
4357: gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4358: tcg_temp_free(t0);
1.1.1.5 root 4359: }
4360:
4361: /* PowerPC 601 specific instructions */
1.1.1.7 root 4362:
1.1.1.5 root 4363: /* abs - abs. */
1.1.1.7 root 4364: static void gen_abs(DisasContext *ctx)
1.1.1.5 root 4365: {
1.1.1.6 root 4366: int l1 = gen_new_label();
4367: int l2 = gen_new_label();
4368: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4369: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4370: tcg_gen_br(l2);
4371: gen_set_label(l1);
4372: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4373: gen_set_label(l2);
1.1.1.5 root 4374: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4375: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4376: }
4377:
4378: /* abso - abso. */
1.1.1.7 root 4379: static void gen_abso(DisasContext *ctx)
1.1.1.5 root 4380: {
1.1.1.6 root 4381: int l1 = gen_new_label();
4382: int l2 = gen_new_label();
4383: int l3 = gen_new_label();
4384: /* Start with XER OV disabled, the most likely case */
4385: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4386: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4387: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4388: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4389: tcg_gen_br(l2);
4390: gen_set_label(l1);
4391: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4392: tcg_gen_br(l3);
4393: gen_set_label(l2);
4394: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4395: gen_set_label(l3);
1.1.1.5 root 4396: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4397: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4398: }
4399:
4400: /* clcs */
1.1.1.7 root 4401: static void gen_clcs(DisasContext *ctx)
1.1.1.5 root 4402: {
1.1.1.6 root 4403: TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4404: gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4405: tcg_temp_free_i32(t0);
1.1.1.5 root 4406: /* Rc=1 sets CR0 to an undefined state */
4407: }
4408:
4409: /* div - div. */
1.1.1.7 root 4410: static void gen_div(DisasContext *ctx)
1.1.1.5 root 4411: {
1.1.1.6 root 4412: gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4413: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4414: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4415: }
4416:
4417: /* divo - divo. */
1.1.1.7 root 4418: static void gen_divo(DisasContext *ctx)
1.1.1.5 root 4419: {
1.1.1.6 root 4420: gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4421: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4422: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4423: }
4424:
4425: /* divs - divs. */
1.1.1.7 root 4426: static void gen_divs(DisasContext *ctx)
1.1.1.5 root 4427: {
1.1.1.6 root 4428: gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4429: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4430: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4431: }
4432:
4433: /* divso - divso. */
1.1.1.7 root 4434: static void gen_divso(DisasContext *ctx)
1.1.1.5 root 4435: {
1.1.1.6 root 4436: gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4437: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4438: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4439: }
4440:
4441: /* doz - doz. */
1.1.1.7 root 4442: static void gen_doz(DisasContext *ctx)
1.1.1.5 root 4443: {
1.1.1.6 root 4444: int l1 = gen_new_label();
4445: int l2 = gen_new_label();
4446: tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4447: tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4448: tcg_gen_br(l2);
4449: gen_set_label(l1);
4450: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4451: gen_set_label(l2);
1.1.1.5 root 4452: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4453: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4454: }
4455:
4456: /* dozo - dozo. */
1.1.1.7 root 4457: static void gen_dozo(DisasContext *ctx)
1.1.1.5 root 4458: {
1.1.1.6 root 4459: int l1 = gen_new_label();
4460: int l2 = gen_new_label();
4461: TCGv t0 = tcg_temp_new();
4462: TCGv t1 = tcg_temp_new();
4463: TCGv t2 = tcg_temp_new();
4464: /* Start with XER OV disabled, the most likely case */
4465: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4466: tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4467: tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4468: tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4469: tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4470: tcg_gen_andc_tl(t1, t1, t2);
4471: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4472: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4473: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4474: tcg_gen_br(l2);
4475: gen_set_label(l1);
4476: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4477: gen_set_label(l2);
4478: tcg_temp_free(t0);
4479: tcg_temp_free(t1);
4480: tcg_temp_free(t2);
1.1.1.5 root 4481: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4482: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4483: }
4484:
4485: /* dozi */
1.1.1.7 root 4486: static void gen_dozi(DisasContext *ctx)
1.1.1.5 root 4487: {
1.1.1.6 root 4488: target_long simm = SIMM(ctx->opcode);
4489: int l1 = gen_new_label();
4490: int l2 = gen_new_label();
4491: tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4492: tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4493: tcg_gen_br(l2);
4494: gen_set_label(l1);
4495: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4496: gen_set_label(l2);
4497: if (unlikely(Rc(ctx->opcode) != 0))
4498: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4499: }
4500:
4501: /* lscbx - lscbx. */
1.1.1.7 root 4502: static void gen_lscbx(DisasContext *ctx)
1.1.1.5 root 4503: {
1.1.1.6 root 4504: TCGv t0 = tcg_temp_new();
4505: TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4506: TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4507: TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
1.1.1.5 root 4508:
1.1.1.6 root 4509: gen_addr_reg_index(ctx, t0);
1.1.1.5 root 4510: /* NIP cannot be restored if the memory exception comes from an helper */
4511: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 4512: gen_helper_lscbx(t0, t0, t1, t2, t3);
4513: tcg_temp_free_i32(t1);
4514: tcg_temp_free_i32(t2);
4515: tcg_temp_free_i32(t3);
4516: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4517: tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
1.1.1.5 root 4518: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4519: gen_set_Rc0(ctx, t0);
4520: tcg_temp_free(t0);
1.1.1.5 root 4521: }
4522:
4523: /* maskg - maskg. */
1.1.1.7 root 4524: static void gen_maskg(DisasContext *ctx)
1.1.1.5 root 4525: {
1.1.1.6 root 4526: int l1 = gen_new_label();
4527: TCGv t0 = tcg_temp_new();
4528: TCGv t1 = tcg_temp_new();
4529: TCGv t2 = tcg_temp_new();
4530: TCGv t3 = tcg_temp_new();
4531: tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4532: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4533: tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4534: tcg_gen_addi_tl(t2, t0, 1);
4535: tcg_gen_shr_tl(t2, t3, t2);
4536: tcg_gen_shr_tl(t3, t3, t1);
4537: tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4538: tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4539: tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4540: gen_set_label(l1);
4541: tcg_temp_free(t0);
4542: tcg_temp_free(t1);
4543: tcg_temp_free(t2);
4544: tcg_temp_free(t3);
1.1.1.5 root 4545: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4546: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4547: }
4548:
4549: /* maskir - maskir. */
1.1.1.7 root 4550: static void gen_maskir(DisasContext *ctx)
1.1.1.5 root 4551: {
1.1.1.6 root 4552: TCGv t0 = tcg_temp_new();
4553: TCGv t1 = tcg_temp_new();
4554: tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4555: tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4556: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4557: tcg_temp_free(t0);
4558: tcg_temp_free(t1);
1.1.1.5 root 4559: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4560: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4561: }
4562:
4563: /* mul - mul. */
1.1.1.7 root 4564: static void gen_mul(DisasContext *ctx)
1.1.1.5 root 4565: {
1.1.1.6 root 4566: TCGv_i64 t0 = tcg_temp_new_i64();
4567: TCGv_i64 t1 = tcg_temp_new_i64();
4568: TCGv t2 = tcg_temp_new();
4569: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4570: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4571: tcg_gen_mul_i64(t0, t0, t1);
4572: tcg_gen_trunc_i64_tl(t2, t0);
4573: gen_store_spr(SPR_MQ, t2);
4574: tcg_gen_shri_i64(t1, t0, 32);
4575: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4576: tcg_temp_free_i64(t0);
4577: tcg_temp_free_i64(t1);
4578: tcg_temp_free(t2);
1.1.1.5 root 4579: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4580: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4581: }
4582:
4583: /* mulo - mulo. */
1.1.1.7 root 4584: static void gen_mulo(DisasContext *ctx)
1.1.1.5 root 4585: {
1.1.1.6 root 4586: int l1 = gen_new_label();
4587: TCGv_i64 t0 = tcg_temp_new_i64();
4588: TCGv_i64 t1 = tcg_temp_new_i64();
4589: TCGv t2 = tcg_temp_new();
4590: /* Start with XER OV disabled, the most likely case */
4591: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4592: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4593: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4594: tcg_gen_mul_i64(t0, t0, t1);
4595: tcg_gen_trunc_i64_tl(t2, t0);
4596: gen_store_spr(SPR_MQ, t2);
4597: tcg_gen_shri_i64(t1, t0, 32);
4598: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4599: tcg_gen_ext32s_i64(t1, t0);
4600: tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4601: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4602: gen_set_label(l1);
4603: tcg_temp_free_i64(t0);
4604: tcg_temp_free_i64(t1);
4605: tcg_temp_free(t2);
1.1.1.5 root 4606: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4607: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4608: }
4609:
4610: /* nabs - nabs. */
1.1.1.7 root 4611: static void gen_nabs(DisasContext *ctx)
1.1.1.5 root 4612: {
1.1.1.6 root 4613: int l1 = gen_new_label();
4614: int l2 = gen_new_label();
4615: tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4616: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4617: tcg_gen_br(l2);
4618: gen_set_label(l1);
4619: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4620: gen_set_label(l2);
1.1.1.5 root 4621: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4622: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4623: }
4624:
4625: /* nabso - nabso. */
1.1.1.7 root 4626: static void gen_nabso(DisasContext *ctx)
1.1.1.5 root 4627: {
1.1.1.6 root 4628: int l1 = gen_new_label();
4629: int l2 = gen_new_label();
4630: tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4631: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4632: tcg_gen_br(l2);
4633: gen_set_label(l1);
4634: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4635: gen_set_label(l2);
4636: /* nabs never overflows */
4637: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1.1.1.5 root 4638: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4639: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4640: }
4641:
4642: /* rlmi - rlmi. */
1.1.1.7 root 4643: static void gen_rlmi(DisasContext *ctx)
1.1.1.5 root 4644: {
1.1.1.6 root 4645: uint32_t mb = MB(ctx->opcode);
4646: uint32_t me = ME(ctx->opcode);
4647: TCGv t0 = tcg_temp_new();
4648: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4649: tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4650: tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4651: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4652: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4653: tcg_temp_free(t0);
1.1.1.5 root 4654: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4655: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4656: }
4657:
4658: /* rrib - rrib. */
1.1.1.7 root 4659: static void gen_rrib(DisasContext *ctx)
1.1.1.5 root 4660: {
1.1.1.6 root 4661: TCGv t0 = tcg_temp_new();
4662: TCGv t1 = tcg_temp_new();
4663: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4664: tcg_gen_movi_tl(t1, 0x80000000);
4665: tcg_gen_shr_tl(t1, t1, t0);
4666: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4667: tcg_gen_and_tl(t0, t0, t1);
4668: tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4669: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4670: tcg_temp_free(t0);
4671: tcg_temp_free(t1);
1.1.1.5 root 4672: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4673: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4674: }
4675:
4676: /* sle - sle. */
1.1.1.7 root 4677: static void gen_sle(DisasContext *ctx)
1.1.1.5 root 4678: {
1.1.1.6 root 4679: TCGv t0 = tcg_temp_new();
4680: TCGv t1 = tcg_temp_new();
4681: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4682: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4683: tcg_gen_subfi_tl(t1, 32, t1);
4684: tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4685: tcg_gen_or_tl(t1, t0, t1);
4686: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4687: gen_store_spr(SPR_MQ, t1);
4688: tcg_temp_free(t0);
4689: tcg_temp_free(t1);
1.1.1.5 root 4690: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4691: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4692: }
4693:
4694: /* sleq - sleq. */
1.1.1.7 root 4695: static void gen_sleq(DisasContext *ctx)
1.1.1.5 root 4696: {
1.1.1.6 root 4697: TCGv t0 = tcg_temp_new();
4698: TCGv t1 = tcg_temp_new();
4699: TCGv t2 = tcg_temp_new();
4700: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4701: tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4702: tcg_gen_shl_tl(t2, t2, t0);
4703: tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4704: gen_load_spr(t1, SPR_MQ);
4705: gen_store_spr(SPR_MQ, t0);
4706: tcg_gen_and_tl(t0, t0, t2);
4707: tcg_gen_andc_tl(t1, t1, t2);
4708: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4709: tcg_temp_free(t0);
4710: tcg_temp_free(t1);
4711: tcg_temp_free(t2);
1.1.1.5 root 4712: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4713: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4714: }
4715:
4716: /* sliq - sliq. */
1.1.1.7 root 4717: static void gen_sliq(DisasContext *ctx)
1.1.1.5 root 4718: {
1.1.1.6 root 4719: int sh = SH(ctx->opcode);
4720: TCGv t0 = tcg_temp_new();
4721: TCGv t1 = tcg_temp_new();
4722: tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4723: tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4724: tcg_gen_or_tl(t1, t0, t1);
4725: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4726: gen_store_spr(SPR_MQ, t1);
4727: tcg_temp_free(t0);
4728: tcg_temp_free(t1);
1.1.1.5 root 4729: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4730: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4731: }
4732:
4733: /* slliq - slliq. */
1.1.1.7 root 4734: static void gen_slliq(DisasContext *ctx)
1.1.1.5 root 4735: {
1.1.1.6 root 4736: int sh = SH(ctx->opcode);
4737: TCGv t0 = tcg_temp_new();
4738: TCGv t1 = tcg_temp_new();
4739: tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4740: gen_load_spr(t1, SPR_MQ);
4741: gen_store_spr(SPR_MQ, t0);
4742: tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
4743: tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4744: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4745: tcg_temp_free(t0);
4746: tcg_temp_free(t1);
1.1.1.5 root 4747: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4748: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4749: }
4750:
4751: /* sllq - sllq. */
1.1.1.7 root 4752: static void gen_sllq(DisasContext *ctx)
1.1.1.5 root 4753: {
1.1.1.6 root 4754: int l1 = gen_new_label();
4755: int l2 = gen_new_label();
4756: TCGv t0 = tcg_temp_local_new();
4757: TCGv t1 = tcg_temp_local_new();
4758: TCGv t2 = tcg_temp_local_new();
4759: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4760: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4761: tcg_gen_shl_tl(t1, t1, t2);
4762: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4763: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4764: gen_load_spr(t0, SPR_MQ);
4765: tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4766: tcg_gen_br(l2);
4767: gen_set_label(l1);
4768: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4769: gen_load_spr(t2, SPR_MQ);
4770: tcg_gen_andc_tl(t1, t2, t1);
4771: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4772: gen_set_label(l2);
4773: tcg_temp_free(t0);
4774: tcg_temp_free(t1);
4775: tcg_temp_free(t2);
1.1.1.5 root 4776: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4777: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4778: }
4779:
4780: /* slq - slq. */
1.1.1.7 root 4781: static void gen_slq(DisasContext *ctx)
1.1.1.5 root 4782: {
1.1.1.6 root 4783: int l1 = gen_new_label();
4784: TCGv t0 = tcg_temp_new();
4785: TCGv t1 = tcg_temp_new();
4786: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4787: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4788: tcg_gen_subfi_tl(t1, 32, t1);
4789: tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4790: tcg_gen_or_tl(t1, t0, t1);
4791: gen_store_spr(SPR_MQ, t1);
4792: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4793: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4794: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4795: tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4796: gen_set_label(l1);
4797: tcg_temp_free(t0);
4798: tcg_temp_free(t1);
1.1.1.5 root 4799: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4800: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4801: }
4802:
4803: /* sraiq - sraiq. */
1.1.1.7 root 4804: static void gen_sraiq(DisasContext *ctx)
1.1.1.5 root 4805: {
1.1.1.6 root 4806: int sh = SH(ctx->opcode);
4807: int l1 = gen_new_label();
4808: TCGv t0 = tcg_temp_new();
4809: TCGv t1 = tcg_temp_new();
4810: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4811: tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4812: tcg_gen_or_tl(t0, t0, t1);
4813: gen_store_spr(SPR_MQ, t0);
4814: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4815: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4816: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4817: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4818: gen_set_label(l1);
4819: tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4820: tcg_temp_free(t0);
4821: tcg_temp_free(t1);
1.1.1.5 root 4822: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4823: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4824: }
4825:
4826: /* sraq - sraq. */
1.1.1.7 root 4827: static void gen_sraq(DisasContext *ctx)
1.1.1.5 root 4828: {
1.1.1.6 root 4829: int l1 = gen_new_label();
4830: int l2 = gen_new_label();
4831: TCGv t0 = tcg_temp_new();
4832: TCGv t1 = tcg_temp_local_new();
4833: TCGv t2 = tcg_temp_local_new();
4834: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4835: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4836: tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4837: tcg_gen_subfi_tl(t2, 32, t2);
4838: tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4839: tcg_gen_or_tl(t0, t0, t2);
4840: gen_store_spr(SPR_MQ, t0);
4841: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4842: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4843: tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4844: tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4845: gen_set_label(l1);
4846: tcg_temp_free(t0);
4847: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4848: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4849: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4850: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4851: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4852: gen_set_label(l2);
4853: tcg_temp_free(t1);
4854: tcg_temp_free(t2);
1.1.1.5 root 4855: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4856: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4857: }
4858:
4859: /* sre - sre. */
1.1.1.7 root 4860: static void gen_sre(DisasContext *ctx)
1.1.1.5 root 4861: {
1.1.1.6 root 4862: TCGv t0 = tcg_temp_new();
4863: TCGv t1 = tcg_temp_new();
4864: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4865: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4866: tcg_gen_subfi_tl(t1, 32, t1);
4867: tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4868: tcg_gen_or_tl(t1, t0, t1);
4869: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4870: gen_store_spr(SPR_MQ, t1);
4871: tcg_temp_free(t0);
4872: tcg_temp_free(t1);
1.1.1.5 root 4873: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4874: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4875: }
4876:
4877: /* srea - srea. */
1.1.1.7 root 4878: static void gen_srea(DisasContext *ctx)
1.1.1.5 root 4879: {
1.1.1.6 root 4880: TCGv t0 = tcg_temp_new();
4881: TCGv t1 = tcg_temp_new();
4882: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4883: tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4884: gen_store_spr(SPR_MQ, t0);
4885: tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4886: tcg_temp_free(t0);
4887: tcg_temp_free(t1);
1.1.1.5 root 4888: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4889: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4890: }
4891:
4892: /* sreq */
1.1.1.7 root 4893: static void gen_sreq(DisasContext *ctx)
1.1.1.5 root 4894: {
1.1.1.6 root 4895: TCGv t0 = tcg_temp_new();
4896: TCGv t1 = tcg_temp_new();
4897: TCGv t2 = tcg_temp_new();
4898: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4899: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4900: tcg_gen_shr_tl(t1, t1, t0);
4901: tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4902: gen_load_spr(t2, SPR_MQ);
4903: gen_store_spr(SPR_MQ, t0);
4904: tcg_gen_and_tl(t0, t0, t1);
4905: tcg_gen_andc_tl(t2, t2, t1);
4906: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4907: tcg_temp_free(t0);
4908: tcg_temp_free(t1);
4909: tcg_temp_free(t2);
1.1.1.5 root 4910: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4911: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4912: }
4913:
4914: /* sriq */
1.1.1.7 root 4915: static void gen_sriq(DisasContext *ctx)
1.1.1.5 root 4916: {
1.1.1.6 root 4917: int sh = SH(ctx->opcode);
4918: TCGv t0 = tcg_temp_new();
4919: TCGv t1 = tcg_temp_new();
4920: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4921: tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4922: tcg_gen_or_tl(t1, t0, t1);
4923: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4924: gen_store_spr(SPR_MQ, t1);
4925: tcg_temp_free(t0);
4926: tcg_temp_free(t1);
1.1.1.5 root 4927: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4928: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4929: }
4930:
4931: /* srliq */
1.1.1.7 root 4932: static void gen_srliq(DisasContext *ctx)
1.1.1.5 root 4933: {
1.1.1.6 root 4934: int sh = SH(ctx->opcode);
4935: TCGv t0 = tcg_temp_new();
4936: TCGv t1 = tcg_temp_new();
4937: tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4938: gen_load_spr(t1, SPR_MQ);
4939: gen_store_spr(SPR_MQ, t0);
4940: tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
4941: tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
4942: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4943: tcg_temp_free(t0);
4944: tcg_temp_free(t1);
1.1.1.5 root 4945: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4946: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4947: }
4948:
4949: /* srlq */
1.1.1.7 root 4950: static void gen_srlq(DisasContext *ctx)
1.1.1.5 root 4951: {
1.1.1.6 root 4952: int l1 = gen_new_label();
4953: int l2 = gen_new_label();
4954: TCGv t0 = tcg_temp_local_new();
4955: TCGv t1 = tcg_temp_local_new();
4956: TCGv t2 = tcg_temp_local_new();
4957: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4958: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4959: tcg_gen_shr_tl(t2, t1, t2);
4960: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4961: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4962: gen_load_spr(t0, SPR_MQ);
4963: tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4964: tcg_gen_br(l2);
4965: gen_set_label(l1);
4966: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4967: tcg_gen_and_tl(t0, t0, t2);
4968: gen_load_spr(t1, SPR_MQ);
4969: tcg_gen_andc_tl(t1, t1, t2);
4970: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4971: gen_set_label(l2);
4972: tcg_temp_free(t0);
4973: tcg_temp_free(t1);
4974: tcg_temp_free(t2);
1.1.1.5 root 4975: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4976: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4977: }
4978:
4979: /* srq */
1.1.1.7 root 4980: static void gen_srq(DisasContext *ctx)
1.1.1.5 root 4981: {
1.1.1.6 root 4982: int l1 = gen_new_label();
4983: TCGv t0 = tcg_temp_new();
4984: TCGv t1 = tcg_temp_new();
4985: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4986: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4987: tcg_gen_subfi_tl(t1, 32, t1);
4988: tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4989: tcg_gen_or_tl(t1, t0, t1);
4990: gen_store_spr(SPR_MQ, t1);
4991: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4992: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4993: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4994: tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4995: gen_set_label(l1);
4996: tcg_temp_free(t0);
4997: tcg_temp_free(t1);
1.1.1.5 root 4998: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4999: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5000: }
5001:
5002: /* PowerPC 602 specific instructions */
1.1.1.7 root 5003:
1.1.1.5 root 5004: /* dsa */
1.1.1.7 root 5005: static void gen_dsa(DisasContext *ctx)
1.1.1.5 root 5006: {
5007: /* XXX: TODO */
1.1.1.6 root 5008: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5009: }
5010:
5011: /* esa */
1.1.1.7 root 5012: static void gen_esa(DisasContext *ctx)
1.1.1.5 root 5013: {
5014: /* XXX: TODO */
1.1.1.6 root 5015: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5016: }
5017:
5018: /* mfrom */
1.1.1.7 root 5019: static void gen_mfrom(DisasContext *ctx)
1.1.1.5 root 5020: {
5021: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5022: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5023: #else
1.1.1.6 root 5024: if (unlikely(!ctx->mem_idx)) {
5025: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5026: return;
5027: }
1.1.1.6 root 5028: gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5029: #endif
5030: }
5031:
5032: /* 602 - 603 - G2 TLB management */
1.1.1.7 root 5033:
1.1.1.5 root 5034: /* tlbld */
1.1.1.7 root 5035: static void gen_tlbld_6xx(DisasContext *ctx)
1.1.1.5 root 5036: {
5037: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5038: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5039: #else
1.1.1.6 root 5040: if (unlikely(!ctx->mem_idx)) {
5041: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5042: return;
5043: }
1.1.1.6 root 5044: gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5045: #endif
5046: }
5047:
5048: /* tlbli */
1.1.1.7 root 5049: static void gen_tlbli_6xx(DisasContext *ctx)
1.1.1.5 root 5050: {
5051: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5052: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5053: #else
1.1.1.6 root 5054: if (unlikely(!ctx->mem_idx)) {
5055: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5056: return;
5057: }
1.1.1.6 root 5058: gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5059: #endif
5060: }
5061:
5062: /* 74xx TLB management */
1.1.1.7 root 5063:
1.1.1.5 root 5064: /* tlbld */
1.1.1.7 root 5065: static void gen_tlbld_74xx(DisasContext *ctx)
1.1.1.5 root 5066: {
5067: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5068: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5069: #else
1.1.1.6 root 5070: if (unlikely(!ctx->mem_idx)) {
5071: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5072: return;
5073: }
1.1.1.6 root 5074: gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5075: #endif
5076: }
5077:
5078: /* tlbli */
1.1.1.7 root 5079: static void gen_tlbli_74xx(DisasContext *ctx)
1.1.1.5 root 5080: {
5081: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5082: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5083: #else
1.1.1.6 root 5084: if (unlikely(!ctx->mem_idx)) {
5085: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5086: return;
5087: }
1.1.1.6 root 5088: gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5089: #endif
5090: }
5091:
5092: /* POWER instructions not in PowerPC 601 */
1.1.1.7 root 5093:
1.1.1.5 root 5094: /* clf */
1.1.1.7 root 5095: static void gen_clf(DisasContext *ctx)
1.1.1.5 root 5096: {
5097: /* Cache line flush: implemented as no-op */
5098: }
5099:
5100: /* cli */
1.1.1.7 root 5101: static void gen_cli(DisasContext *ctx)
1.1.1.5 root 5102: {
5103: /* Cache line invalidate: privileged and treated as no-op */
5104: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5105: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5106: #else
1.1.1.6 root 5107: if (unlikely(!ctx->mem_idx)) {
5108: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5109: return;
5110: }
5111: #endif
5112: }
5113:
5114: /* dclst */
1.1.1.7 root 5115: static void gen_dclst(DisasContext *ctx)
1.1.1.5 root 5116: {
5117: /* Data cache line store: treated as no-op */
5118: }
5119:
1.1.1.7 root 5120: static void gen_mfsri(DisasContext *ctx)
1.1.1.5 root 5121: {
5122: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5123: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5124: #else
5125: int ra = rA(ctx->opcode);
5126: int rd = rD(ctx->opcode);
1.1.1.6 root 5127: TCGv t0;
5128: if (unlikely(!ctx->mem_idx)) {
5129: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5130: return;
5131: }
5132: t0 = tcg_temp_new();
5133: gen_addr_reg_index(ctx, t0);
5134: tcg_gen_shri_tl(t0, t0, 28);
5135: tcg_gen_andi_tl(t0, t0, 0xF);
5136: gen_helper_load_sr(cpu_gpr[rd], t0);
5137: tcg_temp_free(t0);
1.1.1.5 root 5138: if (ra != 0 && ra != rd)
1.1.1.6 root 5139: tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
1.1.1.5 root 5140: #endif
5141: }
5142:
1.1.1.7 root 5143: static void gen_rac(DisasContext *ctx)
1.1.1.5 root 5144: {
5145: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5146: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5147: #else
1.1.1.6 root 5148: TCGv t0;
5149: if (unlikely(!ctx->mem_idx)) {
5150: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5151: return;
5152: }
1.1.1.6 root 5153: t0 = tcg_temp_new();
5154: gen_addr_reg_index(ctx, t0);
5155: gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5156: tcg_temp_free(t0);
1.1.1.5 root 5157: #endif
5158: }
5159:
1.1.1.7 root 5160: static void gen_rfsvc(DisasContext *ctx)
1.1.1.5 root 5161: {
5162: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5163: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5164: #else
1.1.1.6 root 5165: if (unlikely(!ctx->mem_idx)) {
5166: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5167: return;
5168: }
1.1.1.6 root 5169: gen_helper_rfsvc();
5170: gen_sync_exception(ctx);
1.1.1.5 root 5171: #endif
5172: }
5173:
5174: /* svc is not implemented for now */
5175:
5176: /* POWER2 specific instructions */
5177: /* Quad manipulation (load/store two floats at a time) */
5178:
5179: /* lfq */
1.1.1.7 root 5180: static void gen_lfq(DisasContext *ctx)
1.1.1.5 root 5181: {
1.1.1.6 root 5182: int rd = rD(ctx->opcode);
5183: TCGv t0;
5184: gen_set_access_type(ctx, ACCESS_FLOAT);
5185: t0 = tcg_temp_new();
5186: gen_addr_imm_index(ctx, t0, 0);
5187: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5188: gen_addr_add(ctx, t0, t0, 8);
5189: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5190: tcg_temp_free(t0);
1.1.1.5 root 5191: }
5192:
5193: /* lfqu */
1.1.1.7 root 5194: static void gen_lfqu(DisasContext *ctx)
1.1.1.5 root 5195: {
5196: int ra = rA(ctx->opcode);
1.1.1.6 root 5197: int rd = rD(ctx->opcode);
5198: TCGv t0, t1;
5199: gen_set_access_type(ctx, ACCESS_FLOAT);
5200: t0 = tcg_temp_new();
5201: t1 = tcg_temp_new();
5202: gen_addr_imm_index(ctx, t0, 0);
5203: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5204: gen_addr_add(ctx, t1, t0, 8);
5205: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
1.1.1.5 root 5206: if (ra != 0)
1.1.1.6 root 5207: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5208: tcg_temp_free(t0);
5209: tcg_temp_free(t1);
1.1.1.5 root 5210: }
5211:
5212: /* lfqux */
1.1.1.7 root 5213: static void gen_lfqux(DisasContext *ctx)
1.1.1.5 root 5214: {
5215: int ra = rA(ctx->opcode);
1.1.1.6 root 5216: int rd = rD(ctx->opcode);
5217: gen_set_access_type(ctx, ACCESS_FLOAT);
5218: TCGv t0, t1;
5219: t0 = tcg_temp_new();
5220: gen_addr_reg_index(ctx, t0);
5221: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5222: t1 = tcg_temp_new();
5223: gen_addr_add(ctx, t1, t0, 8);
5224: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5225: tcg_temp_free(t1);
1.1.1.5 root 5226: if (ra != 0)
1.1.1.6 root 5227: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5228: tcg_temp_free(t0);
1.1.1.5 root 5229: }
5230:
5231: /* lfqx */
1.1.1.7 root 5232: static void gen_lfqx(DisasContext *ctx)
1.1.1.5 root 5233: {
1.1.1.6 root 5234: int rd = rD(ctx->opcode);
5235: TCGv t0;
5236: gen_set_access_type(ctx, ACCESS_FLOAT);
5237: t0 = tcg_temp_new();
5238: gen_addr_reg_index(ctx, t0);
5239: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5240: gen_addr_add(ctx, t0, t0, 8);
5241: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5242: tcg_temp_free(t0);
1.1.1.5 root 5243: }
5244:
5245: /* stfq */
1.1.1.7 root 5246: static void gen_stfq(DisasContext *ctx)
1.1.1.5 root 5247: {
1.1.1.6 root 5248: int rd = rD(ctx->opcode);
5249: TCGv t0;
5250: gen_set_access_type(ctx, ACCESS_FLOAT);
5251: t0 = tcg_temp_new();
5252: gen_addr_imm_index(ctx, t0, 0);
5253: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5254: gen_addr_add(ctx, t0, t0, 8);
5255: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5256: tcg_temp_free(t0);
1.1.1.5 root 5257: }
5258:
5259: /* stfqu */
1.1.1.7 root 5260: static void gen_stfqu(DisasContext *ctx)
1.1.1.5 root 5261: {
5262: int ra = rA(ctx->opcode);
1.1.1.6 root 5263: int rd = rD(ctx->opcode);
5264: TCGv t0, t1;
5265: gen_set_access_type(ctx, ACCESS_FLOAT);
5266: t0 = tcg_temp_new();
5267: gen_addr_imm_index(ctx, t0, 0);
5268: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5269: t1 = tcg_temp_new();
5270: gen_addr_add(ctx, t1, t0, 8);
5271: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5272: tcg_temp_free(t1);
1.1.1.5 root 5273: if (ra != 0)
1.1.1.6 root 5274: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5275: tcg_temp_free(t0);
1.1.1.5 root 5276: }
5277:
5278: /* stfqux */
1.1.1.7 root 5279: static void gen_stfqux(DisasContext *ctx)
1.1.1.5 root 5280: {
5281: int ra = rA(ctx->opcode);
1.1.1.6 root 5282: int rd = rD(ctx->opcode);
5283: TCGv t0, t1;
5284: gen_set_access_type(ctx, ACCESS_FLOAT);
5285: t0 = tcg_temp_new();
5286: gen_addr_reg_index(ctx, t0);
5287: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5288: t1 = tcg_temp_new();
5289: gen_addr_add(ctx, t1, t0, 8);
5290: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5291: tcg_temp_free(t1);
1.1.1.5 root 5292: if (ra != 0)
1.1.1.6 root 5293: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5294: tcg_temp_free(t0);
1.1.1.5 root 5295: }
5296:
5297: /* stfqx */
1.1.1.7 root 5298: static void gen_stfqx(DisasContext *ctx)
1.1.1.5 root 5299: {
1.1.1.6 root 5300: int rd = rD(ctx->opcode);
5301: TCGv t0;
5302: gen_set_access_type(ctx, ACCESS_FLOAT);
5303: t0 = tcg_temp_new();
5304: gen_addr_reg_index(ctx, t0);
5305: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5306: gen_addr_add(ctx, t0, t0, 8);
5307: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5308: tcg_temp_free(t0);
1.1.1.5 root 5309: }
5310:
5311: /* BookE specific instructions */
1.1.1.7 root 5312:
1.1.1.5 root 5313: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5314: static void gen_mfapidi(DisasContext *ctx)
1.1.1.5 root 5315: {
5316: /* XXX: TODO */
1.1.1.6 root 5317: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5318: }
5319:
5320: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5321: static void gen_tlbiva(DisasContext *ctx)
1.1.1.5 root 5322: {
5323: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5324: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5325: #else
1.1.1.6 root 5326: TCGv t0;
5327: if (unlikely(!ctx->mem_idx)) {
5328: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5329: return;
5330: }
1.1.1.6 root 5331: t0 = tcg_temp_new();
5332: gen_addr_reg_index(ctx, t0);
5333: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
5334: tcg_temp_free(t0);
1.1.1.5 root 5335: #endif
5336: }
5337:
5338: /* All 405 MAC instructions are translated here */
1.1.1.8 root 5339: static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
5340: int ra, int rb, int rt, int Rc)
1.1.1.5 root 5341: {
1.1.1.6 root 5342: TCGv t0, t1;
5343:
5344: t0 = tcg_temp_local_new();
5345: t1 = tcg_temp_local_new();
5346:
1.1.1.5 root 5347: switch (opc3 & 0x0D) {
5348: case 0x05:
5349: /* macchw - macchw. - macchwo - macchwo. */
5350: /* macchws - macchws. - macchwso - macchwso. */
5351: /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5352: /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5353: /* mulchw - mulchw. */
1.1.1.6 root 5354: tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5355: tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5356: tcg_gen_ext16s_tl(t1, t1);
1.1.1.5 root 5357: break;
5358: case 0x04:
5359: /* macchwu - macchwu. - macchwuo - macchwuo. */
5360: /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5361: /* mulchwu - mulchwu. */
1.1.1.6 root 5362: tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5363: tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5364: tcg_gen_ext16u_tl(t1, t1);
1.1.1.5 root 5365: break;
5366: case 0x01:
5367: /* machhw - machhw. - machhwo - machhwo. */
5368: /* machhws - machhws. - machhwso - machhwso. */
5369: /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5370: /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5371: /* mulhhw - mulhhw. */
1.1.1.6 root 5372: tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5373: tcg_gen_ext16s_tl(t0, t0);
5374: tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5375: tcg_gen_ext16s_tl(t1, t1);
1.1.1.5 root 5376: break;
5377: case 0x00:
5378: /* machhwu - machhwu. - machhwuo - machhwuo. */
5379: /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5380: /* mulhhwu - mulhhwu. */
1.1.1.6 root 5381: tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5382: tcg_gen_ext16u_tl(t0, t0);
5383: tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5384: tcg_gen_ext16u_tl(t1, t1);
1.1.1.5 root 5385: break;
5386: case 0x0D:
5387: /* maclhw - maclhw. - maclhwo - maclhwo. */
5388: /* maclhws - maclhws. - maclhwso - maclhwso. */
5389: /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5390: /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5391: /* mullhw - mullhw. */
1.1.1.6 root 5392: tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5393: tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
1.1.1.5 root 5394: break;
5395: case 0x0C:
5396: /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5397: /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5398: /* mullhwu - mullhwu. */
1.1.1.6 root 5399: tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5400: tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
1.1.1.5 root 5401: break;
5402: }
5403: if (opc2 & 0x04) {
1.1.1.6 root 5404: /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5405: tcg_gen_mul_tl(t1, t0, t1);
5406: if (opc2 & 0x02) {
5407: /* nmultiply-and-accumulate (0x0E) */
5408: tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5409: } else {
5410: /* multiply-and-accumulate (0x0C) */
5411: tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5412: }
5413:
5414: if (opc3 & 0x12) {
5415: /* Check overflow and/or saturate */
5416: int l1 = gen_new_label();
5417:
5418: if (opc3 & 0x10) {
5419: /* Start with XER OV disabled, the most likely case */
5420: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5421: }
5422: if (opc3 & 0x01) {
5423: /* Signed */
5424: tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5425: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5426: tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5427: tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
5428: if (opc3 & 0x02) {
5429: /* Saturate */
5430: tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5431: tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5432: }
5433: } else {
5434: /* Unsigned */
5435: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5436: if (opc3 & 0x02) {
5437: /* Saturate */
5438: tcg_gen_movi_tl(t0, UINT32_MAX);
5439: }
5440: }
5441: if (opc3 & 0x10) {
5442: /* Check overflow */
5443: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5444: }
5445: gen_set_label(l1);
5446: tcg_gen_mov_tl(cpu_gpr[rt], t0);
5447: }
5448: } else {
5449: tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
1.1.1.5 root 5450: }
1.1.1.6 root 5451: tcg_temp_free(t0);
5452: tcg_temp_free(t1);
1.1.1.5 root 5453: if (unlikely(Rc) != 0) {
5454: /* Update Rc0 */
1.1.1.6 root 5455: gen_set_Rc0(ctx, cpu_gpr[rt]);
1.1.1.5 root 5456: }
5457: }
5458:
5459: #define GEN_MAC_HANDLER(name, opc2, opc3) \
1.1.1.7 root 5460: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.5 root 5461: { \
5462: gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5463: rD(ctx->opcode), Rc(ctx->opcode)); \
5464: }
5465:
5466: /* macchw - macchw. */
5467: GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5468: /* macchwo - macchwo. */
5469: GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5470: /* macchws - macchws. */
5471: GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5472: /* macchwso - macchwso. */
5473: GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5474: /* macchwsu - macchwsu. */
5475: GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5476: /* macchwsuo - macchwsuo. */
5477: GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5478: /* macchwu - macchwu. */
5479: GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5480: /* macchwuo - macchwuo. */
5481: GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5482: /* machhw - machhw. */
5483: GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5484: /* machhwo - machhwo. */
5485: GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5486: /* machhws - machhws. */
5487: GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5488: /* machhwso - machhwso. */
5489: GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5490: /* machhwsu - machhwsu. */
5491: GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5492: /* machhwsuo - machhwsuo. */
5493: GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5494: /* machhwu - machhwu. */
5495: GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5496: /* machhwuo - machhwuo. */
5497: GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5498: /* maclhw - maclhw. */
5499: GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5500: /* maclhwo - maclhwo. */
5501: GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5502: /* maclhws - maclhws. */
5503: GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5504: /* maclhwso - maclhwso. */
5505: GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5506: /* maclhwu - maclhwu. */
5507: GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5508: /* maclhwuo - maclhwuo. */
5509: GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5510: /* maclhwsu - maclhwsu. */
5511: GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5512: /* maclhwsuo - maclhwsuo. */
5513: GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5514: /* nmacchw - nmacchw. */
5515: GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5516: /* nmacchwo - nmacchwo. */
5517: GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5518: /* nmacchws - nmacchws. */
5519: GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5520: /* nmacchwso - nmacchwso. */
5521: GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5522: /* nmachhw - nmachhw. */
5523: GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5524: /* nmachhwo - nmachhwo. */
5525: GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5526: /* nmachhws - nmachhws. */
5527: GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5528: /* nmachhwso - nmachhwso. */
5529: GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5530: /* nmaclhw - nmaclhw. */
5531: GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5532: /* nmaclhwo - nmaclhwo. */
5533: GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5534: /* nmaclhws - nmaclhws. */
5535: GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5536: /* nmaclhwso - nmaclhwso. */
5537: GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5538:
5539: /* mulchw - mulchw. */
5540: GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5541: /* mulchwu - mulchwu. */
5542: GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5543: /* mulhhw - mulhhw. */
5544: GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5545: /* mulhhwu - mulhhwu. */
5546: GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5547: /* mullhw - mullhw. */
5548: GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5549: /* mullhwu - mullhwu. */
5550: GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5551:
5552: /* mfdcr */
1.1.1.7 root 5553: static void gen_mfdcr(DisasContext *ctx)
1.1.1.5 root 5554: {
5555: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5556: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5557: #else
1.1.1.6 root 5558: TCGv dcrn;
5559: if (unlikely(!ctx->mem_idx)) {
5560: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5561: return;
5562: }
1.1.1.6 root 5563: /* NIP cannot be restored if the memory exception comes from an helper */
5564: gen_update_nip(ctx, ctx->nip - 4);
5565: dcrn = tcg_const_tl(SPR(ctx->opcode));
5566: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5567: tcg_temp_free(dcrn);
1.1.1.5 root 5568: #endif
5569: }
5570:
5571: /* mtdcr */
1.1.1.7 root 5572: static void gen_mtdcr(DisasContext *ctx)
1.1.1.5 root 5573: {
5574: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5575: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5576: #else
1.1.1.6 root 5577: TCGv dcrn;
5578: if (unlikely(!ctx->mem_idx)) {
5579: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5580: return;
5581: }
1.1.1.6 root 5582: /* NIP cannot be restored if the memory exception comes from an helper */
5583: gen_update_nip(ctx, ctx->nip - 4);
5584: dcrn = tcg_const_tl(SPR(ctx->opcode));
5585: gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5586: tcg_temp_free(dcrn);
1.1.1.5 root 5587: #endif
5588: }
5589:
5590: /* mfdcrx */
5591: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5592: static void gen_mfdcrx(DisasContext *ctx)
1.1.1.5 root 5593: {
5594: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5595: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5596: #else
1.1.1.6 root 5597: if (unlikely(!ctx->mem_idx)) {
5598: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5599: return;
5600: }
1.1.1.6 root 5601: /* NIP cannot be restored if the memory exception comes from an helper */
5602: gen_update_nip(ctx, ctx->nip - 4);
5603: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5604: /* Note: Rc update flag set leads to undefined state of Rc0 */
5605: #endif
5606: }
5607:
5608: /* mtdcrx */
5609: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5610: static void gen_mtdcrx(DisasContext *ctx)
1.1.1.5 root 5611: {
5612: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5613: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5614: #else
1.1.1.6 root 5615: if (unlikely(!ctx->mem_idx)) {
5616: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5617: return;
5618: }
1.1.1.6 root 5619: /* NIP cannot be restored if the memory exception comes from an helper */
5620: gen_update_nip(ctx, ctx->nip - 4);
5621: gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5622: /* Note: Rc update flag set leads to undefined state of Rc0 */
5623: #endif
5624: }
5625:
5626: /* mfdcrux (PPC 460) : user-mode access to DCR */
1.1.1.7 root 5627: static void gen_mfdcrux(DisasContext *ctx)
1.1.1.5 root 5628: {
1.1.1.6 root 5629: /* NIP cannot be restored if the memory exception comes from an helper */
5630: gen_update_nip(ctx, ctx->nip - 4);
5631: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5632: /* Note: Rc update flag set leads to undefined state of Rc0 */
5633: }
5634:
5635: /* mtdcrux (PPC 460) : user-mode access to DCR */
1.1.1.7 root 5636: static void gen_mtdcrux(DisasContext *ctx)
1.1.1.5 root 5637: {
1.1.1.6 root 5638: /* NIP cannot be restored if the memory exception comes from an helper */
5639: gen_update_nip(ctx, ctx->nip - 4);
5640: gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5641: /* Note: Rc update flag set leads to undefined state of Rc0 */
5642: }
5643:
5644: /* dccci */
1.1.1.7 root 5645: static void gen_dccci(DisasContext *ctx)
1.1.1.5 root 5646: {
5647: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5648: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5649: #else
1.1.1.6 root 5650: if (unlikely(!ctx->mem_idx)) {
5651: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5652: return;
5653: }
5654: /* interpreted as no-op */
5655: #endif
5656: }
5657:
5658: /* dcread */
1.1.1.7 root 5659: static void gen_dcread(DisasContext *ctx)
1.1.1.5 root 5660: {
5661: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5662: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5663: #else
1.1.1.6 root 5664: TCGv EA, val;
5665: if (unlikely(!ctx->mem_idx)) {
5666: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5667: return;
5668: }
1.1.1.6 root 5669: gen_set_access_type(ctx, ACCESS_CACHE);
5670: EA = tcg_temp_new();
5671: gen_addr_reg_index(ctx, EA);
5672: val = tcg_temp_new();
5673: gen_qemu_ld32u(ctx, val, EA);
5674: tcg_temp_free(val);
5675: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5676: tcg_temp_free(EA);
1.1.1.5 root 5677: #endif
5678: }
5679:
5680: /* icbt */
1.1.1.7 root 5681: static void gen_icbt_40x(DisasContext *ctx)
1.1.1.5 root 5682: {
5683: /* interpreted as no-op */
5684: /* XXX: specification say this is treated as a load by the MMU
5685: * but does not generate any exception
5686: */
5687: }
5688:
5689: /* iccci */
1.1.1.7 root 5690: static void gen_iccci(DisasContext *ctx)
1.1.1.5 root 5691: {
5692: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5693: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5694: #else
1.1.1.6 root 5695: if (unlikely(!ctx->mem_idx)) {
5696: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5697: return;
5698: }
5699: /* interpreted as no-op */
5700: #endif
5701: }
5702:
5703: /* icread */
1.1.1.7 root 5704: static void gen_icread(DisasContext *ctx)
1.1.1.5 root 5705: {
5706: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5707: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5708: #else
1.1.1.6 root 5709: if (unlikely(!ctx->mem_idx)) {
5710: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5711: return;
5712: }
5713: /* interpreted as no-op */
5714: #endif
5715: }
5716:
1.1.1.6 root 5717: /* rfci (mem_idx only) */
1.1.1.7 root 5718: static void gen_rfci_40x(DisasContext *ctx)
1.1.1.5 root 5719: {
5720: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5721: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5722: #else
1.1.1.6 root 5723: if (unlikely(!ctx->mem_idx)) {
5724: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5725: return;
5726: }
5727: /* Restore CPU state */
1.1.1.6 root 5728: gen_helper_40x_rfci();
5729: gen_sync_exception(ctx);
1.1.1.5 root 5730: #endif
5731: }
5732:
1.1.1.7 root 5733: static void gen_rfci(DisasContext *ctx)
1.1.1.5 root 5734: {
5735: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5736: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5737: #else
1.1.1.6 root 5738: if (unlikely(!ctx->mem_idx)) {
5739: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5740: return;
5741: }
5742: /* Restore CPU state */
1.1.1.6 root 5743: gen_helper_rfci();
5744: gen_sync_exception(ctx);
1.1.1.5 root 5745: #endif
5746: }
5747:
5748: /* BookE specific */
1.1.1.7 root 5749:
1.1.1.5 root 5750: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5751: static void gen_rfdi(DisasContext *ctx)
1.1.1.5 root 5752: {
5753: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5754: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5755: #else
1.1.1.6 root 5756: if (unlikely(!ctx->mem_idx)) {
5757: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5758: return;
5759: }
5760: /* Restore CPU state */
1.1.1.6 root 5761: gen_helper_rfdi();
5762: gen_sync_exception(ctx);
1.1.1.5 root 5763: #endif
5764: }
5765:
5766: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5767: static void gen_rfmci(DisasContext *ctx)
1.1.1.5 root 5768: {
5769: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5770: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5771: #else
1.1.1.6 root 5772: if (unlikely(!ctx->mem_idx)) {
5773: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5774: return;
5775: }
5776: /* Restore CPU state */
1.1.1.6 root 5777: gen_helper_rfmci();
5778: gen_sync_exception(ctx);
1.1.1.5 root 5779: #endif
5780: }
5781:
5782: /* TLB management - PowerPC 405 implementation */
1.1.1.7 root 5783:
1.1.1.5 root 5784: /* tlbre */
1.1.1.7 root 5785: static void gen_tlbre_40x(DisasContext *ctx)
1.1.1.5 root 5786: {
5787: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5788: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5789: #else
1.1.1.6 root 5790: if (unlikely(!ctx->mem_idx)) {
5791: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5792: return;
5793: }
5794: switch (rB(ctx->opcode)) {
5795: case 0:
1.1.1.6 root 5796: gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5797: break;
5798: case 1:
1.1.1.6 root 5799: gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5800: break;
5801: default:
1.1.1.6 root 5802: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5803: break;
5804: }
5805: #endif
5806: }
5807:
5808: /* tlbsx - tlbsx. */
1.1.1.7 root 5809: static void gen_tlbsx_40x(DisasContext *ctx)
1.1.1.5 root 5810: {
5811: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5812: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5813: #else
1.1.1.6 root 5814: TCGv t0;
5815: if (unlikely(!ctx->mem_idx)) {
5816: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5817: return;
5818: }
1.1.1.6 root 5819: t0 = tcg_temp_new();
5820: gen_addr_reg_index(ctx, t0);
5821: gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5822: tcg_temp_free(t0);
5823: if (Rc(ctx->opcode)) {
5824: int l1 = gen_new_label();
5825: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5826: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5827: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5828: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5829: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5830: gen_set_label(l1);
5831: }
1.1.1.5 root 5832: #endif
5833: }
5834:
5835: /* tlbwe */
1.1.1.7 root 5836: static void gen_tlbwe_40x(DisasContext *ctx)
1.1.1.5 root 5837: {
5838: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5839: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5840: #else
1.1.1.6 root 5841: if (unlikely(!ctx->mem_idx)) {
5842: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5843: return;
5844: }
5845: switch (rB(ctx->opcode)) {
5846: case 0:
1.1.1.6 root 5847: gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5848: break;
5849: case 1:
1.1.1.6 root 5850: gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5851: break;
5852: default:
1.1.1.6 root 5853: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5854: break;
5855: }
5856: #endif
5857: }
5858:
5859: /* TLB management - PowerPC 440 implementation */
1.1.1.7 root 5860:
1.1.1.5 root 5861: /* tlbre */
1.1.1.7 root 5862: static void gen_tlbre_440(DisasContext *ctx)
1.1.1.5 root 5863: {
5864: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5865: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5866: #else
1.1.1.6 root 5867: if (unlikely(!ctx->mem_idx)) {
5868: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5869: return;
5870: }
5871: switch (rB(ctx->opcode)) {
5872: case 0:
5873: case 1:
5874: case 2:
1.1.1.6 root 5875: {
5876: TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5877: gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5878: tcg_temp_free_i32(t0);
5879: }
1.1.1.5 root 5880: break;
5881: default:
1.1.1.6 root 5882: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5883: break;
5884: }
5885: #endif
5886: }
5887:
5888: /* tlbsx - tlbsx. */
1.1.1.7 root 5889: static void gen_tlbsx_440(DisasContext *ctx)
1.1 root 5890: {
5891: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5892: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5893: #else
1.1.1.6 root 5894: TCGv t0;
5895: if (unlikely(!ctx->mem_idx)) {
5896: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5897: return;
5898: }
1.1.1.6 root 5899: t0 = tcg_temp_new();
5900: gen_addr_reg_index(ctx, t0);
5901: gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5902: tcg_temp_free(t0);
5903: if (Rc(ctx->opcode)) {
5904: int l1 = gen_new_label();
5905: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5906: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5907: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5908: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5909: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5910: gen_set_label(l1);
5911: }
1.1 root 5912: #endif
5913: }
5914:
1.1.1.5 root 5915: /* tlbwe */
1.1.1.7 root 5916: static void gen_tlbwe_440(DisasContext *ctx)
1.1 root 5917: {
5918: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5919: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5920: #else
1.1.1.6 root 5921: if (unlikely(!ctx->mem_idx)) {
5922: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 5923: return;
5924: }
1.1.1.5 root 5925: switch (rB(ctx->opcode)) {
5926: case 0:
5927: case 1:
5928: case 2:
1.1.1.6 root 5929: {
5930: TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5931: gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5932: tcg_temp_free_i32(t0);
5933: }
1.1.1.5 root 5934: break;
5935: default:
1.1.1.6 root 5936: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5937: break;
5938: }
5939: #endif
5940: }
5941:
5942: /* wrtee */
1.1.1.7 root 5943: static void gen_wrtee(DisasContext *ctx)
1.1.1.5 root 5944: {
5945: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5946: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5947: #else
1.1.1.6 root 5948: TCGv t0;
5949: if (unlikely(!ctx->mem_idx)) {
5950: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5951: return;
5952: }
1.1.1.6 root 5953: t0 = tcg_temp_new();
5954: tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
5955: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
5956: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
5957: tcg_temp_free(t0);
1.1.1.5 root 5958: /* Stop translation to have a chance to raise an exception
5959: * if we just set msr_ee to 1
1.1 root 5960: */
1.1.1.6 root 5961: gen_stop_exception(ctx);
1.1 root 5962: #endif
5963: }
5964:
1.1.1.5 root 5965: /* wrteei */
1.1.1.7 root 5966: static void gen_wrteei(DisasContext *ctx)
1.1.1.5 root 5967: {
1.1 root 5968: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5969: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5970: #else
1.1.1.6 root 5971: if (unlikely(!ctx->mem_idx)) {
5972: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5973: return;
5974: }
1.1.1.7 root 5975: if (ctx->opcode & 0x00008000) {
1.1.1.6 root 5976: tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
5977: /* Stop translation to have a chance to raise an exception */
5978: gen_stop_exception(ctx);
5979: } else {
5980: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
5981: }
1.1.1.5 root 5982: #endif
5983: }
5984:
5985: /* PowerPC 440 specific instructions */
1.1.1.7 root 5986:
1.1.1.5 root 5987: /* dlmzb */
1.1.1.7 root 5988: static void gen_dlmzb(DisasContext *ctx)
1.1.1.5 root 5989: {
1.1.1.6 root 5990: TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
5991: gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
5992: cpu_gpr[rB(ctx->opcode)], t0);
5993: tcg_temp_free_i32(t0);
1.1.1.5 root 5994: }
5995:
5996: /* mbar replaces eieio on 440 */
1.1.1.7 root 5997: static void gen_mbar(DisasContext *ctx)
1.1.1.5 root 5998: {
5999: /* interpreted as no-op */
6000: }
6001:
6002: /* msync replaces sync on 440 */
1.1.1.7 root 6003: static void gen_msync(DisasContext *ctx)
1.1.1.5 root 6004: {
6005: /* interpreted as no-op */
6006: }
6007:
6008: /* icbt */
1.1.1.7 root 6009: static void gen_icbt_440(DisasContext *ctx)
1.1.1.5 root 6010: {
6011: /* interpreted as no-op */
6012: /* XXX: specification say this is treated as a load by the MMU
6013: * but does not generate any exception
6014: */
6015: }
6016:
6017: /*** Altivec vector extension ***/
6018: /* Altivec registers moves */
6019:
1.1.1.8 root 6020: static inline TCGv_ptr gen_avr_ptr(int reg)
1.1.1.6 root 6021: {
6022: TCGv_ptr r = tcg_temp_new_ptr();
6023: tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6024: return r;
6025: }
1.1.1.5 root 6026:
6027: #define GEN_VR_LDX(name, opc2, opc3) \
1.1.1.7 root 6028: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.5 root 6029: { \
1.1.1.6 root 6030: TCGv EA; \
1.1.1.5 root 6031: if (unlikely(!ctx->altivec_enabled)) { \
1.1.1.6 root 6032: gen_exception(ctx, POWERPC_EXCP_VPU); \
1.1.1.5 root 6033: return; \
6034: } \
1.1.1.6 root 6035: gen_set_access_type(ctx, ACCESS_INT); \
6036: EA = tcg_temp_new(); \
6037: gen_addr_reg_index(ctx, EA); \
6038: tcg_gen_andi_tl(EA, EA, ~0xf); \
6039: if (ctx->le_mode) { \
6040: gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6041: tcg_gen_addi_tl(EA, EA, 8); \
6042: gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6043: } else { \
6044: gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6045: tcg_gen_addi_tl(EA, EA, 8); \
6046: gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6047: } \
6048: tcg_temp_free(EA); \
1.1.1.5 root 6049: }
6050:
6051: #define GEN_VR_STX(name, opc2, opc3) \
1.1.1.7 root 6052: static void gen_st##name(DisasContext *ctx) \
1.1.1.5 root 6053: { \
1.1.1.6 root 6054: TCGv EA; \
1.1.1.5 root 6055: if (unlikely(!ctx->altivec_enabled)) { \
1.1.1.6 root 6056: gen_exception(ctx, POWERPC_EXCP_VPU); \
1.1.1.5 root 6057: return; \
6058: } \
1.1.1.6 root 6059: gen_set_access_type(ctx, ACCESS_INT); \
6060: EA = tcg_temp_new(); \
6061: gen_addr_reg_index(ctx, EA); \
6062: tcg_gen_andi_tl(EA, EA, ~0xf); \
6063: if (ctx->le_mode) { \
6064: gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6065: tcg_gen_addi_tl(EA, EA, 8); \
6066: gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6067: } else { \
6068: gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6069: tcg_gen_addi_tl(EA, EA, 8); \
6070: gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6071: } \
6072: tcg_temp_free(EA); \
1.1.1.5 root 6073: }
6074:
1.1.1.6 root 6075: #define GEN_VR_LVE(name, opc2, opc3) \
1.1.1.7 root 6076: static void gen_lve##name(DisasContext *ctx) \
1.1.1.6 root 6077: { \
6078: TCGv EA; \
6079: TCGv_ptr rs; \
6080: if (unlikely(!ctx->altivec_enabled)) { \
6081: gen_exception(ctx, POWERPC_EXCP_VPU); \
6082: return; \
6083: } \
6084: gen_set_access_type(ctx, ACCESS_INT); \
6085: EA = tcg_temp_new(); \
6086: gen_addr_reg_index(ctx, EA); \
6087: rs = gen_avr_ptr(rS(ctx->opcode)); \
6088: gen_helper_lve##name (rs, EA); \
6089: tcg_temp_free(EA); \
6090: tcg_temp_free_ptr(rs); \
6091: }
6092:
6093: #define GEN_VR_STVE(name, opc2, opc3) \
1.1.1.7 root 6094: static void gen_stve##name(DisasContext *ctx) \
1.1.1.6 root 6095: { \
6096: TCGv EA; \
6097: TCGv_ptr rs; \
6098: if (unlikely(!ctx->altivec_enabled)) { \
6099: gen_exception(ctx, POWERPC_EXCP_VPU); \
6100: return; \
6101: } \
6102: gen_set_access_type(ctx, ACCESS_INT); \
6103: EA = tcg_temp_new(); \
6104: gen_addr_reg_index(ctx, EA); \
6105: rs = gen_avr_ptr(rS(ctx->opcode)); \
6106: gen_helper_stve##name (rs, EA); \
6107: tcg_temp_free(EA); \
6108: tcg_temp_free_ptr(rs); \
6109: }
6110:
6111: GEN_VR_LDX(lvx, 0x07, 0x03);
1.1.1.5 root 6112: /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
1.1.1.6 root 6113: GEN_VR_LDX(lvxl, 0x07, 0x0B);
1.1.1.5 root 6114:
1.1.1.6 root 6115: GEN_VR_LVE(bx, 0x07, 0x00);
6116: GEN_VR_LVE(hx, 0x07, 0x01);
6117: GEN_VR_LVE(wx, 0x07, 0x02);
6118:
6119: GEN_VR_STX(svx, 0x07, 0x07);
1.1.1.5 root 6120: /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
1.1.1.6 root 6121: GEN_VR_STX(svxl, 0x07, 0x0F);
6122:
6123: GEN_VR_STVE(bx, 0x07, 0x04);
6124: GEN_VR_STVE(hx, 0x07, 0x05);
6125: GEN_VR_STVE(wx, 0x07, 0x06);
6126:
1.1.1.7 root 6127: static void gen_lvsl(DisasContext *ctx)
1.1.1.6 root 6128: {
6129: TCGv_ptr rd;
6130: TCGv EA;
6131: if (unlikely(!ctx->altivec_enabled)) {
6132: gen_exception(ctx, POWERPC_EXCP_VPU);
6133: return;
6134: }
6135: EA = tcg_temp_new();
6136: gen_addr_reg_index(ctx, EA);
6137: rd = gen_avr_ptr(rD(ctx->opcode));
6138: gen_helper_lvsl(rd, EA);
6139: tcg_temp_free(EA);
6140: tcg_temp_free_ptr(rd);
6141: }
6142:
1.1.1.7 root 6143: static void gen_lvsr(DisasContext *ctx)
1.1.1.6 root 6144: {
6145: TCGv_ptr rd;
6146: TCGv EA;
6147: if (unlikely(!ctx->altivec_enabled)) {
6148: gen_exception(ctx, POWERPC_EXCP_VPU);
6149: return;
6150: }
6151: EA = tcg_temp_new();
6152: gen_addr_reg_index(ctx, EA);
6153: rd = gen_avr_ptr(rD(ctx->opcode));
6154: gen_helper_lvsr(rd, EA);
6155: tcg_temp_free(EA);
6156: tcg_temp_free_ptr(rd);
6157: }
6158:
1.1.1.7 root 6159: static void gen_mfvscr(DisasContext *ctx)
1.1.1.6 root 6160: {
6161: TCGv_i32 t;
6162: if (unlikely(!ctx->altivec_enabled)) {
6163: gen_exception(ctx, POWERPC_EXCP_VPU);
6164: return;
6165: }
6166: tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6167: t = tcg_temp_new_i32();
6168: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
6169: tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6170: tcg_temp_free_i32(t);
6171: }
6172:
1.1.1.7 root 6173: static void gen_mtvscr(DisasContext *ctx)
1.1.1.6 root 6174: {
6175: TCGv_ptr p;
6176: if (unlikely(!ctx->altivec_enabled)) {
6177: gen_exception(ctx, POWERPC_EXCP_VPU);
6178: return;
6179: }
6180: p = gen_avr_ptr(rD(ctx->opcode));
6181: gen_helper_mtvscr(p);
6182: tcg_temp_free_ptr(p);
6183: }
6184:
6185: /* Logical operations */
6186: #define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
1.1.1.7 root 6187: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6188: { \
6189: if (unlikely(!ctx->altivec_enabled)) { \
6190: gen_exception(ctx, POWERPC_EXCP_VPU); \
6191: return; \
6192: } \
6193: tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6194: tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6195: }
6196:
6197: GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6198: GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6199: GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6200: GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6201: GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6202:
6203: #define GEN_VXFORM(name, opc2, opc3) \
1.1.1.7 root 6204: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6205: { \
6206: TCGv_ptr ra, rb, rd; \
6207: if (unlikely(!ctx->altivec_enabled)) { \
6208: gen_exception(ctx, POWERPC_EXCP_VPU); \
6209: return; \
6210: } \
6211: ra = gen_avr_ptr(rA(ctx->opcode)); \
6212: rb = gen_avr_ptr(rB(ctx->opcode)); \
6213: rd = gen_avr_ptr(rD(ctx->opcode)); \
6214: gen_helper_##name (rd, ra, rb); \
6215: tcg_temp_free_ptr(ra); \
6216: tcg_temp_free_ptr(rb); \
6217: tcg_temp_free_ptr(rd); \
6218: }
6219:
6220: GEN_VXFORM(vaddubm, 0, 0);
6221: GEN_VXFORM(vadduhm, 0, 1);
6222: GEN_VXFORM(vadduwm, 0, 2);
6223: GEN_VXFORM(vsububm, 0, 16);
6224: GEN_VXFORM(vsubuhm, 0, 17);
6225: GEN_VXFORM(vsubuwm, 0, 18);
6226: GEN_VXFORM(vmaxub, 1, 0);
6227: GEN_VXFORM(vmaxuh, 1, 1);
6228: GEN_VXFORM(vmaxuw, 1, 2);
6229: GEN_VXFORM(vmaxsb, 1, 4);
6230: GEN_VXFORM(vmaxsh, 1, 5);
6231: GEN_VXFORM(vmaxsw, 1, 6);
6232: GEN_VXFORM(vminub, 1, 8);
6233: GEN_VXFORM(vminuh, 1, 9);
6234: GEN_VXFORM(vminuw, 1, 10);
6235: GEN_VXFORM(vminsb, 1, 12);
6236: GEN_VXFORM(vminsh, 1, 13);
6237: GEN_VXFORM(vminsw, 1, 14);
6238: GEN_VXFORM(vavgub, 1, 16);
6239: GEN_VXFORM(vavguh, 1, 17);
6240: GEN_VXFORM(vavguw, 1, 18);
6241: GEN_VXFORM(vavgsb, 1, 20);
6242: GEN_VXFORM(vavgsh, 1, 21);
6243: GEN_VXFORM(vavgsw, 1, 22);
6244: GEN_VXFORM(vmrghb, 6, 0);
6245: GEN_VXFORM(vmrghh, 6, 1);
6246: GEN_VXFORM(vmrghw, 6, 2);
6247: GEN_VXFORM(vmrglb, 6, 4);
6248: GEN_VXFORM(vmrglh, 6, 5);
6249: GEN_VXFORM(vmrglw, 6, 6);
6250: GEN_VXFORM(vmuloub, 4, 0);
6251: GEN_VXFORM(vmulouh, 4, 1);
6252: GEN_VXFORM(vmulosb, 4, 4);
6253: GEN_VXFORM(vmulosh, 4, 5);
6254: GEN_VXFORM(vmuleub, 4, 8);
6255: GEN_VXFORM(vmuleuh, 4, 9);
6256: GEN_VXFORM(vmulesb, 4, 12);
6257: GEN_VXFORM(vmulesh, 4, 13);
6258: GEN_VXFORM(vslb, 2, 4);
6259: GEN_VXFORM(vslh, 2, 5);
6260: GEN_VXFORM(vslw, 2, 6);
6261: GEN_VXFORM(vsrb, 2, 8);
6262: GEN_VXFORM(vsrh, 2, 9);
6263: GEN_VXFORM(vsrw, 2, 10);
6264: GEN_VXFORM(vsrab, 2, 12);
6265: GEN_VXFORM(vsrah, 2, 13);
6266: GEN_VXFORM(vsraw, 2, 14);
6267: GEN_VXFORM(vslo, 6, 16);
6268: GEN_VXFORM(vsro, 6, 17);
6269: GEN_VXFORM(vaddcuw, 0, 6);
6270: GEN_VXFORM(vsubcuw, 0, 22);
6271: GEN_VXFORM(vaddubs, 0, 8);
6272: GEN_VXFORM(vadduhs, 0, 9);
6273: GEN_VXFORM(vadduws, 0, 10);
6274: GEN_VXFORM(vaddsbs, 0, 12);
6275: GEN_VXFORM(vaddshs, 0, 13);
6276: GEN_VXFORM(vaddsws, 0, 14);
6277: GEN_VXFORM(vsububs, 0, 24);
6278: GEN_VXFORM(vsubuhs, 0, 25);
6279: GEN_VXFORM(vsubuws, 0, 26);
6280: GEN_VXFORM(vsubsbs, 0, 28);
6281: GEN_VXFORM(vsubshs, 0, 29);
6282: GEN_VXFORM(vsubsws, 0, 30);
6283: GEN_VXFORM(vrlb, 2, 0);
6284: GEN_VXFORM(vrlh, 2, 1);
6285: GEN_VXFORM(vrlw, 2, 2);
6286: GEN_VXFORM(vsl, 2, 7);
6287: GEN_VXFORM(vsr, 2, 11);
6288: GEN_VXFORM(vpkuhum, 7, 0);
6289: GEN_VXFORM(vpkuwum, 7, 1);
6290: GEN_VXFORM(vpkuhus, 7, 2);
6291: GEN_VXFORM(vpkuwus, 7, 3);
6292: GEN_VXFORM(vpkshus, 7, 4);
6293: GEN_VXFORM(vpkswus, 7, 5);
6294: GEN_VXFORM(vpkshss, 7, 6);
6295: GEN_VXFORM(vpkswss, 7, 7);
6296: GEN_VXFORM(vpkpx, 7, 12);
6297: GEN_VXFORM(vsum4ubs, 4, 24);
6298: GEN_VXFORM(vsum4sbs, 4, 28);
6299: GEN_VXFORM(vsum4shs, 4, 25);
6300: GEN_VXFORM(vsum2sws, 4, 26);
6301: GEN_VXFORM(vsumsws, 4, 30);
6302: GEN_VXFORM(vaddfp, 5, 0);
6303: GEN_VXFORM(vsubfp, 5, 1);
6304: GEN_VXFORM(vmaxfp, 5, 16);
6305: GEN_VXFORM(vminfp, 5, 17);
6306:
6307: #define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
1.1.1.7 root 6308: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6309: { \
6310: TCGv_ptr ra, rb, rd; \
6311: if (unlikely(!ctx->altivec_enabled)) { \
6312: gen_exception(ctx, POWERPC_EXCP_VPU); \
6313: return; \
6314: } \
6315: ra = gen_avr_ptr(rA(ctx->opcode)); \
6316: rb = gen_avr_ptr(rB(ctx->opcode)); \
6317: rd = gen_avr_ptr(rD(ctx->opcode)); \
6318: gen_helper_##opname (rd, ra, rb); \
6319: tcg_temp_free_ptr(ra); \
6320: tcg_temp_free_ptr(rb); \
6321: tcg_temp_free_ptr(rd); \
6322: }
6323:
6324: #define GEN_VXRFORM(name, opc2, opc3) \
6325: GEN_VXRFORM1(name, name, #name, opc2, opc3) \
6326: GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
6327:
6328: GEN_VXRFORM(vcmpequb, 3, 0)
6329: GEN_VXRFORM(vcmpequh, 3, 1)
6330: GEN_VXRFORM(vcmpequw, 3, 2)
6331: GEN_VXRFORM(vcmpgtsb, 3, 12)
6332: GEN_VXRFORM(vcmpgtsh, 3, 13)
6333: GEN_VXRFORM(vcmpgtsw, 3, 14)
6334: GEN_VXRFORM(vcmpgtub, 3, 8)
6335: GEN_VXRFORM(vcmpgtuh, 3, 9)
6336: GEN_VXRFORM(vcmpgtuw, 3, 10)
6337: GEN_VXRFORM(vcmpeqfp, 3, 3)
6338: GEN_VXRFORM(vcmpgefp, 3, 7)
6339: GEN_VXRFORM(vcmpgtfp, 3, 11)
6340: GEN_VXRFORM(vcmpbfp, 3, 15)
6341:
6342: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
1.1.1.7 root 6343: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6344: { \
6345: TCGv_ptr rd; \
6346: TCGv_i32 simm; \
6347: if (unlikely(!ctx->altivec_enabled)) { \
6348: gen_exception(ctx, POWERPC_EXCP_VPU); \
6349: return; \
6350: } \
6351: simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6352: rd = gen_avr_ptr(rD(ctx->opcode)); \
6353: gen_helper_##name (rd, simm); \
6354: tcg_temp_free_i32(simm); \
6355: tcg_temp_free_ptr(rd); \
6356: }
6357:
6358: GEN_VXFORM_SIMM(vspltisb, 6, 12);
6359: GEN_VXFORM_SIMM(vspltish, 6, 13);
6360: GEN_VXFORM_SIMM(vspltisw, 6, 14);
6361:
6362: #define GEN_VXFORM_NOA(name, opc2, opc3) \
1.1.1.7 root 6363: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6364: { \
6365: TCGv_ptr rb, rd; \
6366: if (unlikely(!ctx->altivec_enabled)) { \
6367: gen_exception(ctx, POWERPC_EXCP_VPU); \
6368: return; \
6369: } \
6370: rb = gen_avr_ptr(rB(ctx->opcode)); \
6371: rd = gen_avr_ptr(rD(ctx->opcode)); \
6372: gen_helper_##name (rd, rb); \
6373: tcg_temp_free_ptr(rb); \
6374: tcg_temp_free_ptr(rd); \
6375: }
6376:
6377: GEN_VXFORM_NOA(vupkhsb, 7, 8);
6378: GEN_VXFORM_NOA(vupkhsh, 7, 9);
6379: GEN_VXFORM_NOA(vupklsb, 7, 10);
6380: GEN_VXFORM_NOA(vupklsh, 7, 11);
6381: GEN_VXFORM_NOA(vupkhpx, 7, 13);
6382: GEN_VXFORM_NOA(vupklpx, 7, 15);
6383: GEN_VXFORM_NOA(vrefp, 5, 4);
6384: GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
1.1.1.9 ! root 6385: GEN_VXFORM_NOA(vexptefp, 5, 6);
1.1.1.6 root 6386: GEN_VXFORM_NOA(vlogefp, 5, 7);
6387: GEN_VXFORM_NOA(vrfim, 5, 8);
6388: GEN_VXFORM_NOA(vrfin, 5, 9);
6389: GEN_VXFORM_NOA(vrfip, 5, 10);
6390: GEN_VXFORM_NOA(vrfiz, 5, 11);
6391:
6392: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
1.1.1.7 root 6393: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6394: { \
6395: TCGv_ptr rd; \
6396: TCGv_i32 simm; \
6397: if (unlikely(!ctx->altivec_enabled)) { \
6398: gen_exception(ctx, POWERPC_EXCP_VPU); \
6399: return; \
6400: } \
6401: simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6402: rd = gen_avr_ptr(rD(ctx->opcode)); \
6403: gen_helper_##name (rd, simm); \
6404: tcg_temp_free_i32(simm); \
6405: tcg_temp_free_ptr(rd); \
6406: }
6407:
6408: #define GEN_VXFORM_UIMM(name, opc2, opc3) \
1.1.1.7 root 6409: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6410: { \
6411: TCGv_ptr rb, rd; \
6412: TCGv_i32 uimm; \
6413: if (unlikely(!ctx->altivec_enabled)) { \
6414: gen_exception(ctx, POWERPC_EXCP_VPU); \
6415: return; \
6416: } \
6417: uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
6418: rb = gen_avr_ptr(rB(ctx->opcode)); \
6419: rd = gen_avr_ptr(rD(ctx->opcode)); \
6420: gen_helper_##name (rd, rb, uimm); \
6421: tcg_temp_free_i32(uimm); \
6422: tcg_temp_free_ptr(rb); \
6423: tcg_temp_free_ptr(rd); \
6424: }
6425:
6426: GEN_VXFORM_UIMM(vspltb, 6, 8);
6427: GEN_VXFORM_UIMM(vsplth, 6, 9);
6428: GEN_VXFORM_UIMM(vspltw, 6, 10);
6429: GEN_VXFORM_UIMM(vcfux, 5, 12);
6430: GEN_VXFORM_UIMM(vcfsx, 5, 13);
6431: GEN_VXFORM_UIMM(vctuxs, 5, 14);
6432: GEN_VXFORM_UIMM(vctsxs, 5, 15);
6433:
1.1.1.7 root 6434: static void gen_vsldoi(DisasContext *ctx)
1.1.1.6 root 6435: {
6436: TCGv_ptr ra, rb, rd;
6437: TCGv_i32 sh;
6438: if (unlikely(!ctx->altivec_enabled)) {
6439: gen_exception(ctx, POWERPC_EXCP_VPU);
6440: return;
6441: }
6442: ra = gen_avr_ptr(rA(ctx->opcode));
6443: rb = gen_avr_ptr(rB(ctx->opcode));
6444: rd = gen_avr_ptr(rD(ctx->opcode));
6445: sh = tcg_const_i32(VSH(ctx->opcode));
6446: gen_helper_vsldoi (rd, ra, rb, sh);
6447: tcg_temp_free_ptr(ra);
6448: tcg_temp_free_ptr(rb);
6449: tcg_temp_free_ptr(rd);
6450: tcg_temp_free_i32(sh);
6451: }
6452:
6453: #define GEN_VAFORM_PAIRED(name0, name1, opc2) \
1.1.1.7 root 6454: static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
1.1.1.6 root 6455: { \
6456: TCGv_ptr ra, rb, rc, rd; \
6457: if (unlikely(!ctx->altivec_enabled)) { \
6458: gen_exception(ctx, POWERPC_EXCP_VPU); \
6459: return; \
6460: } \
6461: ra = gen_avr_ptr(rA(ctx->opcode)); \
6462: rb = gen_avr_ptr(rB(ctx->opcode)); \
6463: rc = gen_avr_ptr(rC(ctx->opcode)); \
6464: rd = gen_avr_ptr(rD(ctx->opcode)); \
6465: if (Rc(ctx->opcode)) { \
6466: gen_helper_##name1 (rd, ra, rb, rc); \
6467: } else { \
6468: gen_helper_##name0 (rd, ra, rb, rc); \
6469: } \
6470: tcg_temp_free_ptr(ra); \
6471: tcg_temp_free_ptr(rb); \
6472: tcg_temp_free_ptr(rc); \
6473: tcg_temp_free_ptr(rd); \
6474: }
6475:
6476: GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
6477:
1.1.1.7 root 6478: static void gen_vmladduhm(DisasContext *ctx)
1.1.1.6 root 6479: {
6480: TCGv_ptr ra, rb, rc, rd;
6481: if (unlikely(!ctx->altivec_enabled)) {
6482: gen_exception(ctx, POWERPC_EXCP_VPU);
6483: return;
6484: }
6485: ra = gen_avr_ptr(rA(ctx->opcode));
6486: rb = gen_avr_ptr(rB(ctx->opcode));
6487: rc = gen_avr_ptr(rC(ctx->opcode));
6488: rd = gen_avr_ptr(rD(ctx->opcode));
6489: gen_helper_vmladduhm(rd, ra, rb, rc);
6490: tcg_temp_free_ptr(ra);
6491: tcg_temp_free_ptr(rb);
6492: tcg_temp_free_ptr(rc);
6493: tcg_temp_free_ptr(rd);
6494: }
6495:
6496: GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
6497: GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
6498: GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
6499: GEN_VAFORM_PAIRED(vsel, vperm, 21)
6500: GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
1.1.1.5 root 6501:
6502: /*** SPE extension ***/
6503: /* Register moves */
6504:
1.1.1.8 root 6505: static inline void gen_load_gpr64(TCGv_i64 t, int reg)
6506: {
1.1.1.6 root 6507: #if defined(TARGET_PPC64)
6508: tcg_gen_mov_i64(t, cpu_gpr[reg]);
6509: #else
6510: tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
1.1.1.5 root 6511: #endif
1.1.1.6 root 6512: }
1.1.1.5 root 6513:
1.1.1.8 root 6514: static inline void gen_store_gpr64(int reg, TCGv_i64 t)
6515: {
1.1.1.6 root 6516: #if defined(TARGET_PPC64)
6517: tcg_gen_mov_i64(cpu_gpr[reg], t);
6518: #else
6519: TCGv_i64 tmp = tcg_temp_new_i64();
6520: tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
6521: tcg_gen_shri_i64(tmp, t, 32);
6522: tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
6523: tcg_temp_free_i64(tmp);
1.1.1.5 root 6524: #endif
1.1.1.6 root 6525: }
1.1.1.5 root 6526:
6527: #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
1.1.1.7 root 6528: static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
1.1.1.5 root 6529: { \
6530: if (Rc(ctx->opcode)) \
6531: gen_##name1(ctx); \
6532: else \
6533: gen_##name0(ctx); \
6534: }
6535:
6536: /* Handler for undefined SPE opcodes */
1.1.1.8 root 6537: static inline void gen_speundef(DisasContext *ctx)
1.1 root 6538: {
1.1.1.6 root 6539: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 6540: }
6541:
1.1.1.6 root 6542: /* SPE logic */
6543: #if defined(TARGET_PPC64)
6544: #define GEN_SPEOP_LOGIC2(name, tcg_op) \
1.1.1.8 root 6545: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6546: { \
6547: if (unlikely(!ctx->spe_enabled)) { \
6548: gen_exception(ctx, POWERPC_EXCP_APU); \
6549: return; \
6550: } \
6551: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6552: cpu_gpr[rB(ctx->opcode)]); \
6553: }
6554: #else
6555: #define GEN_SPEOP_LOGIC2(name, tcg_op) \
1.1.1.8 root 6556: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6557: { \
6558: if (unlikely(!ctx->spe_enabled)) { \
6559: gen_exception(ctx, POWERPC_EXCP_APU); \
6560: return; \
6561: } \
6562: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6563: cpu_gpr[rB(ctx->opcode)]); \
6564: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6565: cpu_gprh[rB(ctx->opcode)]); \
1.1.1.5 root 6566: }
1.1.1.6 root 6567: #endif
1.1.1.5 root 6568:
1.1.1.6 root 6569: GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6570: GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6571: GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6572: GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6573: GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6574: GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6575: GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6576: GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
1.1.1.5 root 6577:
1.1.1.6 root 6578: /* SPE logic immediate */
6579: #if defined(TARGET_PPC64)
6580: #define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
1.1.1.8 root 6581: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6582: { \
6583: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6584: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6585: return; \
6586: } \
1.1.1.6 root 6587: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6588: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6589: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6590: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6591: tcg_opi(t0, t0, rB(ctx->opcode)); \
6592: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6593: tcg_gen_trunc_i64_i32(t1, t2); \
6594: tcg_temp_free_i64(t2); \
6595: tcg_opi(t1, t1, rB(ctx->opcode)); \
6596: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6597: tcg_temp_free_i32(t0); \
6598: tcg_temp_free_i32(t1); \
1.1.1.5 root 6599: }
1.1.1.6 root 6600: #else
6601: #define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
1.1.1.8 root 6602: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6603: { \
6604: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6605: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6606: return; \
6607: } \
1.1.1.6 root 6608: tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6609: rB(ctx->opcode)); \
6610: tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6611: rB(ctx->opcode)); \
1.1.1.5 root 6612: }
1.1.1.6 root 6613: #endif
6614: GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6615: GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6616: GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6617: GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
1.1.1.5 root 6618:
1.1.1.6 root 6619: /* SPE arithmetic */
6620: #if defined(TARGET_PPC64)
6621: #define GEN_SPEOP_ARITH1(name, tcg_op) \
1.1.1.8 root 6622: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6623: { \
6624: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6625: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6626: return; \
6627: } \
1.1.1.6 root 6628: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6629: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6630: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6631: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6632: tcg_op(t0, t0); \
6633: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6634: tcg_gen_trunc_i64_i32(t1, t2); \
6635: tcg_temp_free_i64(t2); \
6636: tcg_op(t1, t1); \
6637: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6638: tcg_temp_free_i32(t0); \
6639: tcg_temp_free_i32(t1); \
1.1.1.5 root 6640: }
1.1.1.6 root 6641: #else
6642: #define GEN_SPEOP_ARITH1(name, tcg_op) \
1.1.1.8 root 6643: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6644: { \
6645: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6646: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6647: return; \
6648: } \
1.1.1.6 root 6649: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
6650: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
1.1.1.5 root 6651: }
1.1.1.6 root 6652: #endif
1.1.1.5 root 6653:
1.1.1.8 root 6654: static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
1.1.1.6 root 6655: {
6656: int l1 = gen_new_label();
6657: int l2 = gen_new_label();
1.1.1.5 root 6658:
1.1.1.6 root 6659: tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6660: tcg_gen_neg_i32(ret, arg1);
6661: tcg_gen_br(l2);
6662: gen_set_label(l1);
6663: tcg_gen_mov_i32(ret, arg1);
6664: gen_set_label(l2);
6665: }
6666: GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6667: GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6668: GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6669: GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
1.1.1.8 root 6670: static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
1.1.1.6 root 6671: {
6672: tcg_gen_addi_i32(ret, arg1, 0x8000);
6673: tcg_gen_ext16u_i32(ret, ret);
6674: }
6675: GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
6676: GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6677: GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
1.1.1.5 root 6678:
1.1.1.6 root 6679: #if defined(TARGET_PPC64)
6680: #define GEN_SPEOP_ARITH2(name, tcg_op) \
1.1.1.8 root 6681: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6682: { \
6683: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6684: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6685: return; \
6686: } \
1.1.1.6 root 6687: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6688: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6689: TCGv_i32 t2 = tcg_temp_local_new_i32(); \
6690: TCGv_i64 t3 = tcg_temp_local_new_i64(); \
6691: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6692: tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
6693: tcg_op(t0, t0, t2); \
6694: tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
6695: tcg_gen_trunc_i64_i32(t1, t3); \
6696: tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
6697: tcg_gen_trunc_i64_i32(t2, t3); \
6698: tcg_temp_free_i64(t3); \
6699: tcg_op(t1, t1, t2); \
6700: tcg_temp_free_i32(t2); \
6701: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6702: tcg_temp_free_i32(t0); \
6703: tcg_temp_free_i32(t1); \
1.1.1.5 root 6704: }
1.1.1.6 root 6705: #else
6706: #define GEN_SPEOP_ARITH2(name, tcg_op) \
1.1.1.8 root 6707: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6708: { \
6709: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6710: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6711: return; \
6712: } \
1.1.1.6 root 6713: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6714: cpu_gpr[rB(ctx->opcode)]); \
6715: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6716: cpu_gprh[rB(ctx->opcode)]); \
6717: }
6718: #endif
6719:
1.1.1.8 root 6720: static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6721: {
6722: TCGv_i32 t0;
6723: int l1, l2;
6724:
6725: l1 = gen_new_label();
6726: l2 = gen_new_label();
6727: t0 = tcg_temp_local_new_i32();
6728: /* No error here: 6 bits are used */
6729: tcg_gen_andi_i32(t0, arg2, 0x3F);
6730: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6731: tcg_gen_shr_i32(ret, arg1, t0);
6732: tcg_gen_br(l2);
6733: gen_set_label(l1);
6734: tcg_gen_movi_i32(ret, 0);
1.1.1.9 ! root 6735: gen_set_label(l2);
1.1.1.6 root 6736: tcg_temp_free_i32(t0);
6737: }
6738: GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
1.1.1.8 root 6739: static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6740: {
6741: TCGv_i32 t0;
6742: int l1, l2;
6743:
6744: l1 = gen_new_label();
6745: l2 = gen_new_label();
6746: t0 = tcg_temp_local_new_i32();
6747: /* No error here: 6 bits are used */
6748: tcg_gen_andi_i32(t0, arg2, 0x3F);
6749: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6750: tcg_gen_sar_i32(ret, arg1, t0);
6751: tcg_gen_br(l2);
6752: gen_set_label(l1);
6753: tcg_gen_movi_i32(ret, 0);
1.1.1.9 ! root 6754: gen_set_label(l2);
1.1.1.6 root 6755: tcg_temp_free_i32(t0);
6756: }
6757: GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
1.1.1.8 root 6758: static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6759: {
6760: TCGv_i32 t0;
6761: int l1, l2;
6762:
6763: l1 = gen_new_label();
6764: l2 = gen_new_label();
6765: t0 = tcg_temp_local_new_i32();
6766: /* No error here: 6 bits are used */
6767: tcg_gen_andi_i32(t0, arg2, 0x3F);
6768: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6769: tcg_gen_shl_i32(ret, arg1, t0);
6770: tcg_gen_br(l2);
6771: gen_set_label(l1);
6772: tcg_gen_movi_i32(ret, 0);
1.1.1.9 ! root 6773: gen_set_label(l2);
1.1.1.6 root 6774: tcg_temp_free_i32(t0);
6775: }
6776: GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
1.1.1.8 root 6777: static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6778: {
6779: TCGv_i32 t0 = tcg_temp_new_i32();
6780: tcg_gen_andi_i32(t0, arg2, 0x1F);
6781: tcg_gen_rotl_i32(ret, arg1, t0);
6782: tcg_temp_free_i32(t0);
6783: }
6784: GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
1.1.1.8 root 6785: static inline void gen_evmergehi(DisasContext *ctx)
1.1.1.6 root 6786: {
6787: if (unlikely(!ctx->spe_enabled)) {
6788: gen_exception(ctx, POWERPC_EXCP_APU);
6789: return;
6790: }
6791: #if defined(TARGET_PPC64)
6792: TCGv t0 = tcg_temp_new();
6793: TCGv t1 = tcg_temp_new();
6794: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6795: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6796: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6797: tcg_temp_free(t0);
6798: tcg_temp_free(t1);
6799: #else
6800: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6801: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6802: #endif
6803: }
6804: GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
1.1.1.8 root 6805: static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 6806: {
6807: tcg_gen_sub_i32(ret, arg2, arg1);
1.1.1.5 root 6808: }
1.1.1.6 root 6809: GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
1.1.1.5 root 6810:
1.1.1.6 root 6811: /* SPE arithmetic immediate */
6812: #if defined(TARGET_PPC64)
6813: #define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
1.1.1.8 root 6814: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6815: { \
6816: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6817: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6818: return; \
6819: } \
1.1.1.6 root 6820: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6821: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6822: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6823: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6824: tcg_op(t0, t0, rA(ctx->opcode)); \
6825: tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6826: tcg_gen_trunc_i64_i32(t1, t2); \
6827: tcg_temp_free_i64(t2); \
6828: tcg_op(t1, t1, rA(ctx->opcode)); \
6829: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6830: tcg_temp_free_i32(t0); \
6831: tcg_temp_free_i32(t1); \
1.1 root 6832: }
1.1.1.6 root 6833: #else
6834: #define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
1.1.1.8 root 6835: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6836: { \
6837: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6838: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6839: return; \
6840: } \
1.1.1.6 root 6841: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
6842: rA(ctx->opcode)); \
6843: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
6844: rA(ctx->opcode)); \
1.1.1.5 root 6845: }
1.1.1.6 root 6846: #endif
6847: GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6848: GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
1.1.1.5 root 6849:
1.1.1.6 root 6850: /* SPE comparison */
6851: #if defined(TARGET_PPC64)
6852: #define GEN_SPEOP_COMP(name, tcg_cond) \
1.1.1.8 root 6853: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6854: { \
6855: if (unlikely(!ctx->spe_enabled)) { \
6856: gen_exception(ctx, POWERPC_EXCP_APU); \
6857: return; \
6858: } \
6859: int l1 = gen_new_label(); \
6860: int l2 = gen_new_label(); \
6861: int l3 = gen_new_label(); \
6862: int l4 = gen_new_label(); \
6863: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6864: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6865: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6866: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6867: tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
6868: tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
6869: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
6870: tcg_gen_br(l2); \
6871: gen_set_label(l1); \
6872: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6873: CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6874: gen_set_label(l2); \
6875: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6876: tcg_gen_trunc_i64_i32(t0, t2); \
6877: tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6878: tcg_gen_trunc_i64_i32(t1, t2); \
6879: tcg_temp_free_i64(t2); \
6880: tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
6881: tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6882: ~(CRF_CH | CRF_CH_AND_CL)); \
6883: tcg_gen_br(l4); \
6884: gen_set_label(l3); \
6885: tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6886: CRF_CH | CRF_CH_OR_CL); \
6887: gen_set_label(l4); \
6888: tcg_temp_free_i32(t0); \
6889: tcg_temp_free_i32(t1); \
6890: }
6891: #else
6892: #define GEN_SPEOP_COMP(name, tcg_cond) \
1.1.1.8 root 6893: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6894: { \
6895: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.6 root 6896: gen_exception(ctx, POWERPC_EXCP_APU); \
1.1.1.5 root 6897: return; \
6898: } \
1.1.1.6 root 6899: int l1 = gen_new_label(); \
6900: int l2 = gen_new_label(); \
6901: int l3 = gen_new_label(); \
6902: int l4 = gen_new_label(); \
6903: \
6904: tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
6905: cpu_gpr[rB(ctx->opcode)], l1); \
6906: tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
6907: tcg_gen_br(l2); \
6908: gen_set_label(l1); \
6909: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6910: CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6911: gen_set_label(l2); \
6912: tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
6913: cpu_gprh[rB(ctx->opcode)], l3); \
6914: tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6915: ~(CRF_CH | CRF_CH_AND_CL)); \
6916: tcg_gen_br(l4); \
6917: gen_set_label(l3); \
6918: tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6919: CRF_CH | CRF_CH_OR_CL); \
6920: gen_set_label(l4); \
6921: }
6922: #endif
6923: GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6924: GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6925: GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6926: GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6927: GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
1.1.1.5 root 6928:
1.1.1.6 root 6929: /* SPE misc */
1.1.1.8 root 6930: static inline void gen_brinc(DisasContext *ctx)
1.1.1.6 root 6931: {
6932: /* Note: brinc is usable even if SPE is disabled */
6933: gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6934: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6935: }
1.1.1.8 root 6936: static inline void gen_evmergelo(DisasContext *ctx)
1.1.1.6 root 6937: {
6938: if (unlikely(!ctx->spe_enabled)) {
6939: gen_exception(ctx, POWERPC_EXCP_APU);
6940: return;
6941: }
6942: #if defined(TARGET_PPC64)
6943: TCGv t0 = tcg_temp_new();
6944: TCGv t1 = tcg_temp_new();
6945: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6946: tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6947: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6948: tcg_temp_free(t0);
6949: tcg_temp_free(t1);
6950: #else
6951: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.7 root 6952: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.6 root 6953: #endif
6954: }
1.1.1.8 root 6955: static inline void gen_evmergehilo(DisasContext *ctx)
1.1.1.6 root 6956: {
6957: if (unlikely(!ctx->spe_enabled)) {
6958: gen_exception(ctx, POWERPC_EXCP_APU);
6959: return;
6960: }
6961: #if defined(TARGET_PPC64)
6962: TCGv t0 = tcg_temp_new();
6963: TCGv t1 = tcg_temp_new();
6964: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6965: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6966: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6967: tcg_temp_free(t0);
6968: tcg_temp_free(t1);
6969: #else
6970: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6971: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6972: #endif
6973: }
1.1.1.8 root 6974: static inline void gen_evmergelohi(DisasContext *ctx)
1.1.1.6 root 6975: {
6976: if (unlikely(!ctx->spe_enabled)) {
6977: gen_exception(ctx, POWERPC_EXCP_APU);
6978: return;
6979: }
6980: #if defined(TARGET_PPC64)
6981: TCGv t0 = tcg_temp_new();
6982: TCGv t1 = tcg_temp_new();
6983: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6984: tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6985: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6986: tcg_temp_free(t0);
6987: tcg_temp_free(t1);
6988: #else
1.1.1.7 root 6989: if (rD(ctx->opcode) == rA(ctx->opcode)) {
6990: TCGv_i32 tmp = tcg_temp_new_i32();
6991: tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
6992: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6993: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
6994: tcg_temp_free_i32(tmp);
6995: } else {
6996: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6997: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6998: }
1.1.1.6 root 6999: #endif
7000: }
1.1.1.8 root 7001: static inline void gen_evsplati(DisasContext *ctx)
1.1.1.5 root 7002: {
1.1.1.9 ! root 7003: uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
1.1.1.5 root 7004:
1.1.1.6 root 7005: #if defined(TARGET_PPC64)
7006: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7007: #else
7008: tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7009: tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7010: #endif
1.1.1.5 root 7011: }
1.1.1.8 root 7012: static inline void gen_evsplatfi(DisasContext *ctx)
1.1.1.5 root 7013: {
1.1.1.9 ! root 7014: uint64_t imm = rA(ctx->opcode) << 27;
1.1.1.5 root 7015:
1.1.1.6 root 7016: #if defined(TARGET_PPC64)
7017: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7018: #else
7019: tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7020: tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7021: #endif
1.1.1.5 root 7022: }
7023:
1.1.1.8 root 7024: static inline void gen_evsel(DisasContext *ctx)
1.1.1.6 root 7025: {
7026: int l1 = gen_new_label();
7027: int l2 = gen_new_label();
7028: int l3 = gen_new_label();
7029: int l4 = gen_new_label();
7030: TCGv_i32 t0 = tcg_temp_local_new_i32();
7031: #if defined(TARGET_PPC64)
7032: TCGv t1 = tcg_temp_local_new();
7033: TCGv t2 = tcg_temp_local_new();
7034: #endif
7035: tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
7036: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
7037: #if defined(TARGET_PPC64)
7038: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7039: #else
7040: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7041: #endif
7042: tcg_gen_br(l2);
7043: gen_set_label(l1);
7044: #if defined(TARGET_PPC64)
7045: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7046: #else
7047: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7048: #endif
7049: gen_set_label(l2);
7050: tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
7051: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
7052: #if defined(TARGET_PPC64)
7053: tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
7054: #else
7055: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7056: #endif
7057: tcg_gen_br(l4);
7058: gen_set_label(l3);
7059: #if defined(TARGET_PPC64)
7060: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
7061: #else
7062: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7063: #endif
7064: gen_set_label(l4);
7065: tcg_temp_free_i32(t0);
7066: #if defined(TARGET_PPC64)
7067: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
7068: tcg_temp_free(t1);
7069: tcg_temp_free(t2);
7070: #endif
7071: }
1.1.1.7 root 7072:
7073: static void gen_evsel0(DisasContext *ctx)
1.1.1.6 root 7074: {
7075: gen_evsel(ctx);
7076: }
1.1.1.7 root 7077:
7078: static void gen_evsel1(DisasContext *ctx)
1.1.1.6 root 7079: {
7080: gen_evsel(ctx);
7081: }
1.1.1.7 root 7082:
7083: static void gen_evsel2(DisasContext *ctx)
1.1.1.6 root 7084: {
7085: gen_evsel(ctx);
7086: }
1.1.1.7 root 7087:
7088: static void gen_evsel3(DisasContext *ctx)
1.1.1.6 root 7089: {
7090: gen_evsel(ctx);
7091: }
1.1.1.5 root 7092:
7093: GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
7094: GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
7095: GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
7096: GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
7097: GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
7098: GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
7099: GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
7100: GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
7101: GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
7102: GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
7103: GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
7104: GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
7105: GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
7106: GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
7107: GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
7108: GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
7109: GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
7110: GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
7111: GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
7112: GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
7113: GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
7114: GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
7115: GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
7116: GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
7117: GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
7118:
1.1.1.6 root 7119: /* SPE load and stores */
1.1.1.8 root 7120: static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
1.1 root 7121: {
1.1.1.6 root 7122: target_ulong uimm = rB(ctx->opcode);
7123:
7124: if (rA(ctx->opcode) == 0) {
7125: tcg_gen_movi_tl(EA, uimm << sh);
7126: } else {
7127: tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
7128: #if defined(TARGET_PPC64)
7129: if (!ctx->sf_mode) {
7130: tcg_gen_ext32u_tl(EA, EA);
7131: }
7132: #endif
1.1 root 7133: }
1.1.1.5 root 7134: }
7135:
1.1.1.8 root 7136: static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7137: {
1.1.1.6 root 7138: #if defined(TARGET_PPC64)
7139: gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7140: #else
7141: TCGv_i64 t0 = tcg_temp_new_i64();
7142: gen_qemu_ld64(ctx, t0, addr);
7143: tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
7144: tcg_gen_shri_i64(t0, t0, 32);
7145: tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
7146: tcg_temp_free_i64(t0);
7147: #endif
1.1.1.5 root 7148: }
1.1.1.6 root 7149:
1.1.1.8 root 7150: static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7151: {
1.1.1.6 root 7152: #if defined(TARGET_PPC64)
7153: TCGv t0 = tcg_temp_new();
7154: gen_qemu_ld32u(ctx, t0, addr);
7155: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7156: gen_addr_add(ctx, addr, addr, 4);
7157: gen_qemu_ld32u(ctx, t0, addr);
7158: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7159: tcg_temp_free(t0);
7160: #else
7161: gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7162: gen_addr_add(ctx, addr, addr, 4);
7163: gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7164: #endif
1.1.1.5 root 7165: }
1.1.1.6 root 7166:
1.1.1.8 root 7167: static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7168: {
1.1.1.6 root 7169: TCGv t0 = tcg_temp_new();
7170: #if defined(TARGET_PPC64)
7171: gen_qemu_ld16u(ctx, t0, addr);
7172: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7173: gen_addr_add(ctx, addr, addr, 2);
7174: gen_qemu_ld16u(ctx, t0, addr);
7175: tcg_gen_shli_tl(t0, t0, 32);
7176: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7177: gen_addr_add(ctx, addr, addr, 2);
7178: gen_qemu_ld16u(ctx, t0, addr);
7179: tcg_gen_shli_tl(t0, t0, 16);
7180: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7181: gen_addr_add(ctx, addr, addr, 2);
7182: gen_qemu_ld16u(ctx, t0, addr);
7183: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7184: #else
7185: gen_qemu_ld16u(ctx, t0, addr);
7186: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7187: gen_addr_add(ctx, addr, addr, 2);
7188: gen_qemu_ld16u(ctx, t0, addr);
7189: tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7190: gen_addr_add(ctx, addr, addr, 2);
7191: gen_qemu_ld16u(ctx, t0, addr);
7192: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7193: gen_addr_add(ctx, addr, addr, 2);
7194: gen_qemu_ld16u(ctx, t0, addr);
7195: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7196: #endif
7197: tcg_temp_free(t0);
1.1.1.5 root 7198: }
1.1.1.6 root 7199:
1.1.1.8 root 7200: static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7201: {
1.1.1.6 root 7202: TCGv t0 = tcg_temp_new();
7203: gen_qemu_ld16u(ctx, t0, addr);
7204: #if defined(TARGET_PPC64)
7205: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7206: tcg_gen_shli_tl(t0, t0, 16);
7207: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7208: #else
7209: tcg_gen_shli_tl(t0, t0, 16);
7210: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7211: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7212: #endif
7213: tcg_temp_free(t0);
1.1.1.5 root 7214: }
7215:
1.1.1.8 root 7216: static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7217: {
7218: TCGv t0 = tcg_temp_new();
7219: gen_qemu_ld16u(ctx, t0, addr);
1.1.1.5 root 7220: #if defined(TARGET_PPC64)
1.1.1.6 root 7221: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7222: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7223: #else
7224: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7225: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7226: #endif
7227: tcg_temp_free(t0);
7228: }
7229:
1.1.1.8 root 7230: static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7231: {
7232: TCGv t0 = tcg_temp_new();
7233: gen_qemu_ld16s(ctx, t0, addr);
7234: #if defined(TARGET_PPC64)
7235: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7236: tcg_gen_ext32u_tl(t0, t0);
7237: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7238: #else
7239: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7240: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7241: #endif
7242: tcg_temp_free(t0);
7243: }
7244:
1.1.1.8 root 7245: static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7246: {
7247: TCGv t0 = tcg_temp_new();
7248: #if defined(TARGET_PPC64)
7249: gen_qemu_ld16u(ctx, t0, addr);
7250: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7251: gen_addr_add(ctx, addr, addr, 2);
7252: gen_qemu_ld16u(ctx, t0, addr);
7253: tcg_gen_shli_tl(t0, t0, 16);
7254: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7255: #else
7256: gen_qemu_ld16u(ctx, t0, addr);
7257: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7258: gen_addr_add(ctx, addr, addr, 2);
7259: gen_qemu_ld16u(ctx, t0, addr);
7260: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7261: #endif
7262: tcg_temp_free(t0);
7263: }
7264:
1.1.1.8 root 7265: static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7266: {
7267: #if defined(TARGET_PPC64)
7268: TCGv t0 = tcg_temp_new();
7269: gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7270: gen_addr_add(ctx, addr, addr, 2);
7271: gen_qemu_ld16u(ctx, t0, addr);
7272: tcg_gen_shli_tl(t0, t0, 32);
7273: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7274: tcg_temp_free(t0);
7275: #else
7276: gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7277: gen_addr_add(ctx, addr, addr, 2);
7278: gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7279: #endif
7280: }
7281:
1.1.1.8 root 7282: static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7283: {
7284: #if defined(TARGET_PPC64)
7285: TCGv t0 = tcg_temp_new();
7286: gen_qemu_ld16s(ctx, t0, addr);
7287: tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
7288: gen_addr_add(ctx, addr, addr, 2);
7289: gen_qemu_ld16s(ctx, t0, addr);
7290: tcg_gen_shli_tl(t0, t0, 32);
7291: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7292: tcg_temp_free(t0);
7293: #else
7294: gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7295: gen_addr_add(ctx, addr, addr, 2);
7296: gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7297: #endif
7298: }
7299:
1.1.1.8 root 7300: static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7301: {
7302: TCGv t0 = tcg_temp_new();
7303: gen_qemu_ld32u(ctx, t0, addr);
7304: #if defined(TARGET_PPC64)
7305: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7306: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7307: #else
7308: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7309: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7310: #endif
7311: tcg_temp_free(t0);
7312: }
7313:
1.1.1.8 root 7314: static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7315: {
7316: TCGv t0 = tcg_temp_new();
7317: #if defined(TARGET_PPC64)
7318: gen_qemu_ld16u(ctx, t0, addr);
7319: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7320: tcg_gen_shli_tl(t0, t0, 32);
7321: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7322: gen_addr_add(ctx, addr, addr, 2);
7323: gen_qemu_ld16u(ctx, t0, addr);
7324: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7325: tcg_gen_shli_tl(t0, t0, 16);
7326: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7327: #else
7328: gen_qemu_ld16u(ctx, t0, addr);
7329: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7330: tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7331: gen_addr_add(ctx, addr, addr, 2);
7332: gen_qemu_ld16u(ctx, t0, addr);
7333: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7334: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7335: #endif
7336: tcg_temp_free(t0);
7337: }
7338:
1.1.1.8 root 7339: static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7340: {
7341: #if defined(TARGET_PPC64)
7342: gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7343: #else
7344: TCGv_i64 t0 = tcg_temp_new_i64();
7345: tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
7346: gen_qemu_st64(ctx, t0, addr);
7347: tcg_temp_free_i64(t0);
7348: #endif
7349: }
7350:
1.1.1.8 root 7351: static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7352: {
7353: #if defined(TARGET_PPC64)
7354: TCGv t0 = tcg_temp_new();
7355: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7356: gen_qemu_st32(ctx, t0, addr);
7357: tcg_temp_free(t0);
7358: #else
7359: gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7360: #endif
7361: gen_addr_add(ctx, addr, addr, 4);
7362: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
1.1.1.5 root 7363: }
1.1.1.6 root 7364:
1.1.1.8 root 7365: static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7366: {
7367: TCGv t0 = tcg_temp_new();
7368: #if defined(TARGET_PPC64)
7369: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
1.1.1.5 root 7370: #else
1.1.1.6 root 7371: tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7372: #endif
7373: gen_qemu_st16(ctx, t0, addr);
7374: gen_addr_add(ctx, addr, addr, 2);
7375: #if defined(TARGET_PPC64)
7376: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7377: gen_qemu_st16(ctx, t0, addr);
7378: #else
7379: gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7380: #endif
7381: gen_addr_add(ctx, addr, addr, 2);
7382: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7383: gen_qemu_st16(ctx, t0, addr);
7384: tcg_temp_free(t0);
7385: gen_addr_add(ctx, addr, addr, 2);
7386: gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7387: }
7388:
1.1.1.8 root 7389: static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7390: {
7391: TCGv t0 = tcg_temp_new();
7392: #if defined(TARGET_PPC64)
7393: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7394: #else
7395: tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7396: #endif
7397: gen_qemu_st16(ctx, t0, addr);
7398: gen_addr_add(ctx, addr, addr, 2);
7399: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7400: gen_qemu_st16(ctx, t0, addr);
7401: tcg_temp_free(t0);
7402: }
7403:
1.1.1.8 root 7404: static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7405: {
7406: #if defined(TARGET_PPC64)
7407: TCGv t0 = tcg_temp_new();
7408: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7409: gen_qemu_st16(ctx, t0, addr);
7410: tcg_temp_free(t0);
7411: #else
7412: gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7413: #endif
7414: gen_addr_add(ctx, addr, addr, 2);
7415: gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7416: }
7417:
1.1.1.8 root 7418: static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7419: {
7420: #if defined(TARGET_PPC64)
7421: TCGv t0 = tcg_temp_new();
7422: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7423: gen_qemu_st32(ctx, t0, addr);
7424: tcg_temp_free(t0);
7425: #else
7426: gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7427: #endif
7428: }
7429:
1.1.1.8 root 7430: static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7431: {
7432: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7433: }
7434:
7435: #define GEN_SPEOP_LDST(name, opc2, sh) \
1.1.1.7 root 7436: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 7437: { \
7438: TCGv t0; \
7439: if (unlikely(!ctx->spe_enabled)) { \
7440: gen_exception(ctx, POWERPC_EXCP_APU); \
7441: return; \
7442: } \
7443: gen_set_access_type(ctx, ACCESS_INT); \
7444: t0 = tcg_temp_new(); \
7445: if (Rc(ctx->opcode)) { \
7446: gen_addr_spe_imm_index(ctx, t0, sh); \
7447: } else { \
7448: gen_addr_reg_index(ctx, t0); \
7449: } \
7450: gen_op_##name(ctx, t0); \
7451: tcg_temp_free(t0); \
7452: }
7453:
7454: GEN_SPEOP_LDST(evldd, 0x00, 3);
7455: GEN_SPEOP_LDST(evldw, 0x01, 3);
7456: GEN_SPEOP_LDST(evldh, 0x02, 3);
7457: GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7458: GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7459: GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7460: GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7461: GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7462: GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7463: GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7464: GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7465:
7466: GEN_SPEOP_LDST(evstdd, 0x10, 3);
7467: GEN_SPEOP_LDST(evstdw, 0x11, 3);
7468: GEN_SPEOP_LDST(evstdh, 0x12, 3);
7469: GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7470: GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7471: GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7472: GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
1.1.1.5 root 7473:
7474: /* Multiply and add - TODO */
7475: #if 0
7476: GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
7477: GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
7478: GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
7479: GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
7480: GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
7481: GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
7482: GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
7483: GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
7484: GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
7485: GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
7486: GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
7487: GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
7488:
7489: GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
7490: GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
7491: GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
7492: GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
7493: GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
7494: GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
7495: GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
7496: GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
7497: GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
7498: GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
7499: GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
7500: GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
7501: GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
7502: GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
7503:
7504: GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
7505: GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
7506: GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
7507: GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
7508: GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
7509: GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
7510:
7511: GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
7512: GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
7513: GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
7514: GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
7515: GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
7516: GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
7517: GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
7518: GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
7519: GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
7520: GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
7521: GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
7522: GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
7523:
7524: GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
7525: GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
7526: GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
7527: GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
7528: GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
7529:
7530: GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
7531: GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
7532: GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
7533: GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
7534: GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
7535: GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
7536: GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
7537: GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
7538: GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
7539: GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
7540: GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
7541: GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
7542:
7543: GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
7544: GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
7545: GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
7546: GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
7547: GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
7548: #endif
7549:
7550: /*** SPE floating-point extension ***/
1.1.1.6 root 7551: #if defined(TARGET_PPC64)
7552: #define GEN_SPEFPUOP_CONV_32_32(name) \
1.1.1.8 root 7553: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7554: { \
7555: TCGv_i32 t0; \
7556: TCGv t1; \
7557: t0 = tcg_temp_new_i32(); \
7558: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7559: gen_helper_##name(t0, t0); \
7560: t1 = tcg_temp_new(); \
7561: tcg_gen_extu_i32_tl(t1, t0); \
7562: tcg_temp_free_i32(t0); \
7563: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7564: 0xFFFFFFFF00000000ULL); \
7565: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7566: tcg_temp_free(t1); \
7567: }
7568: #define GEN_SPEFPUOP_CONV_32_64(name) \
1.1.1.8 root 7569: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7570: { \
7571: TCGv_i32 t0; \
7572: TCGv t1; \
7573: t0 = tcg_temp_new_i32(); \
7574: gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7575: t1 = tcg_temp_new(); \
7576: tcg_gen_extu_i32_tl(t1, t0); \
7577: tcg_temp_free_i32(t0); \
7578: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7579: 0xFFFFFFFF00000000ULL); \
7580: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7581: tcg_temp_free(t1); \
7582: }
7583: #define GEN_SPEFPUOP_CONV_64_32(name) \
1.1.1.8 root 7584: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7585: { \
7586: TCGv_i32 t0 = tcg_temp_new_i32(); \
7587: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7588: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7589: tcg_temp_free_i32(t0); \
7590: }
7591: #define GEN_SPEFPUOP_CONV_64_64(name) \
1.1.1.8 root 7592: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7593: { \
7594: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7595: }
7596: #define GEN_SPEFPUOP_ARITH2_32_32(name) \
1.1.1.8 root 7597: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7598: { \
7599: TCGv_i32 t0, t1; \
7600: TCGv_i64 t2; \
7601: if (unlikely(!ctx->spe_enabled)) { \
7602: gen_exception(ctx, POWERPC_EXCP_APU); \
7603: return; \
7604: } \
7605: t0 = tcg_temp_new_i32(); \
7606: t1 = tcg_temp_new_i32(); \
7607: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7608: tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7609: gen_helper_##name(t0, t0, t1); \
7610: tcg_temp_free_i32(t1); \
7611: t2 = tcg_temp_new(); \
7612: tcg_gen_extu_i32_tl(t2, t0); \
7613: tcg_temp_free_i32(t0); \
7614: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7615: 0xFFFFFFFF00000000ULL); \
7616: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
7617: tcg_temp_free(t2); \
7618: }
7619: #define GEN_SPEFPUOP_ARITH2_64_64(name) \
1.1.1.8 root 7620: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 7621: { \
1.1.1.6 root 7622: if (unlikely(!ctx->spe_enabled)) { \
7623: gen_exception(ctx, POWERPC_EXCP_APU); \
7624: return; \
7625: } \
7626: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7627: cpu_gpr[rB(ctx->opcode)]); \
1.1 root 7628: }
1.1.1.6 root 7629: #define GEN_SPEFPUOP_COMP_32(name) \
1.1.1.8 root 7630: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7631: { \
7632: TCGv_i32 t0, t1; \
7633: if (unlikely(!ctx->spe_enabled)) { \
7634: gen_exception(ctx, POWERPC_EXCP_APU); \
7635: return; \
7636: } \
7637: t0 = tcg_temp_new_i32(); \
7638: t1 = tcg_temp_new_i32(); \
7639: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7640: tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7641: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7642: tcg_temp_free_i32(t0); \
7643: tcg_temp_free_i32(t1); \
7644: }
7645: #define GEN_SPEFPUOP_COMP_64(name) \
1.1.1.8 root 7646: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7647: { \
7648: if (unlikely(!ctx->spe_enabled)) { \
7649: gen_exception(ctx, POWERPC_EXCP_APU); \
7650: return; \
7651: } \
7652: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7653: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7654: }
7655: #else
7656: #define GEN_SPEFPUOP_CONV_32_32(name) \
1.1.1.8 root 7657: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7658: { \
7659: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7660: }
7661: #define GEN_SPEFPUOP_CONV_32_64(name) \
1.1.1.8 root 7662: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7663: { \
7664: TCGv_i64 t0 = tcg_temp_new_i64(); \
7665: gen_load_gpr64(t0, rB(ctx->opcode)); \
7666: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7667: tcg_temp_free_i64(t0); \
7668: }
7669: #define GEN_SPEFPUOP_CONV_64_32(name) \
1.1.1.8 root 7670: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7671: { \
7672: TCGv_i64 t0 = tcg_temp_new_i64(); \
7673: gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7674: gen_store_gpr64(rD(ctx->opcode), t0); \
7675: tcg_temp_free_i64(t0); \
7676: }
7677: #define GEN_SPEFPUOP_CONV_64_64(name) \
1.1.1.8 root 7678: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7679: { \
7680: TCGv_i64 t0 = tcg_temp_new_i64(); \
7681: gen_load_gpr64(t0, rB(ctx->opcode)); \
7682: gen_helper_##name(t0, t0); \
7683: gen_store_gpr64(rD(ctx->opcode), t0); \
7684: tcg_temp_free_i64(t0); \
7685: }
7686: #define GEN_SPEFPUOP_ARITH2_32_32(name) \
1.1.1.8 root 7687: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7688: { \
7689: if (unlikely(!ctx->spe_enabled)) { \
7690: gen_exception(ctx, POWERPC_EXCP_APU); \
7691: return; \
7692: } \
7693: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \
7694: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7695: }
7696: #define GEN_SPEFPUOP_ARITH2_64_64(name) \
1.1.1.8 root 7697: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7698: { \
7699: TCGv_i64 t0, t1; \
7700: if (unlikely(!ctx->spe_enabled)) { \
7701: gen_exception(ctx, POWERPC_EXCP_APU); \
7702: return; \
7703: } \
7704: t0 = tcg_temp_new_i64(); \
7705: t1 = tcg_temp_new_i64(); \
7706: gen_load_gpr64(t0, rA(ctx->opcode)); \
7707: gen_load_gpr64(t1, rB(ctx->opcode)); \
7708: gen_helper_##name(t0, t0, t1); \
7709: gen_store_gpr64(rD(ctx->opcode), t0); \
7710: tcg_temp_free_i64(t0); \
7711: tcg_temp_free_i64(t1); \
7712: }
7713: #define GEN_SPEFPUOP_COMP_32(name) \
1.1.1.8 root 7714: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7715: { \
7716: if (unlikely(!ctx->spe_enabled)) { \
7717: gen_exception(ctx, POWERPC_EXCP_APU); \
7718: return; \
7719: } \
7720: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7721: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7722: }
7723: #define GEN_SPEFPUOP_COMP_64(name) \
1.1.1.8 root 7724: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7725: { \
7726: TCGv_i64 t0, t1; \
7727: if (unlikely(!ctx->spe_enabled)) { \
7728: gen_exception(ctx, POWERPC_EXCP_APU); \
7729: return; \
7730: } \
7731: t0 = tcg_temp_new_i64(); \
7732: t1 = tcg_temp_new_i64(); \
7733: gen_load_gpr64(t0, rA(ctx->opcode)); \
7734: gen_load_gpr64(t1, rB(ctx->opcode)); \
7735: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7736: tcg_temp_free_i64(t0); \
7737: tcg_temp_free_i64(t1); \
7738: }
7739: #endif
1.1 root 7740:
1.1.1.5 root 7741: /* Single precision floating-point vectors operations */
7742: /* Arithmetic */
1.1.1.6 root 7743: GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7744: GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7745: GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7746: GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
1.1.1.8 root 7747: static inline void gen_evfsabs(DisasContext *ctx)
1.1.1.6 root 7748: {
7749: if (unlikely(!ctx->spe_enabled)) {
7750: gen_exception(ctx, POWERPC_EXCP_APU);
7751: return;
7752: }
7753: #if defined(TARGET_PPC64)
7754: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7755: #else
7756: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7757: tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7758: #endif
7759: }
1.1.1.8 root 7760: static inline void gen_evfsnabs(DisasContext *ctx)
1.1.1.6 root 7761: {
7762: if (unlikely(!ctx->spe_enabled)) {
7763: gen_exception(ctx, POWERPC_EXCP_APU);
7764: return;
7765: }
7766: #if defined(TARGET_PPC64)
7767: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7768: #else
7769: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7770: tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7771: #endif
7772: }
1.1.1.8 root 7773: static inline void gen_evfsneg(DisasContext *ctx)
1.1.1.6 root 7774: {
7775: if (unlikely(!ctx->spe_enabled)) {
7776: gen_exception(ctx, POWERPC_EXCP_APU);
7777: return;
7778: }
7779: #if defined(TARGET_PPC64)
7780: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7781: #else
7782: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7783: tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7784: #endif
7785: }
7786:
1.1.1.5 root 7787: /* Conversion */
1.1.1.6 root 7788: GEN_SPEFPUOP_CONV_64_64(evfscfui);
7789: GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7790: GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7791: GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7792: GEN_SPEFPUOP_CONV_64_64(evfsctui);
7793: GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7794: GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7795: GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7796: GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7797: GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7798:
1.1.1.5 root 7799: /* Comparison */
1.1.1.6 root 7800: GEN_SPEFPUOP_COMP_64(evfscmpgt);
7801: GEN_SPEFPUOP_COMP_64(evfscmplt);
7802: GEN_SPEFPUOP_COMP_64(evfscmpeq);
7803: GEN_SPEFPUOP_COMP_64(evfststgt);
7804: GEN_SPEFPUOP_COMP_64(evfststlt);
7805: GEN_SPEFPUOP_COMP_64(evfststeq);
1.1.1.5 root 7806:
7807: /* Opcodes definitions */
1.1.1.6 root 7808: GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7809: GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7810: GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7811: GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7812: GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7813: GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7814: GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7815: GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7816: GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7817: GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7818: GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7819: GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7820: GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7821: GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
1.1.1.5 root 7822:
7823: /* Single precision floating-point operations */
7824: /* Arithmetic */
1.1.1.6 root 7825: GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7826: GEN_SPEFPUOP_ARITH2_32_32(efssub);
7827: GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7828: GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
1.1.1.8 root 7829: static inline void gen_efsabs(DisasContext *ctx)
1.1.1.6 root 7830: {
7831: if (unlikely(!ctx->spe_enabled)) {
7832: gen_exception(ctx, POWERPC_EXCP_APU);
7833: return;
7834: }
7835: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7836: }
1.1.1.8 root 7837: static inline void gen_efsnabs(DisasContext *ctx)
1.1.1.6 root 7838: {
7839: if (unlikely(!ctx->spe_enabled)) {
7840: gen_exception(ctx, POWERPC_EXCP_APU);
7841: return;
7842: }
7843: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7844: }
1.1.1.8 root 7845: static inline void gen_efsneg(DisasContext *ctx)
1.1.1.6 root 7846: {
7847: if (unlikely(!ctx->spe_enabled)) {
7848: gen_exception(ctx, POWERPC_EXCP_APU);
7849: return;
7850: }
7851: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7852: }
7853:
1.1.1.5 root 7854: /* Conversion */
1.1.1.6 root 7855: GEN_SPEFPUOP_CONV_32_32(efscfui);
7856: GEN_SPEFPUOP_CONV_32_32(efscfsi);
7857: GEN_SPEFPUOP_CONV_32_32(efscfuf);
7858: GEN_SPEFPUOP_CONV_32_32(efscfsf);
7859: GEN_SPEFPUOP_CONV_32_32(efsctui);
7860: GEN_SPEFPUOP_CONV_32_32(efsctsi);
7861: GEN_SPEFPUOP_CONV_32_32(efsctuf);
7862: GEN_SPEFPUOP_CONV_32_32(efsctsf);
7863: GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7864: GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7865: GEN_SPEFPUOP_CONV_32_64(efscfd);
7866:
1.1.1.5 root 7867: /* Comparison */
1.1.1.6 root 7868: GEN_SPEFPUOP_COMP_32(efscmpgt);
7869: GEN_SPEFPUOP_COMP_32(efscmplt);
7870: GEN_SPEFPUOP_COMP_32(efscmpeq);
7871: GEN_SPEFPUOP_COMP_32(efststgt);
7872: GEN_SPEFPUOP_COMP_32(efststlt);
7873: GEN_SPEFPUOP_COMP_32(efststeq);
1.1.1.5 root 7874:
7875: /* Opcodes definitions */
1.1.1.6 root 7876: GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7877: GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7878: GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7879: GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7880: GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7881: GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7882: GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7883: GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7884: GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7885: GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7886: GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7887: GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7888: GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7889: GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
1.1.1.5 root 7890:
7891: /* Double precision floating-point operations */
7892: /* Arithmetic */
1.1.1.6 root 7893: GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7894: GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7895: GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7896: GEN_SPEFPUOP_ARITH2_64_64(efddiv);
1.1.1.8 root 7897: static inline void gen_efdabs(DisasContext *ctx)
1.1.1.6 root 7898: {
7899: if (unlikely(!ctx->spe_enabled)) {
7900: gen_exception(ctx, POWERPC_EXCP_APU);
7901: return;
7902: }
7903: #if defined(TARGET_PPC64)
7904: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7905: #else
7906: tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7907: #endif
7908: }
1.1.1.8 root 7909: static inline void gen_efdnabs(DisasContext *ctx)
1.1.1.6 root 7910: {
7911: if (unlikely(!ctx->spe_enabled)) {
7912: gen_exception(ctx, POWERPC_EXCP_APU);
7913: return;
7914: }
7915: #if defined(TARGET_PPC64)
7916: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7917: #else
7918: tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7919: #endif
7920: }
1.1.1.8 root 7921: static inline void gen_efdneg(DisasContext *ctx)
1.1.1.6 root 7922: {
7923: if (unlikely(!ctx->spe_enabled)) {
7924: gen_exception(ctx, POWERPC_EXCP_APU);
7925: return;
7926: }
7927: #if defined(TARGET_PPC64)
7928: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7929: #else
7930: tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7931: #endif
7932: }
7933:
1.1.1.5 root 7934: /* Conversion */
1.1.1.6 root 7935: GEN_SPEFPUOP_CONV_64_32(efdcfui);
7936: GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7937: GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7938: GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7939: GEN_SPEFPUOP_CONV_32_64(efdctui);
7940: GEN_SPEFPUOP_CONV_32_64(efdctsi);
7941: GEN_SPEFPUOP_CONV_32_64(efdctuf);
7942: GEN_SPEFPUOP_CONV_32_64(efdctsf);
7943: GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7944: GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7945: GEN_SPEFPUOP_CONV_64_32(efdcfs);
7946: GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7947: GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7948: GEN_SPEFPUOP_CONV_64_64(efdctuidz);
7949: GEN_SPEFPUOP_CONV_64_64(efdctsidz);
1.1.1.5 root 7950:
7951: /* Comparison */
1.1.1.6 root 7952: GEN_SPEFPUOP_COMP_64(efdcmpgt);
7953: GEN_SPEFPUOP_COMP_64(efdcmplt);
7954: GEN_SPEFPUOP_COMP_64(efdcmpeq);
7955: GEN_SPEFPUOP_COMP_64(efdtstgt);
7956: GEN_SPEFPUOP_COMP_64(efdtstlt);
7957: GEN_SPEFPUOP_COMP_64(efdtsteq);
1.1.1.5 root 7958:
7959: /* Opcodes definitions */
1.1.1.6 root 7960: GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
7961: GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7962: GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
7963: GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
7964: GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
7965: GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7966: GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7967: GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7968: GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7969: GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7970: GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7971: GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7972: GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7973: GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7974: GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7975: GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
1.1.1.5 root 7976:
1.1.1.7 root 7977: static opcode_t opcodes[] = {
7978: GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
7979: GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
7980: GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
7981: GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
7982: GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
7983: GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
7984: GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7985: GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7986: GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7987: GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7988: GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
7989: GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
7990: GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
7991: GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
7992: GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7993: #if defined(TARGET_PPC64)
7994: GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
7995: #endif
7996: GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
7997: GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
7998: GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7999: GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8000: GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8001: GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
8002: GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
8003: GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
8004: GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8005: GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8006: GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8007: GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8008: GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
8009: #if defined(TARGET_PPC64)
8010: GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
8011: #endif
8012: GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8013: GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8014: GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8015: GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
8016: GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
8017: GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
8018: GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
8019: #if defined(TARGET_PPC64)
8020: GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
8021: GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
8022: GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
8023: GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
8024: GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
8025: #endif
8026: GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
8027: GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8028: GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8029: GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
8030: GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
8031: GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
8032: GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
8033: GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
8034: GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
8035: GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
8036: GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
8037: GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
8038: #if defined(TARGET_PPC64)
8039: GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
8040: GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
8041: GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
8042: #endif
8043: GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8044: GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8045: GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
8046: GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
8047: GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
8048: GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
8049: GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
8050: GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
8051: GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES),
8052: GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
8053: #if defined(TARGET_PPC64)
8054: GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B),
8055: GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
8056: #endif
8057: GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
8058: GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
8059: GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8060: GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8061: GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
8062: GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
8063: GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
8064: GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
8065: #if defined(TARGET_PPC64)
8066: GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
8067: GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
8068: #endif
8069: GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
8070: GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
8071: GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8072: #if defined(TARGET_PPC64)
8073: GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
8074: GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
8075: #endif
8076: GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
8077: GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
8078: GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
8079: GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
8080: GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
8081: GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
8082: #if defined(TARGET_PPC64)
8083: GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
8084: #endif
8085: GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
8086: GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC),
8087: GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
8088: GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
8089: GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
8090: GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE),
8091: GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE),
8092: GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ),
8093: GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT),
8094: GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
8095: GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
8096: GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
8097: GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
8098: GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
8099: GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
8100: GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
8101: GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
8102: GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
8103: #if defined(TARGET_PPC64)
8104: GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
8105: GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
8106: PPC_SEGMENT_64B),
8107: GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
8108: GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
8109: PPC_SEGMENT_64B),
8110: GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B),
8111: #endif
8112: GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
8113: GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
8114: GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
8115: GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
8116: #if defined(TARGET_PPC64)
8117: GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
8118: GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
8119: #endif
8120: GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
8121: GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
8122: GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
8123: GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
8124: GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
8125: GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
8126: GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
8127: GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
8128: GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
8129: GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
8130: GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
8131: GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8132: GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
8133: GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
8134: GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
8135: GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
8136: GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
8137: GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
8138: GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
8139: GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8140: GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
8141: GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
8142: GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
8143: GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
8144: GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
8145: GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
8146: GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
8147: GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
8148: GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
8149: GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
8150: GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
8151: GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
8152: GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
8153: GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
8154: GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
8155: GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
8156: GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
8157: GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
8158: GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
8159: GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
8160: GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
8161: GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
8162: GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
8163: GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
8164: GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
8165: GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
8166: GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
8167: GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
8168: GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
8169: GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8170: GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8171: GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
8172: GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
8173: GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8174: GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8175: GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
8176: GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
8177: GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
8178: GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
8179: GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
8180: GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
8181: GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
8182: GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
8183: GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
8184: GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
8185: GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
8186: GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
8187: GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
8188: GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
8189: GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
8190: GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
8191: GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE),
8192: GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
8193: GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
8194: GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
8195: GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
8196: GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
8197: GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
8198: GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
8199: GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
8200: GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8201: GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8202: GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
8203: GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE),
8204: GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
8205: GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE),
8206: GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
8207: GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
8208: GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
8209: GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
8210: GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC),
8211: GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
8212: GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
8213: GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
8214: GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
8215: GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
8216:
8217: #undef GEN_INT_ARITH_ADD
8218: #undef GEN_INT_ARITH_ADD_CONST
8219: #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
8220: GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
8221: #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
8222: add_ca, compute_ca, compute_ov) \
8223: GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
8224: GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
8225: GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
8226: GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
8227: GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
8228: GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
8229: GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
8230: GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
8231: GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
8232: GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
8233: GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
8234:
8235: #undef GEN_INT_ARITH_DIVW
8236: #define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
8237: GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
8238: GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
8239: GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
8240: GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
8241: GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
8242:
8243: #if defined(TARGET_PPC64)
8244: #undef GEN_INT_ARITH_DIVD
8245: #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
8246: GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8247: GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
8248: GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
8249: GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
8250: GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
8251:
8252: #undef GEN_INT_ARITH_MUL_HELPER
8253: #define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
8254: GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8255: GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
8256: GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
8257: GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
8258: #endif
8259:
8260: #undef GEN_INT_ARITH_SUBF
8261: #undef GEN_INT_ARITH_SUBF_CONST
8262: #define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
8263: GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
8264: #define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
8265: add_ca, compute_ca, compute_ov) \
8266: GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
8267: GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
8268: GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
8269: GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
8270: GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
8271: GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
8272: GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
8273: GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
8274: GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
8275: GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
8276: GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
8277:
8278: #undef GEN_LOGICAL1
8279: #undef GEN_LOGICAL2
8280: #define GEN_LOGICAL2(name, tcg_op, opc, type) \
8281: GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
8282: #define GEN_LOGICAL1(name, tcg_op, opc, type) \
8283: GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
8284: GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
8285: GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
8286: GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
8287: GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
8288: GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
8289: GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
8290: GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
8291: GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
8292: #if defined(TARGET_PPC64)
8293: GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
8294: #endif
8295:
8296: #if defined(TARGET_PPC64)
8297: #undef GEN_PPC64_R2
8298: #undef GEN_PPC64_R4
8299: #define GEN_PPC64_R2(name, opc1, opc2) \
8300: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8301: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8302: PPC_64B)
8303: #define GEN_PPC64_R4(name, opc1, opc2) \
8304: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8305: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
8306: PPC_64B), \
8307: GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8308: PPC_64B), \
8309: GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
8310: PPC_64B)
8311: GEN_PPC64_R4(rldicl, 0x1E, 0x00),
8312: GEN_PPC64_R4(rldicr, 0x1E, 0x02),
8313: GEN_PPC64_R4(rldic, 0x1E, 0x04),
8314: GEN_PPC64_R2(rldcl, 0x1E, 0x08),
8315: GEN_PPC64_R2(rldcr, 0x1E, 0x09),
8316: GEN_PPC64_R4(rldimi, 0x1E, 0x06),
8317: #endif
8318:
8319: #undef _GEN_FLOAT_ACB
8320: #undef GEN_FLOAT_ACB
8321: #undef _GEN_FLOAT_AB
8322: #undef GEN_FLOAT_AB
8323: #undef _GEN_FLOAT_AC
8324: #undef GEN_FLOAT_AC
8325: #undef GEN_FLOAT_B
8326: #undef GEN_FLOAT_BS
8327: #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
8328: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
8329: #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
8330: _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type), \
8331: _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
8332: #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8333: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8334: #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
8335: _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8336: _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8337: #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8338: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8339: #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
8340: _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8341: _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8342: #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
8343: GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
8344: #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
8345: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
8346:
8347: GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
8348: GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
8349: GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
8350: GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
8351: GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
8352: GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
8353: _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
8354: GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
8355: GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
8356: GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
8357: GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
8358: GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
8359: GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
8360: GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
8361: GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
8362: #if defined(TARGET_PPC64)
8363: GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
8364: GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
8365: GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
8366: #endif
8367: GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
8368: GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
8369: GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
8370: GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
8371: GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT),
8372: GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT),
8373: GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
8374:
8375: #undef GEN_LD
8376: #undef GEN_LDU
8377: #undef GEN_LDUX
8378: #undef GEN_LDX
8379: #undef GEN_LDS
8380: #define GEN_LD(name, ldop, opc, type) \
8381: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8382: #define GEN_LDU(name, ldop, opc, type) \
8383: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8384: #define GEN_LDUX(name, ldop, opc2, opc3, type) \
8385: GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8386: #define GEN_LDX(name, ldop, opc2, opc3, type) \
8387: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8388: #define GEN_LDS(name, ldop, op, type) \
8389: GEN_LD(name, ldop, op | 0x20, type) \
8390: GEN_LDU(name, ldop, op | 0x21, type) \
8391: GEN_LDUX(name, ldop, 0x17, op | 0x01, type) \
8392: GEN_LDX(name, ldop, 0x17, op | 0x00, type)
8393:
8394: GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
8395: GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
8396: GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
8397: GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
8398: #if defined(TARGET_PPC64)
8399: GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
8400: GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
8401: GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
8402: GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
8403: #endif
8404: GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
8405: GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
8406:
8407: #undef GEN_ST
8408: #undef GEN_STU
8409: #undef GEN_STUX
8410: #undef GEN_STX
8411: #undef GEN_STS
8412: #define GEN_ST(name, stop, opc, type) \
8413: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8414: #define GEN_STU(name, stop, opc, type) \
8415: GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
8416: #define GEN_STUX(name, stop, opc2, opc3, type) \
8417: GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8418: #define GEN_STX(name, stop, opc2, opc3, type) \
8419: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8420: #define GEN_STS(name, stop, op, type) \
8421: GEN_ST(name, stop, op | 0x20, type) \
8422: GEN_STU(name, stop, op | 0x21, type) \
8423: GEN_STUX(name, stop, 0x17, op | 0x01, type) \
8424: GEN_STX(name, stop, 0x17, op | 0x00, type)
8425:
8426: GEN_STS(stb, st8, 0x06, PPC_INTEGER)
8427: GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
8428: GEN_STS(stw, st32, 0x04, PPC_INTEGER)
8429: #if defined(TARGET_PPC64)
8430: GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
8431: GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
8432: #endif
8433: GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
8434: GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
8435:
8436: #undef GEN_LDF
8437: #undef GEN_LDUF
8438: #undef GEN_LDUXF
8439: #undef GEN_LDXF
8440: #undef GEN_LDFS
8441: #define GEN_LDF(name, ldop, opc, type) \
8442: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8443: #define GEN_LDUF(name, ldop, opc, type) \
8444: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8445: #define GEN_LDUXF(name, ldop, opc, type) \
8446: GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8447: #define GEN_LDXF(name, ldop, opc2, opc3, type) \
8448: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8449: #define GEN_LDFS(name, ldop, op, type) \
8450: GEN_LDF(name, ldop, op | 0x20, type) \
8451: GEN_LDUF(name, ldop, op | 0x21, type) \
8452: GEN_LDUXF(name, ldop, op | 0x01, type) \
8453: GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
8454:
8455: GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
8456: GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
8457:
8458: #undef GEN_STF
8459: #undef GEN_STUF
8460: #undef GEN_STUXF
8461: #undef GEN_STXF
8462: #undef GEN_STFS
8463: #define GEN_STF(name, stop, opc, type) \
8464: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8465: #define GEN_STUF(name, stop, opc, type) \
8466: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8467: #define GEN_STUXF(name, stop, opc, type) \
8468: GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8469: #define GEN_STXF(name, stop, opc2, opc3, type) \
8470: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8471: #define GEN_STFS(name, stop, op, type) \
8472: GEN_STF(name, stop, op | 0x20, type) \
8473: GEN_STUF(name, stop, op | 0x21, type) \
8474: GEN_STUXF(name, stop, op | 0x01, type) \
8475: GEN_STXF(name, stop, 0x17, op | 0x00, type)
8476:
8477: GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
8478: GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
8479: GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
8480:
8481: #undef GEN_CRLOGIC
8482: #define GEN_CRLOGIC(name, tcg_op, opc) \
8483: GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
8484: GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
8485: GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
8486: GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
8487: GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
8488: GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
8489: GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
8490: GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
8491: GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
8492:
8493: #undef GEN_MAC_HANDLER
8494: #define GEN_MAC_HANDLER(name, opc2, opc3) \
8495: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
8496: GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
8497: GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
8498: GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
8499: GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
8500: GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
8501: GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
8502: GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
8503: GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
8504: GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
8505: GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
8506: GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
8507: GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
8508: GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
8509: GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
8510: GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
8511: GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
8512: GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
8513: GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
8514: GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
8515: GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
8516: GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
8517: GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
8518: GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
8519: GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
8520: GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
8521: GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
8522: GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
8523: GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
8524: GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
8525: GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
8526: GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
8527: GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
8528: GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
8529: GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
8530: GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
8531: GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
8532: GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
8533: GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
8534: GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
8535: GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
8536: GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
8537: GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
8538:
8539: #undef GEN_VR_LDX
8540: #undef GEN_VR_STX
8541: #undef GEN_VR_LVE
8542: #undef GEN_VR_STVE
8543: #define GEN_VR_LDX(name, opc2, opc3) \
8544: GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8545: #define GEN_VR_STX(name, opc2, opc3) \
8546: GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8547: #define GEN_VR_LVE(name, opc2, opc3) \
8548: GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8549: #define GEN_VR_STVE(name, opc2, opc3) \
8550: GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8551: GEN_VR_LDX(lvx, 0x07, 0x03),
8552: GEN_VR_LDX(lvxl, 0x07, 0x0B),
8553: GEN_VR_LVE(bx, 0x07, 0x00),
8554: GEN_VR_LVE(hx, 0x07, 0x01),
8555: GEN_VR_LVE(wx, 0x07, 0x02),
8556: GEN_VR_STX(svx, 0x07, 0x07),
8557: GEN_VR_STX(svxl, 0x07, 0x0F),
8558: GEN_VR_STVE(bx, 0x07, 0x04),
8559: GEN_VR_STVE(hx, 0x07, 0x05),
8560: GEN_VR_STVE(wx, 0x07, 0x06),
8561:
8562: #undef GEN_VX_LOGICAL
8563: #define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
8564: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8565: GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
8566: GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
8567: GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
8568: GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
8569: GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
8570:
8571: #undef GEN_VXFORM
8572: #define GEN_VXFORM(name, opc2, opc3) \
8573: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8574: GEN_VXFORM(vaddubm, 0, 0),
8575: GEN_VXFORM(vadduhm, 0, 1),
8576: GEN_VXFORM(vadduwm, 0, 2),
8577: GEN_VXFORM(vsububm, 0, 16),
8578: GEN_VXFORM(vsubuhm, 0, 17),
8579: GEN_VXFORM(vsubuwm, 0, 18),
8580: GEN_VXFORM(vmaxub, 1, 0),
8581: GEN_VXFORM(vmaxuh, 1, 1),
8582: GEN_VXFORM(vmaxuw, 1, 2),
8583: GEN_VXFORM(vmaxsb, 1, 4),
8584: GEN_VXFORM(vmaxsh, 1, 5),
8585: GEN_VXFORM(vmaxsw, 1, 6),
8586: GEN_VXFORM(vminub, 1, 8),
8587: GEN_VXFORM(vminuh, 1, 9),
8588: GEN_VXFORM(vminuw, 1, 10),
8589: GEN_VXFORM(vminsb, 1, 12),
8590: GEN_VXFORM(vminsh, 1, 13),
8591: GEN_VXFORM(vminsw, 1, 14),
8592: GEN_VXFORM(vavgub, 1, 16),
8593: GEN_VXFORM(vavguh, 1, 17),
8594: GEN_VXFORM(vavguw, 1, 18),
8595: GEN_VXFORM(vavgsb, 1, 20),
8596: GEN_VXFORM(vavgsh, 1, 21),
8597: GEN_VXFORM(vavgsw, 1, 22),
8598: GEN_VXFORM(vmrghb, 6, 0),
8599: GEN_VXFORM(vmrghh, 6, 1),
8600: GEN_VXFORM(vmrghw, 6, 2),
8601: GEN_VXFORM(vmrglb, 6, 4),
8602: GEN_VXFORM(vmrglh, 6, 5),
8603: GEN_VXFORM(vmrglw, 6, 6),
8604: GEN_VXFORM(vmuloub, 4, 0),
8605: GEN_VXFORM(vmulouh, 4, 1),
8606: GEN_VXFORM(vmulosb, 4, 4),
8607: GEN_VXFORM(vmulosh, 4, 5),
8608: GEN_VXFORM(vmuleub, 4, 8),
8609: GEN_VXFORM(vmuleuh, 4, 9),
8610: GEN_VXFORM(vmulesb, 4, 12),
8611: GEN_VXFORM(vmulesh, 4, 13),
8612: GEN_VXFORM(vslb, 2, 4),
8613: GEN_VXFORM(vslh, 2, 5),
8614: GEN_VXFORM(vslw, 2, 6),
8615: GEN_VXFORM(vsrb, 2, 8),
8616: GEN_VXFORM(vsrh, 2, 9),
8617: GEN_VXFORM(vsrw, 2, 10),
8618: GEN_VXFORM(vsrab, 2, 12),
8619: GEN_VXFORM(vsrah, 2, 13),
8620: GEN_VXFORM(vsraw, 2, 14),
8621: GEN_VXFORM(vslo, 6, 16),
8622: GEN_VXFORM(vsro, 6, 17),
8623: GEN_VXFORM(vaddcuw, 0, 6),
8624: GEN_VXFORM(vsubcuw, 0, 22),
8625: GEN_VXFORM(vaddubs, 0, 8),
8626: GEN_VXFORM(vadduhs, 0, 9),
8627: GEN_VXFORM(vadduws, 0, 10),
8628: GEN_VXFORM(vaddsbs, 0, 12),
8629: GEN_VXFORM(vaddshs, 0, 13),
8630: GEN_VXFORM(vaddsws, 0, 14),
8631: GEN_VXFORM(vsububs, 0, 24),
8632: GEN_VXFORM(vsubuhs, 0, 25),
8633: GEN_VXFORM(vsubuws, 0, 26),
8634: GEN_VXFORM(vsubsbs, 0, 28),
8635: GEN_VXFORM(vsubshs, 0, 29),
8636: GEN_VXFORM(vsubsws, 0, 30),
8637: GEN_VXFORM(vrlb, 2, 0),
8638: GEN_VXFORM(vrlh, 2, 1),
8639: GEN_VXFORM(vrlw, 2, 2),
8640: GEN_VXFORM(vsl, 2, 7),
8641: GEN_VXFORM(vsr, 2, 11),
8642: GEN_VXFORM(vpkuhum, 7, 0),
8643: GEN_VXFORM(vpkuwum, 7, 1),
8644: GEN_VXFORM(vpkuhus, 7, 2),
8645: GEN_VXFORM(vpkuwus, 7, 3),
8646: GEN_VXFORM(vpkshus, 7, 4),
8647: GEN_VXFORM(vpkswus, 7, 5),
8648: GEN_VXFORM(vpkshss, 7, 6),
8649: GEN_VXFORM(vpkswss, 7, 7),
8650: GEN_VXFORM(vpkpx, 7, 12),
8651: GEN_VXFORM(vsum4ubs, 4, 24),
8652: GEN_VXFORM(vsum4sbs, 4, 28),
8653: GEN_VXFORM(vsum4shs, 4, 25),
8654: GEN_VXFORM(vsum2sws, 4, 26),
8655: GEN_VXFORM(vsumsws, 4, 30),
8656: GEN_VXFORM(vaddfp, 5, 0),
8657: GEN_VXFORM(vsubfp, 5, 1),
8658: GEN_VXFORM(vmaxfp, 5, 16),
8659: GEN_VXFORM(vminfp, 5, 17),
8660:
8661: #undef GEN_VXRFORM1
8662: #undef GEN_VXRFORM
8663: #define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
8664: GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
8665: #define GEN_VXRFORM(name, opc2, opc3) \
8666: GEN_VXRFORM1(name, name, #name, opc2, opc3) \
8667: GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
8668: GEN_VXRFORM(vcmpequb, 3, 0)
8669: GEN_VXRFORM(vcmpequh, 3, 1)
8670: GEN_VXRFORM(vcmpequw, 3, 2)
8671: GEN_VXRFORM(vcmpgtsb, 3, 12)
8672: GEN_VXRFORM(vcmpgtsh, 3, 13)
8673: GEN_VXRFORM(vcmpgtsw, 3, 14)
8674: GEN_VXRFORM(vcmpgtub, 3, 8)
8675: GEN_VXRFORM(vcmpgtuh, 3, 9)
8676: GEN_VXRFORM(vcmpgtuw, 3, 10)
8677: GEN_VXRFORM(vcmpeqfp, 3, 3)
8678: GEN_VXRFORM(vcmpgefp, 3, 7)
8679: GEN_VXRFORM(vcmpgtfp, 3, 11)
8680: GEN_VXRFORM(vcmpbfp, 3, 15)
8681:
8682: #undef GEN_VXFORM_SIMM
8683: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
8684: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8685: GEN_VXFORM_SIMM(vspltisb, 6, 12),
8686: GEN_VXFORM_SIMM(vspltish, 6, 13),
8687: GEN_VXFORM_SIMM(vspltisw, 6, 14),
8688:
8689: #undef GEN_VXFORM_NOA
8690: #define GEN_VXFORM_NOA(name, opc2, opc3) \
8691: GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
8692: GEN_VXFORM_NOA(vupkhsb, 7, 8),
8693: GEN_VXFORM_NOA(vupkhsh, 7, 9),
8694: GEN_VXFORM_NOA(vupklsb, 7, 10),
8695: GEN_VXFORM_NOA(vupklsh, 7, 11),
8696: GEN_VXFORM_NOA(vupkhpx, 7, 13),
8697: GEN_VXFORM_NOA(vupklpx, 7, 15),
8698: GEN_VXFORM_NOA(vrefp, 5, 4),
8699: GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
1.1.1.9 ! root 8700: GEN_VXFORM_NOA(vexptefp, 5, 6),
1.1.1.7 root 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: "
1.1.1.9 ! root 8923: "%016" PRIx64 " %" PRId64 "\n",
1.1.1.5 root 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: "
1.1.1.9 ! root 8932: "%016" PRIx64 " %" PRId64 "\n",
1.1.1.5 root 8933: op1, op2, op1, op2, handler->oname,
8934: handler->count, handler->count);
8935: }
8936: }
8937: } else {
8938: if (handler->count == 0)
8939: continue;
1.1.1.9 ! root 8940: cpu_fprintf(f, "%02x (%02x ) %16s: %016" PRIx64
! 8941: " %" PRId64 "\n",
1.1.1.5 root 8942: op1, op1, handler->oname,
8943: handler->count, handler->count);
8944: }
8945: }
8946: #endif
1.1 root 8947: }
8948:
8949: /*****************************************************************************/
1.1.1.8 root 8950: static inline void gen_intermediate_code_internal(CPUState *env,
8951: TranslationBlock *tb,
8952: int search_pc)
1.1 root 8953: {
8954: DisasContext ctx, *ctxp = &ctx;
8955: opc_handler_t **table, *handler;
8956: target_ulong pc_start;
8957: uint16_t *gen_opc_end;
1.1.1.6 root 8958: CPUBreakpoint *bp;
1.1 root 8959: int j, lj = -1;
1.1.1.6 root 8960: int num_insns;
8961: int max_insns;
1.1 root 8962:
8963: pc_start = tb->pc;
8964: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8965: ctx.nip = pc_start;
8966: ctx.tb = tb;
1.1.1.5 root 8967: ctx.exception = POWERPC_EXCP_NONE;
1.1 root 8968: ctx.spr_cb = env->spr_cb;
1.1.1.6 root 8969: ctx.mem_idx = env->mmu_idx;
8970: ctx.access_type = -1;
8971: ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
1.1.1.5 root 8972: #if defined(TARGET_PPC64)
8973: ctx.sf_mode = msr_sf;
1.1 root 8974: #endif
8975: ctx.fpu_enabled = msr_fp;
1.1.1.5 root 8976: if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
8977: ctx.spe_enabled = msr_spe;
8978: else
8979: ctx.spe_enabled = 0;
8980: if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
8981: ctx.altivec_enabled = msr_vr;
8982: else
8983: ctx.altivec_enabled = 0;
8984: if ((env->flags & POWERPC_FLAG_SE) && msr_se)
1.1.1.6 root 8985: ctx.singlestep_enabled = CPU_SINGLE_STEP;
1.1.1.5 root 8986: else
1.1.1.6 root 8987: ctx.singlestep_enabled = 0;
1.1.1.5 root 8988: if ((env->flags & POWERPC_FLAG_BE) && msr_be)
1.1.1.6 root 8989: ctx.singlestep_enabled |= CPU_BRANCH_STEP;
8990: if (unlikely(env->singlestep_enabled))
8991: ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
1.1 root 8992: #if defined (DO_SINGLE_STEP) && 0
8993: /* Single step trace mode */
8994: msr_se = 1;
8995: #endif
1.1.1.6 root 8996: num_insns = 0;
8997: max_insns = tb->cflags & CF_COUNT_MASK;
8998: if (max_insns == 0)
8999: max_insns = CF_COUNT_MASK;
9000:
9001: gen_icount_start();
1.1 root 9002: /* Set env in case of segfault during code fetch */
1.1.1.5 root 9003: while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
1.1.1.8 root 9004: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9005: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.6 root 9006: if (bp->pc == ctx.nip) {
9007: gen_debug_exception(ctxp);
1.1.1.3 root 9008: break;
9009: }
9010: }
9011: }
1.1.1.5 root 9012: if (unlikely(search_pc)) {
1.1 root 9013: j = gen_opc_ptr - gen_opc_buf;
9014: if (lj < j) {
9015: lj++;
9016: while (lj < j)
9017: gen_opc_instr_start[lj++] = 0;
9018: }
1.1.1.7 root 9019: gen_opc_pc[lj] = ctx.nip;
9020: gen_opc_instr_start[lj] = 1;
9021: gen_opc_icount[lj] = num_insns;
1.1 root 9022: }
1.1.1.6 root 9023: LOG_DISAS("----------------\n");
1.1.1.8 root 9024: LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
1.1.1.6 root 9025: ctx.nip, ctx.mem_idx, (int)msr_ir);
9026: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9027: gen_io_start();
9028: if (unlikely(ctx.le_mode)) {
1.1.1.5 root 9029: ctx.opcode = bswap32(ldl_code(ctx.nip));
9030: } else {
9031: ctx.opcode = ldl_code(ctx.nip);
1.1 root 9032: }
1.1.1.6 root 9033: LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
1.1 root 9034: ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
1.1.1.5 root 9035: opc3(ctx.opcode), little_endian ? "little" : "big");
1.1.1.8 root 9036: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
9037: tcg_gen_debug_insn_start(ctx.nip);
1.1 root 9038: ctx.nip += 4;
9039: table = env->opcodes;
1.1.1.6 root 9040: num_insns++;
1.1 root 9041: handler = table[opc1(ctx.opcode)];
9042: if (is_indirect_opcode(handler)) {
9043: table = ind_table(handler);
9044: handler = table[opc2(ctx.opcode)];
9045: if (is_indirect_opcode(handler)) {
9046: table = ind_table(handler);
9047: handler = table[opc3(ctx.opcode)];
9048: }
9049: }
9050: /* Is opcode *REALLY* valid ? */
1.1.1.5 root 9051: if (unlikely(handler->handler == &gen_invalid)) {
1.1.1.6 root 9052: if (qemu_log_enabled()) {
9053: qemu_log("invalid/unsupported opcode: "
1.1.1.8 root 9054: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
9055: opc1(ctx.opcode), opc2(ctx.opcode),
9056: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
1.1 root 9057: }
1.1.1.5 root 9058: } else {
9059: if (unlikely((ctx.opcode & handler->inval) != 0)) {
1.1.1.6 root 9060: if (qemu_log_enabled()) {
9061: qemu_log("invalid bits: %08x for opcode: "
1.1.1.8 root 9062: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9063: ctx.opcode & handler->inval, opc1(ctx.opcode),
9064: opc2(ctx.opcode), opc3(ctx.opcode),
9065: ctx.opcode, ctx.nip - 4);
1.1.1.5 root 9066: }
1.1.1.6 root 9067: gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
1.1 root 9068: break;
9069: }
9070: }
9071: (*(handler->handler))(&ctx);
1.1.1.5 root 9072: #if defined(DO_PPC_STATISTICS)
9073: handler->count++;
9074: #endif
1.1 root 9075: /* Check trace mode exceptions */
1.1.1.6 root 9076: if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
9077: (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
9078: ctx.exception != POWERPC_SYSCALL &&
9079: ctx.exception != POWERPC_EXCP_TRAP &&
9080: ctx.exception != POWERPC_EXCP_BRANCH)) {
9081: gen_exception(ctxp, POWERPC_EXCP_TRACE);
1.1.1.5 root 9082: } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
1.1.1.6 root 9083: (env->singlestep_enabled) ||
1.1.1.7 root 9084: singlestep ||
1.1.1.6 root 9085: num_insns >= max_insns)) {
1.1.1.5 root 9086: /* if we reach a page boundary or are single stepping, stop
9087: * generation
1.1 root 9088: */
9089: break;
1.1.1.5 root 9090: }
1.1 root 9091: }
1.1.1.6 root 9092: if (tb->cflags & CF_LAST_IO)
9093: gen_io_end();
1.1.1.5 root 9094: if (ctx.exception == POWERPC_EXCP_NONE) {
1.1.1.2 root 9095: gen_goto_tb(&ctx, 0, ctx.nip);
1.1.1.5 root 9096: } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
1.1.1.6 root 9097: if (unlikely(env->singlestep_enabled)) {
9098: gen_debug_exception(ctxp);
9099: }
1.1.1.5 root 9100: /* Generate the return instruction */
1.1.1.6 root 9101: tcg_gen_exit_tb(0);
1.1 root 9102: }
1.1.1.6 root 9103: gen_icount_end(tb, num_insns);
1.1 root 9104: *gen_opc_ptr = INDEX_op_end;
1.1.1.5 root 9105: if (unlikely(search_pc)) {
1.1 root 9106: j = gen_opc_ptr - gen_opc_buf;
9107: lj++;
9108: while (lj <= j)
9109: gen_opc_instr_start[lj++] = 0;
9110: } else {
9111: tb->size = ctx.nip - pc_start;
1.1.1.6 root 9112: tb->icount = num_insns;
1.1 root 9113: }
1.1.1.5 root 9114: #if defined(DEBUG_DISAS)
1.1.1.6 root 9115: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1.1.1.5 root 9116: int flags;
9117: flags = env->bfd_mach;
1.1.1.6 root 9118: flags |= ctx.le_mode << 16;
9119: qemu_log("IN: %s\n", lookup_symbol(pc_start));
9120: log_target_disas(pc_start, ctx.nip - pc_start, flags);
9121: qemu_log("\n");
1.1 root 9122: }
9123: #endif
9124: }
9125:
1.1.1.6 root 9126: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
9127: {
9128: gen_intermediate_code_internal(env, tb, 0);
9129: }
9130:
9131: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 9132: {
1.1.1.6 root 9133: gen_intermediate_code_internal(env, tb, 1);
1.1 root 9134: }
9135:
1.1.1.6 root 9136: void gen_pc_load(CPUState *env, TranslationBlock *tb,
9137: unsigned long searched_pc, int pc_pos, void *puc)
1.1 root 9138: {
1.1.1.6 root 9139: env->nip = gen_opc_pc[pc_pos];
1.1 root 9140: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.