|
|
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.1.11 root 5: * Copyright (C) 2011 Freescale Semiconductor, Inc.
1.1 root 6: *
7: * This library is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU Lesser General Public
9: * License as published by the Free Software Foundation; either
10: * version 2 of the License, or (at your option) any later version.
11: *
12: * This library is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * Lesser General Public License for more details.
16: *
17: * You should have received a copy of the GNU Lesser General Public
1.1.1.7 root 18: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 19: */
20:
21: #include "cpu.h"
22: #include "disas.h"
1.1.1.6 root 23: #include "tcg-op.h"
24: #include "host-utils.h"
25:
26: #include "helper.h"
27: #define GEN_HELPER 1
28: #include "helper.h"
29:
30: #define CPU_SINGLE_STEP 0x1
31: #define CPU_BRANCH_STEP 0x2
32: #define GDBSTUB_SINGLE_STEP 0x4
1.1 root 33:
1.1.1.5 root 34: /* Include definitions for instructions classes and implementations flags */
1.1 root 35: //#define PPC_DEBUG_DISAS
1.1.1.5 root 36: //#define DO_PPC_STATISTICS
1.1 root 37:
1.1.1.6 root 38: #ifdef PPC_DEBUG_DISAS
39: # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
1.1.1.2 root 40: #else
1.1.1.6 root 41: # define LOG_DISAS(...) do { } while (0)
1.1.1.2 root 42: #endif
1.1.1.6 root 43: /*****************************************************************************/
44: /* Code translation helpers */
1.1.1.2 root 45:
1.1.1.6 root 46: /* global register indexes */
47: static TCGv_ptr cpu_env;
48: static char cpu_reg_names[10*3 + 22*4 /* GPR */
49: #if !defined(TARGET_PPC64)
50: + 10*4 + 22*5 /* SPE GPRh */
1.1.1.5 root 51: #endif
1.1.1.6 root 52: + 10*4 + 22*5 /* FPR */
53: + 2*(10*6 + 22*7) /* AVRh, AVRl */
54: + 8*5 /* CRF */];
55: static TCGv cpu_gpr[32];
56: #if !defined(TARGET_PPC64)
57: static TCGv cpu_gprh[32];
58: #endif
59: static TCGv_i64 cpu_fpr[32];
60: static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
61: static TCGv_i32 cpu_crf[8];
62: static TCGv cpu_nip;
63: static TCGv cpu_msr;
64: static TCGv cpu_ctr;
65: static TCGv cpu_lr;
1.1.1.12 root 66: #if defined(TARGET_PPC64)
67: static TCGv cpu_cfar;
68: #endif
1.1.1.6 root 69: static TCGv cpu_xer;
70: static TCGv cpu_reserve;
71: static TCGv_i32 cpu_fpscr;
72: static TCGv_i32 cpu_access_type;
1.1 root 73:
1.1.1.6 root 74: #include "gen-icount.h"
1.1 root 75:
1.1.1.6 root 76: void ppc_translate_init(void)
1.1.1.5 root 77: {
1.1.1.6 root 78: int i;
79: char* p;
1.1.1.7 root 80: size_t cpu_reg_names_size;
1.1.1.6 root 81: static int done_init = 0;
82:
83: if (done_init)
84: return;
85:
86: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
87:
88: p = cpu_reg_names;
1.1.1.7 root 89: cpu_reg_names_size = sizeof(cpu_reg_names);
1.1.1.6 root 90:
91: for (i = 0; i < 8; i++) {
1.1.1.7 root 92: snprintf(p, cpu_reg_names_size, "crf%d", i);
1.1.1.6 root 93: cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.13! root 94: offsetof(CPUPPCState, crf[i]), p);
1.1.1.6 root 95: p += 5;
1.1.1.7 root 96: cpu_reg_names_size -= 5;
1.1.1.6 root 97: }
98:
99: for (i = 0; i < 32; i++) {
1.1.1.7 root 100: snprintf(p, cpu_reg_names_size, "r%d", i);
1.1.1.6 root 101: cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 102: offsetof(CPUPPCState, gpr[i]), p);
1.1.1.6 root 103: p += (i < 10) ? 3 : 4;
1.1.1.7 root 104: cpu_reg_names_size -= (i < 10) ? 3 : 4;
1.1.1.6 root 105: #if !defined(TARGET_PPC64)
1.1.1.7 root 106: snprintf(p, cpu_reg_names_size, "r%dH", i);
1.1.1.6 root 107: cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.13! root 108: offsetof(CPUPPCState, gprh[i]), p);
1.1.1.6 root 109: p += (i < 10) ? 4 : 5;
1.1.1.7 root 110: cpu_reg_names_size -= (i < 10) ? 4 : 5;
1.1.1.5 root 111: #endif
112:
1.1.1.7 root 113: snprintf(p, cpu_reg_names_size, "fp%d", i);
1.1.1.6 root 114: cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.13! root 115: offsetof(CPUPPCState, fpr[i]), p);
1.1.1.6 root 116: p += (i < 10) ? 4 : 5;
1.1.1.7 root 117: cpu_reg_names_size -= (i < 10) ? 4 : 5;
1.1.1.6 root 118:
1.1.1.7 root 119: snprintf(p, cpu_reg_names_size, "avr%dH", i);
1.1.1.8 root 120: #ifdef HOST_WORDS_BIGENDIAN
1.1.1.6 root 121: cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.13! root 122: offsetof(CPUPPCState, avr[i].u64[0]), p);
1.1.1.6 root 123: #else
124: cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.13! root 125: offsetof(CPUPPCState, avr[i].u64[1]), p);
1.1.1.5 root 126: #endif
1.1.1.6 root 127: p += (i < 10) ? 6 : 7;
1.1.1.7 root 128: cpu_reg_names_size -= (i < 10) ? 6 : 7;
1.1.1.5 root 129:
1.1.1.7 root 130: snprintf(p, cpu_reg_names_size, "avr%dL", i);
1.1.1.8 root 131: #ifdef HOST_WORDS_BIGENDIAN
1.1.1.6 root 132: cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.13! root 133: offsetof(CPUPPCState, avr[i].u64[1]), p);
1.1.1.6 root 134: #else
135: cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.13! root 136: offsetof(CPUPPCState, avr[i].u64[0]), p);
1.1.1.5 root 137: #endif
1.1.1.6 root 138: p += (i < 10) ? 6 : 7;
1.1.1.7 root 139: cpu_reg_names_size -= (i < 10) ? 6 : 7;
1.1.1.6 root 140: }
141:
142: cpu_nip = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 143: offsetof(CPUPPCState, nip), "nip");
1.1.1.6 root 144:
145: cpu_msr = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 146: offsetof(CPUPPCState, msr), "msr");
1.1.1.6 root 147:
148: cpu_ctr = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 149: offsetof(CPUPPCState, ctr), "ctr");
1.1.1.6 root 150:
151: cpu_lr = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 152: offsetof(CPUPPCState, lr), "lr");
1.1.1.6 root 153:
1.1.1.12 root 154: #if defined(TARGET_PPC64)
155: cpu_cfar = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 156: offsetof(CPUPPCState, cfar), "cfar");
1.1.1.12 root 157: #endif
158:
1.1.1.6 root 159: cpu_xer = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 160: offsetof(CPUPPCState, xer), "xer");
1.1.1.6 root 161:
162: cpu_reserve = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 163: offsetof(CPUPPCState, reserve_addr),
1.1.1.8 root 164: "reserve_addr");
1.1.1.6 root 165:
166: cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.13! root 167: offsetof(CPUPPCState, fpscr), "fpscr");
1.1.1.6 root 168:
169: cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.13! root 170: offsetof(CPUPPCState, access_type), "access_type");
1.1.1.6 root 171:
172: /* register helpers */
173: #define GEN_HELPER 2
174: #include "helper.h"
175:
176: done_init = 1;
177: }
1.1 root 178:
179: /* internal defines */
180: typedef struct DisasContext {
181: struct TranslationBlock *tb;
182: target_ulong nip;
183: uint32_t opcode;
184: uint32_t exception;
185: /* Routine used to access memory */
186: int mem_idx;
1.1.1.6 root 187: int access_type;
1.1 root 188: /* Translation flags */
1.1.1.6 root 189: int le_mode;
1.1.1.5 root 190: #if defined(TARGET_PPC64)
191: int sf_mode;
1.1.1.12 root 192: int has_cfar;
1.1.1.5 root 193: #endif
1.1 root 194: int fpu_enabled;
1.1.1.5 root 195: int altivec_enabled;
196: int spe_enabled;
1.1 root 197: ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
1.1.1.3 root 198: int singlestep_enabled;
1.1 root 199: } DisasContext;
200:
201: struct opc_handler_t {
1.1.1.12 root 202: /* invalid bits for instruction 1 (Rc(opcode) == 0) */
203: uint32_t inval1;
204: /* invalid bits for instruction 2 (Rc(opcode) == 1) */
205: uint32_t inval2;
1.1 root 206: /* instruction type */
1.1.1.5 root 207: uint64_t type;
1.1.1.11 root 208: /* extended instruction type */
209: uint64_t type2;
1.1 root 210: /* handler */
211: void (*handler)(DisasContext *ctx);
1.1.1.5 root 212: #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
1.1.1.6 root 213: const char *oname;
1.1.1.5 root 214: #endif
215: #if defined(DO_PPC_STATISTICS)
216: uint64_t count;
217: #endif
1.1 root 218: };
219:
1.1.1.8 root 220: static inline void gen_reset_fpstatus(void)
1.1.1.5 root 221: {
1.1.1.6 root 222: gen_helper_reset_fpstatus();
1.1.1.5 root 223: }
224:
1.1.1.8 root 225: static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
1.1.1.5 root 226: {
1.1.1.6 root 227: TCGv_i32 t0 = tcg_temp_new_i32();
228:
1.1.1.5 root 229: if (set_fprf != 0) {
230: /* This case might be optimized later */
1.1.1.6 root 231: tcg_gen_movi_i32(t0, 1);
232: gen_helper_compute_fprf(t0, arg, t0);
233: if (unlikely(set_rc)) {
234: tcg_gen_mov_i32(cpu_crf[1], t0);
235: }
236: gen_helper_float_check_status();
1.1.1.5 root 237: } else if (unlikely(set_rc)) {
238: /* We always need to compute fpcc */
1.1.1.6 root 239: tcg_gen_movi_i32(t0, 0);
240: gen_helper_compute_fprf(t0, arg, t0);
241: tcg_gen_mov_i32(cpu_crf[1], t0);
1.1.1.5 root 242: }
1.1.1.6 root 243:
244: tcg_temp_free_i32(t0);
1.1.1.5 root 245: }
246:
1.1.1.8 root 247: static inline void gen_set_access_type(DisasContext *ctx, int access_type)
1.1.1.5 root 248: {
1.1.1.6 root 249: if (ctx->access_type != access_type) {
250: tcg_gen_movi_i32(cpu_access_type, access_type);
251: ctx->access_type = access_type;
252: }
1.1.1.5 root 253: }
254:
1.1.1.8 root 255: static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
1.1.1.5 root 256: {
257: #if defined(TARGET_PPC64)
258: if (ctx->sf_mode)
1.1.1.6 root 259: tcg_gen_movi_tl(cpu_nip, nip);
1.1.1.5 root 260: else
261: #endif
1.1.1.6 root 262: tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
1.1.1.5 root 263: }
264:
1.1.1.8 root 265: static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
1.1.1.6 root 266: {
267: TCGv_i32 t0, t1;
268: if (ctx->exception == POWERPC_EXCP_NONE) {
269: gen_update_nip(ctx, ctx->nip);
270: }
271: t0 = tcg_const_i32(excp);
272: t1 = tcg_const_i32(error);
273: gen_helper_raise_exception_err(t0, t1);
274: tcg_temp_free_i32(t0);
275: tcg_temp_free_i32(t1);
276: ctx->exception = (excp);
277: }
1.1.1.5 root 278:
1.1.1.8 root 279: static inline void gen_exception(DisasContext *ctx, uint32_t excp)
1.1.1.6 root 280: {
281: TCGv_i32 t0;
282: if (ctx->exception == POWERPC_EXCP_NONE) {
283: gen_update_nip(ctx, ctx->nip);
284: }
285: t0 = tcg_const_i32(excp);
286: gen_helper_raise_exception(t0);
287: tcg_temp_free_i32(t0);
288: ctx->exception = (excp);
289: }
1.1.1.5 root 290:
1.1.1.8 root 291: static inline void gen_debug_exception(DisasContext *ctx)
1.1.1.6 root 292: {
293: TCGv_i32 t0;
1.1 root 294:
1.1.1.12 root 295: if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
296: (ctx->exception != POWERPC_EXCP_SYNC)) {
1.1.1.6 root 297: gen_update_nip(ctx, ctx->nip);
1.1.1.12 root 298: }
1.1.1.6 root 299: t0 = tcg_const_i32(EXCP_DEBUG);
300: gen_helper_raise_exception(t0);
301: tcg_temp_free_i32(t0);
302: }
1.1 root 303:
1.1.1.8 root 304: static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
1.1.1.6 root 305: {
306: gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
307: }
1.1 root 308:
1.1.1.2 root 309: /* Stop translation */
1.1.1.8 root 310: static inline void gen_stop_exception(DisasContext *ctx)
1.1 root 311: {
1.1.1.5 root 312: gen_update_nip(ctx, ctx->nip);
313: ctx->exception = POWERPC_EXCP_STOP;
1.1 root 314: }
315:
1.1.1.2 root 316: /* No need to update nip here, as execution flow will change */
1.1.1.8 root 317: static inline void gen_sync_exception(DisasContext *ctx)
1.1 root 318: {
1.1.1.5 root 319: ctx->exception = POWERPC_EXCP_SYNC;
1.1 root 320: }
321:
322: #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
1.1.1.11 root 323: GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
324:
325: #define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
326: GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
1.1 root 327:
1.1.1.5 root 328: #define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
1.1.1.11 root 329: GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
330:
331: #define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
332: GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
1.1.1.5 root 333:
1.1 root 334: typedef struct opcode_t {
335: unsigned char opc1, opc2, opc3;
1.1.1.6 root 336: #if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
1.1 root 337: unsigned char pad[5];
338: #else
339: unsigned char pad[1];
340: #endif
341: opc_handler_t handler;
1.1.1.6 root 342: const char *oname;
1.1 root 343: } opcode_t;
344:
1.1.1.5 root 345: /*****************************************************************************/
1.1 root 346: /*** Instruction decoding ***/
347: #define EXTRACT_HELPER(name, shift, nb) \
1.1.1.8 root 348: static inline uint32_t name(uint32_t opcode) \
1.1 root 349: { \
350: return (opcode >> (shift)) & ((1 << (nb)) - 1); \
351: }
352:
353: #define EXTRACT_SHELPER(name, shift, nb) \
1.1.1.8 root 354: static inline int32_t name(uint32_t opcode) \
1.1 root 355: { \
356: return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
357: }
358:
359: /* Opcode part 1 */
360: EXTRACT_HELPER(opc1, 26, 6);
361: /* Opcode part 2 */
362: EXTRACT_HELPER(opc2, 1, 5);
363: /* Opcode part 3 */
364: EXTRACT_HELPER(opc3, 6, 5);
365: /* Update Cr0 flags */
366: EXTRACT_HELPER(Rc, 0, 1);
367: /* Destination */
368: EXTRACT_HELPER(rD, 21, 5);
369: /* Source */
370: EXTRACT_HELPER(rS, 21, 5);
371: /* First operand */
372: EXTRACT_HELPER(rA, 16, 5);
373: /* Second operand */
374: EXTRACT_HELPER(rB, 11, 5);
375: /* Third operand */
376: EXTRACT_HELPER(rC, 6, 5);
377: /*** Get CRn ***/
378: EXTRACT_HELPER(crfD, 23, 3);
379: EXTRACT_HELPER(crfS, 18, 3);
380: EXTRACT_HELPER(crbD, 21, 5);
381: EXTRACT_HELPER(crbA, 16, 5);
382: EXTRACT_HELPER(crbB, 11, 5);
383: /* SPR / TBL */
384: EXTRACT_HELPER(_SPR, 11, 10);
1.1.1.8 root 385: static inline uint32_t SPR(uint32_t opcode)
1.1 root 386: {
387: uint32_t sprn = _SPR(opcode);
388:
389: return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
390: }
391: /*** Get constants ***/
392: EXTRACT_HELPER(IMM, 12, 8);
393: /* 16 bits signed immediate value */
394: EXTRACT_SHELPER(SIMM, 0, 16);
395: /* 16 bits unsigned immediate value */
396: EXTRACT_HELPER(UIMM, 0, 16);
1.1.1.6 root 397: /* 5 bits signed immediate value */
398: EXTRACT_HELPER(SIMM5, 16, 5);
399: /* 5 bits signed immediate value */
400: EXTRACT_HELPER(UIMM5, 16, 5);
1.1 root 401: /* Bit count */
402: EXTRACT_HELPER(NB, 11, 5);
403: /* Shift count */
404: EXTRACT_HELPER(SH, 11, 5);
1.1.1.6 root 405: /* Vector shift count */
406: EXTRACT_HELPER(VSH, 6, 4);
1.1 root 407: /* Mask start */
408: EXTRACT_HELPER(MB, 6, 5);
409: /* Mask end */
410: EXTRACT_HELPER(ME, 1, 5);
411: /* Trap operand */
412: EXTRACT_HELPER(TO, 21, 5);
413:
414: EXTRACT_HELPER(CRM, 12, 8);
415: EXTRACT_HELPER(FM, 17, 8);
416: EXTRACT_HELPER(SR, 16, 4);
1.1.1.6 root 417: EXTRACT_HELPER(FPIMM, 12, 4);
1.1 root 418:
419: /*** Jump target decoding ***/
420: /* Displacement */
421: EXTRACT_SHELPER(d, 0, 16);
422: /* Immediate address */
1.1.1.8 root 423: static inline target_ulong LI(uint32_t opcode)
1.1 root 424: {
425: return (opcode >> 0) & 0x03FFFFFC;
426: }
427:
1.1.1.8 root 428: static inline uint32_t BD(uint32_t opcode)
1.1 root 429: {
430: return (opcode >> 0) & 0xFFFC;
431: }
432:
433: EXTRACT_HELPER(BO, 21, 5);
434: EXTRACT_HELPER(BI, 16, 5);
435: /* Absolute/relative address */
436: EXTRACT_HELPER(AA, 1, 1);
437: /* Link */
438: EXTRACT_HELPER(LK, 0, 1);
439:
440: /* Create a mask between <start> and <end> bits */
1.1.1.8 root 441: static inline target_ulong MASK(uint32_t start, uint32_t end)
1.1 root 442: {
1.1.1.5 root 443: target_ulong ret;
1.1 root 444:
1.1.1.5 root 445: #if defined(TARGET_PPC64)
446: if (likely(start == 0)) {
447: ret = UINT64_MAX << (63 - end);
448: } else if (likely(end == 63)) {
449: ret = UINT64_MAX >> start;
450: }
451: #else
452: if (likely(start == 0)) {
453: ret = UINT32_MAX << (31 - end);
454: } else if (likely(end == 31)) {
455: ret = UINT32_MAX >> start;
456: }
457: #endif
458: else {
459: ret = (((target_ulong)(-1ULL)) >> (start)) ^
460: (((target_ulong)(-1ULL) >> (end)) >> 1);
461: if (unlikely(start > end))
462: return ~ret;
463: }
1.1 root 464:
465: return ret;
466: }
467:
1.1.1.5 root 468: /*****************************************************************************/
469: /* PowerPC instructions table */
1.1 root 470:
1.1.1.5 root 471: #if defined(DO_PPC_STATISTICS)
1.1.1.11 root 472: #define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
1.1.1.7 root 473: { \
1.1.1.5 root 474: .opc1 = op1, \
475: .opc2 = op2, \
476: .opc3 = op3, \
477: .pad = { 0, }, \
478: .handler = { \
1.1.1.12 root 479: .inval1 = invl, \
480: .type = _typ, \
481: .type2 = _typ2, \
482: .handler = &gen_##name, \
483: .oname = stringify(name), \
484: }, \
485: .oname = stringify(name), \
486: }
487: #define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
488: { \
489: .opc1 = op1, \
490: .opc2 = op2, \
491: .opc3 = op3, \
492: .pad = { 0, }, \
493: .handler = { \
494: .inval1 = invl1, \
495: .inval2 = invl2, \
1.1.1.5 root 496: .type = _typ, \
1.1.1.11 root 497: .type2 = _typ2, \
1.1.1.5 root 498: .handler = &gen_##name, \
499: .oname = stringify(name), \
500: }, \
501: .oname = stringify(name), \
502: }
1.1.1.11 root 503: #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
1.1.1.7 root 504: { \
1.1.1.5 root 505: .opc1 = op1, \
506: .opc2 = op2, \
507: .opc3 = op3, \
508: .pad = { 0, }, \
509: .handler = { \
1.1.1.12 root 510: .inval1 = invl, \
1.1.1.5 root 511: .type = _typ, \
1.1.1.11 root 512: .type2 = _typ2, \
1.1.1.5 root 513: .handler = &gen_##name, \
514: .oname = onam, \
515: }, \
516: .oname = onam, \
517: }
518: #else
1.1.1.11 root 519: #define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
1.1.1.7 root 520: { \
1.1 root 521: .opc1 = op1, \
522: .opc2 = op2, \
523: .opc3 = op3, \
524: .pad = { 0, }, \
525: .handler = { \
1.1.1.12 root 526: .inval1 = invl, \
527: .type = _typ, \
528: .type2 = _typ2, \
529: .handler = &gen_##name, \
530: }, \
531: .oname = stringify(name), \
532: }
533: #define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
534: { \
535: .opc1 = op1, \
536: .opc2 = op2, \
537: .opc3 = op3, \
538: .pad = { 0, }, \
539: .handler = { \
540: .inval1 = invl1, \
541: .inval2 = invl2, \
1.1 root 542: .type = _typ, \
1.1.1.11 root 543: .type2 = _typ2, \
1.1 root 544: .handler = &gen_##name, \
545: }, \
546: .oname = stringify(name), \
547: }
1.1.1.11 root 548: #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
1.1.1.7 root 549: { \
1.1.1.5 root 550: .opc1 = op1, \
551: .opc2 = op2, \
552: .opc3 = op3, \
553: .pad = { 0, }, \
554: .handler = { \
1.1.1.12 root 555: .inval1 = invl, \
1.1.1.5 root 556: .type = _typ, \
1.1.1.11 root 557: .type2 = _typ2, \
1.1.1.5 root 558: .handler = &gen_##name, \
559: }, \
560: .oname = onam, \
561: }
562: #endif
1.1 root 563:
1.1.1.6 root 564: /* SPR load/store helpers */
1.1.1.8 root 565: static inline void gen_load_spr(TCGv t, int reg)
1.1.1.6 root 566: {
1.1.1.13! root 567: tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
1.1.1.6 root 568: }
569:
1.1.1.8 root 570: static inline void gen_store_spr(int reg, TCGv t)
1.1.1.6 root 571: {
1.1.1.13! root 572: tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
1.1.1.6 root 573: }
574:
1.1 root 575: /* Invalid instruction */
1.1.1.7 root 576: static void gen_invalid(DisasContext *ctx)
1.1 root 577: {
1.1.1.6 root 578: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1 root 579: }
580:
581: static opc_handler_t invalid_handler = {
1.1.1.12 root 582: .inval1 = 0xFFFFFFFF,
583: .inval2 = 0xFFFFFFFF,
1.1 root 584: .type = PPC_NONE,
1.1.1.11 root 585: .type2 = PPC_NONE,
1.1 root 586: .handler = gen_invalid,
587: };
588:
1.1.1.6 root 589: /*** Integer comparison ***/
1.1 root 590:
1.1.1.8 root 591: static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
1.1.1.6 root 592: {
593: int l1, l2, l3;
1.1 root 594:
1.1.1.6 root 595: tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
596: tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
597: tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
598:
599: l1 = gen_new_label();
600: l2 = gen_new_label();
601: l3 = gen_new_label();
602: if (s) {
603: tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
604: tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
605: } else {
606: tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
607: tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
608: }
609: tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
610: tcg_gen_br(l3);
611: gen_set_label(l1);
612: tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
613: tcg_gen_br(l3);
614: gen_set_label(l2);
615: tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
616: gen_set_label(l3);
1.1.1.5 root 617: }
618:
1.1.1.8 root 619: static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
1.1.1.6 root 620: {
621: TCGv t0 = tcg_const_local_tl(arg1);
622: gen_op_cmp(arg0, t0, s, crf);
623: tcg_temp_free(t0);
1.1.1.5 root 624: }
625:
1.1.1.6 root 626: #if defined(TARGET_PPC64)
1.1.1.8 root 627: static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
1.1.1.6 root 628: {
629: TCGv t0, t1;
630: t0 = tcg_temp_local_new();
631: t1 = tcg_temp_local_new();
632: if (s) {
633: tcg_gen_ext32s_tl(t0, arg0);
634: tcg_gen_ext32s_tl(t1, arg1);
635: } else {
636: tcg_gen_ext32u_tl(t0, arg0);
637: tcg_gen_ext32u_tl(t1, arg1);
638: }
639: gen_op_cmp(t0, t1, s, crf);
640: tcg_temp_free(t1);
641: tcg_temp_free(t0);
1.1.1.5 root 642: }
643:
1.1.1.8 root 644: static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
1.1.1.6 root 645: {
646: TCGv t0 = tcg_const_local_tl(arg1);
647: gen_op_cmp32(arg0, t0, s, crf);
648: tcg_temp_free(t0);
1.1 root 649: }
1.1.1.5 root 650: #endif
1.1 root 651:
1.1.1.8 root 652: static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
1.1.1.5 root 653: {
654: #if defined(TARGET_PPC64)
1.1.1.6 root 655: if (!(ctx->sf_mode))
656: gen_op_cmpi32(reg, 0, 1, 0);
657: else
1.1.1.5 root 658: #endif
1.1.1.6 root 659: gen_op_cmpi(reg, 0, 1, 0);
1.1.1.5 root 660: }
1.1.1.6 root 661:
662: /* cmp */
1.1.1.7 root 663: static void gen_cmp(DisasContext *ctx)
1.1.1.5 root 664: {
665: #if defined(TARGET_PPC64)
1.1.1.6 root 666: if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
667: gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
668: 1, crfD(ctx->opcode));
669: else
1.1.1.5 root 670: #endif
1.1.1.6 root 671: gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
672: 1, crfD(ctx->opcode));
1.1.1.5 root 673: }
1.1.1.6 root 674:
675: /* cmpi */
1.1.1.7 root 676: static void gen_cmpi(DisasContext *ctx)
1.1.1.5 root 677: {
1.1.1.6 root 678: #if defined(TARGET_PPC64)
679: if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
680: gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
681: 1, crfD(ctx->opcode));
682: else
1.1.1.5 root 683: #endif
1.1.1.6 root 684: gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
685: 1, crfD(ctx->opcode));
1.1.1.5 root 686: }
1.1.1.6 root 687:
688: /* cmpl */
1.1.1.7 root 689: static void gen_cmpl(DisasContext *ctx)
1.1.1.5 root 690: {
1.1.1.6 root 691: #if defined(TARGET_PPC64)
692: if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
693: gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
694: 0, crfD(ctx->opcode));
695: else
1.1.1.5 root 696: #endif
1.1.1.6 root 697: gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
698: 0, crfD(ctx->opcode));
1.1.1.5 root 699: }
1.1.1.6 root 700:
701: /* cmpli */
1.1.1.7 root 702: static void gen_cmpli(DisasContext *ctx)
1.1.1.5 root 703: {
704: #if defined(TARGET_PPC64)
1.1.1.6 root 705: if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
706: gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
707: 0, crfD(ctx->opcode));
708: else
709: #endif
710: gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
711: 0, crfD(ctx->opcode));
1.1.1.5 root 712: }
1.1.1.6 root 713:
714: /* isel (PowerPC 2.03 specification) */
1.1.1.7 root 715: static void gen_isel(DisasContext *ctx)
1.1.1.5 root 716: {
1.1.1.6 root 717: int l1, l2;
718: uint32_t bi = rC(ctx->opcode);
719: uint32_t mask;
720: TCGv_i32 t0;
721:
722: l1 = gen_new_label();
723: l2 = gen_new_label();
724:
725: mask = 1 << (3 - (bi & 0x03));
726: t0 = tcg_temp_new_i32();
727: tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
728: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
729: if (rA(ctx->opcode) == 0)
730: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
731: else
732: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
733: tcg_gen_br(l2);
734: gen_set_label(l1);
735: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
736: gen_set_label(l2);
737: tcg_temp_free_i32(t0);
1.1.1.5 root 738: }
1.1.1.6 root 739:
740: /*** Integer arithmetic ***/
741:
1.1.1.8 root 742: static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
743: TCGv arg1, TCGv arg2, int sub)
1.1.1.5 root 744: {
1.1.1.6 root 745: int l1;
746: TCGv t0;
747:
748: l1 = gen_new_label();
749: /* Start with XER OV disabled, the most likely case */
750: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
751: t0 = tcg_temp_local_new();
752: tcg_gen_xor_tl(t0, arg0, arg1);
1.1.1.5 root 753: #if defined(TARGET_PPC64)
1.1.1.6 root 754: if (!ctx->sf_mode)
755: tcg_gen_ext32s_tl(t0, t0);
1.1.1.5 root 756: #endif
1.1.1.6 root 757: if (sub)
758: tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
759: else
760: tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
761: tcg_gen_xor_tl(t0, arg1, arg2);
762: #if defined(TARGET_PPC64)
763: if (!ctx->sf_mode)
764: tcg_gen_ext32s_tl(t0, t0);
765: #endif
766: if (sub)
767: tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
768: else
769: tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
770: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
771: gen_set_label(l1);
772: tcg_temp_free(t0);
1.1.1.5 root 773: }
1.1.1.6 root 774:
1.1.1.8 root 775: static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
776: TCGv arg2, int sub)
1.1.1.5 root 777: {
1.1.1.6 root 778: int l1 = gen_new_label();
779:
1.1.1.5 root 780: #if defined(TARGET_PPC64)
1.1.1.6 root 781: if (!(ctx->sf_mode)) {
782: TCGv t0, t1;
783: t0 = tcg_temp_new();
784: t1 = tcg_temp_new();
785:
786: tcg_gen_ext32u_tl(t0, arg1);
787: tcg_gen_ext32u_tl(t1, arg2);
788: if (sub) {
789: tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
790: } else {
791: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
792: }
793: tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
794: gen_set_label(l1);
795: tcg_temp_free(t0);
796: tcg_temp_free(t1);
797: } else
798: #endif
799: {
800: if (sub) {
801: tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
802: } else {
803: tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
804: }
805: tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
806: gen_set_label(l1);
807: }
1.1.1.5 root 808: }
1.1.1.6 root 809:
810: /* Common add function */
1.1.1.8 root 811: static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
812: TCGv arg2, int add_ca, int compute_ca,
813: int compute_ov)
1.1.1.6 root 814: {
815: TCGv t0, t1;
816:
817: if ((!compute_ca && !compute_ov) ||
818: (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2))) {
819: t0 = ret;
820: } else {
821: t0 = tcg_temp_local_new();
822: }
823:
824: if (add_ca) {
825: t1 = tcg_temp_local_new();
826: tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
827: tcg_gen_shri_tl(t1, t1, XER_CA);
1.1.1.7 root 828: } else {
829: TCGV_UNUSED(t1);
1.1.1.6 root 830: }
831:
832: if (compute_ca && compute_ov) {
833: /* Start with XER CA and OV disabled, the most likely case */
834: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
835: } else if (compute_ca) {
836: /* Start with XER CA disabled, the most likely case */
837: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
838: } else if (compute_ov) {
839: /* Start with XER OV disabled, the most likely case */
840: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
841: }
842:
843: tcg_gen_add_tl(t0, arg1, arg2);
844:
845: if (compute_ca) {
846: gen_op_arith_compute_ca(ctx, t0, arg1, 0);
847: }
848: if (add_ca) {
849: tcg_gen_add_tl(t0, t0, t1);
850: gen_op_arith_compute_ca(ctx, t0, t1, 0);
851: tcg_temp_free(t1);
852: }
853: if (compute_ov) {
854: gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
855: }
856:
857: if (unlikely(Rc(ctx->opcode) != 0))
858: gen_set_Rc0(ctx, t0);
859:
860: if (!TCGV_EQUAL(t0, ret)) {
861: tcg_gen_mov_tl(ret, t0);
862: tcg_temp_free(t0);
863: }
1.1.1.5 root 864: }
1.1.1.6 root 865: /* Add functions with two operands */
866: #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
1.1.1.7 root 867: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 868: { \
869: gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
870: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
871: add_ca, compute_ca, compute_ov); \
1.1.1.5 root 872: }
1.1.1.6 root 873: /* Add functions with one operand and one immediate */
874: #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
875: add_ca, compute_ca, compute_ov) \
1.1.1.7 root 876: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 877: { \
878: TCGv t0 = tcg_const_local_tl(const_val); \
879: gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
880: cpu_gpr[rA(ctx->opcode)], t0, \
881: add_ca, compute_ca, compute_ov); \
882: tcg_temp_free(t0); \
1.1.1.5 root 883: }
1.1.1.6 root 884:
885: /* add add. addo addo. */
886: GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
887: GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
888: /* addc addc. addco addco. */
889: GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
890: GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
891: /* adde adde. addeo addeo. */
892: GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
893: GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
894: /* addme addme. addmeo addmeo. */
895: GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
896: GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
897: /* addze addze. addzeo addzeo.*/
898: GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
899: GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
1.1 root 900: /* addi */
1.1.1.7 root 901: static void gen_addi(DisasContext *ctx)
1.1 root 902: {
1.1.1.5 root 903: target_long simm = SIMM(ctx->opcode);
1.1 root 904:
905: if (rA(ctx->opcode) == 0) {
1.1.1.5 root 906: /* li case */
1.1.1.6 root 907: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
1.1 root 908: } else {
1.1.1.6 root 909: tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
1.1 root 910: }
911: }
1.1.1.6 root 912: /* addic addic.*/
1.1.1.8 root 913: static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
914: int compute_Rc0)
1.1 root 915: {
1.1.1.5 root 916: target_long simm = SIMM(ctx->opcode);
917:
1.1.1.6 root 918: /* Start with XER CA and OV disabled, the most likely case */
919: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
920:
1.1.1.5 root 921: if (likely(simm != 0)) {
1.1.1.6 root 922: TCGv t0 = tcg_temp_local_new();
923: tcg_gen_addi_tl(t0, arg1, simm);
924: gen_op_arith_compute_ca(ctx, t0, arg1, 0);
925: tcg_gen_mov_tl(ret, t0);
926: tcg_temp_free(t0);
1.1.1.5 root 927: } else {
1.1.1.6 root 928: tcg_gen_mov_tl(ret, arg1);
929: }
930: if (compute_Rc0) {
931: gen_set_Rc0(ctx, ret);
1.1.1.5 root 932: }
1.1 root 933: }
1.1.1.7 root 934:
935: static void gen_addic(DisasContext *ctx)
1.1.1.6 root 936: {
937: gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
938: }
1.1.1.7 root 939:
940: static void gen_addic_(DisasContext *ctx)
1.1 root 941: {
1.1.1.6 root 942: gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1.1 root 943: }
1.1.1.7 root 944:
1.1 root 945: /* addis */
1.1.1.7 root 946: static void gen_addis(DisasContext *ctx)
1.1 root 947: {
1.1.1.5 root 948: target_long simm = SIMM(ctx->opcode);
1.1 root 949:
950: if (rA(ctx->opcode) == 0) {
1.1.1.5 root 951: /* lis case */
1.1.1.6 root 952: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
1.1 root 953: } else {
1.1.1.6 root 954: tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
1.1 root 955: }
956: }
957:
1.1.1.8 root 958: static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
959: TCGv arg2, int sign, int compute_ov)
1.1.1.6 root 960: {
961: int l1 = gen_new_label();
962: int l2 = gen_new_label();
963: TCGv_i32 t0 = tcg_temp_local_new_i32();
964: TCGv_i32 t1 = tcg_temp_local_new_i32();
965:
966: tcg_gen_trunc_tl_i32(t0, arg1);
967: tcg_gen_trunc_tl_i32(t1, arg2);
968: tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
969: if (sign) {
970: int l3 = gen_new_label();
971: tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
972: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
973: gen_set_label(l3);
974: tcg_gen_div_i32(t0, t0, t1);
975: } else {
976: tcg_gen_divu_i32(t0, t0, t1);
977: }
978: if (compute_ov) {
979: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
980: }
981: tcg_gen_br(l2);
982: gen_set_label(l1);
983: if (sign) {
984: tcg_gen_sari_i32(t0, t0, 31);
985: } else {
986: tcg_gen_movi_i32(t0, 0);
987: }
988: if (compute_ov) {
989: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
990: }
991: gen_set_label(l2);
992: tcg_gen_extu_i32_tl(ret, t0);
993: tcg_temp_free_i32(t0);
994: tcg_temp_free_i32(t1);
995: if (unlikely(Rc(ctx->opcode) != 0))
996: gen_set_Rc0(ctx, ret);
997: }
998: /* Div functions */
999: #define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
1.1.1.7 root 1000: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 1001: { \
1002: gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
1003: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1004: sign, compute_ov); \
1005: }
1006: /* divwu divwu. divwuo divwuo. */
1007: GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
1008: GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
1009: /* divw divw. divwo divwo. */
1010: GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1011: GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
1012: #if defined(TARGET_PPC64)
1.1.1.8 root 1013: static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
1014: TCGv arg2, int sign, int compute_ov)
1.1.1.6 root 1015: {
1016: int l1 = gen_new_label();
1017: int l2 = gen_new_label();
1018:
1019: tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
1020: if (sign) {
1021: int l3 = gen_new_label();
1022: tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
1023: tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
1024: gen_set_label(l3);
1025: tcg_gen_div_i64(ret, arg1, arg2);
1026: } else {
1027: tcg_gen_divu_i64(ret, arg1, arg2);
1028: }
1029: if (compute_ov) {
1030: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1031: }
1032: tcg_gen_br(l2);
1033: gen_set_label(l1);
1034: if (sign) {
1035: tcg_gen_sari_i64(ret, arg1, 63);
1036: } else {
1037: tcg_gen_movi_i64(ret, 0);
1038: }
1039: if (compute_ov) {
1040: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1041: }
1042: gen_set_label(l2);
1043: if (unlikely(Rc(ctx->opcode) != 0))
1044: gen_set_Rc0(ctx, ret);
1.1.1.5 root 1045: }
1.1.1.6 root 1046: #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
1.1.1.7 root 1047: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 1048: { \
1.1.1.6 root 1049: gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
1050: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1051: sign, compute_ov); \
1.1 root 1052: }
1.1.1.6 root 1053: /* divwu divwu. divwuo divwuo. */
1054: GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1055: GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1056: /* divw divw. divwo divwo. */
1057: GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1058: GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1.1.1.5 root 1059: #endif
1.1 root 1060:
1.1.1.6 root 1061: /* mulhw mulhw. */
1.1.1.7 root 1062: static void gen_mulhw(DisasContext *ctx)
1.1 root 1063: {
1.1.1.6 root 1064: TCGv_i64 t0, t1;
1065:
1066: t0 = tcg_temp_new_i64();
1067: t1 = tcg_temp_new_i64();
1.1.1.5 root 1068: #if defined(TARGET_PPC64)
1.1.1.6 root 1069: tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1070: tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1071: tcg_gen_mul_i64(t0, t0, t1);
1072: tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1073: #else
1074: tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1075: tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1076: tcg_gen_mul_i64(t0, t0, t1);
1077: tcg_gen_shri_i64(t0, t0, 32);
1078: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.5 root 1079: #endif
1.1.1.6 root 1080: tcg_temp_free_i64(t0);
1081: tcg_temp_free_i64(t1);
1082: if (unlikely(Rc(ctx->opcode) != 0))
1083: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1 root 1084: }
1.1.1.7 root 1085:
1.1.1.6 root 1086: /* mulhwu mulhwu. */
1.1.1.7 root 1087: static void gen_mulhwu(DisasContext *ctx)
1.1 root 1088: {
1.1.1.6 root 1089: TCGv_i64 t0, t1;
1090:
1091: t0 = tcg_temp_new_i64();
1092: t1 = tcg_temp_new_i64();
1.1.1.5 root 1093: #if defined(TARGET_PPC64)
1.1.1.6 root 1094: tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1095: tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1096: tcg_gen_mul_i64(t0, t0, t1);
1097: tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1098: #else
1099: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1100: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1101: tcg_gen_mul_i64(t0, t0, t1);
1102: tcg_gen_shri_i64(t0, t0, 32);
1103: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.5 root 1104: #endif
1.1.1.6 root 1105: tcg_temp_free_i64(t0);
1106: tcg_temp_free_i64(t1);
1107: if (unlikely(Rc(ctx->opcode) != 0))
1108: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1109: }
1.1.1.7 root 1110:
1.1.1.6 root 1111: /* mullw mullw. */
1.1.1.7 root 1112: static void gen_mullw(DisasContext *ctx)
1.1.1.6 root 1113: {
1114: tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1115: cpu_gpr[rB(ctx->opcode)]);
1116: tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1117: if (unlikely(Rc(ctx->opcode) != 0))
1118: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1 root 1119: }
1.1.1.7 root 1120:
1.1.1.6 root 1121: /* mullwo mullwo. */
1.1.1.7 root 1122: static void gen_mullwo(DisasContext *ctx)
1.1.1.6 root 1123: {
1124: int l1;
1125: TCGv_i64 t0, t1;
1.1 root 1126:
1.1.1.6 root 1127: t0 = tcg_temp_new_i64();
1128: t1 = tcg_temp_new_i64();
1129: l1 = gen_new_label();
1130: /* Start with XER OV disabled, the most likely case */
1131: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1132: #if defined(TARGET_PPC64)
1133: tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1134: tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1135: #else
1136: tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1137: tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1138: #endif
1139: tcg_gen_mul_i64(t0, t0, t1);
1140: #if defined(TARGET_PPC64)
1141: tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
1142: tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
1143: #else
1144: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1145: tcg_gen_ext32s_i64(t1, t0);
1146: tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
1147: #endif
1148: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1149: gen_set_label(l1);
1150: tcg_temp_free_i64(t0);
1151: tcg_temp_free_i64(t1);
1152: if (unlikely(Rc(ctx->opcode) != 0))
1153: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1154: }
1.1.1.7 root 1155:
1.1.1.6 root 1156: /* mulli */
1.1.1.7 root 1157: static void gen_mulli(DisasContext *ctx)
1.1.1.5 root 1158: {
1.1.1.6 root 1159: tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1160: SIMM(ctx->opcode));
1161: }
1162: #if defined(TARGET_PPC64)
1163: #define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
1.1.1.7 root 1164: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 1165: { \
1166: gen_helper_##name (cpu_gpr[rD(ctx->opcode)], \
1167: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
1168: if (unlikely(Rc(ctx->opcode) != 0)) \
1169: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
1170: }
1171: /* mulhd mulhd. */
1172: GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
1173: /* mulhdu mulhdu. */
1174: GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
1.1.1.7 root 1175:
1.1.1.6 root 1176: /* mulld mulld. */
1.1.1.7 root 1177: static void gen_mulld(DisasContext *ctx)
1.1.1.6 root 1178: {
1179: tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1180: cpu_gpr[rB(ctx->opcode)]);
1181: if (unlikely(Rc(ctx->opcode) != 0))
1182: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1183: }
1184: /* mulldo mulldo. */
1185: GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1186: #endif
1.1.1.5 root 1187:
1.1.1.6 root 1188: /* neg neg. nego nego. */
1.1.1.8 root 1189: static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
1190: int ov_check)
1.1.1.6 root 1191: {
1192: int l1 = gen_new_label();
1193: int l2 = gen_new_label();
1194: TCGv t0 = tcg_temp_local_new();
1195: #if defined(TARGET_PPC64)
1196: if (ctx->sf_mode) {
1197: tcg_gen_mov_tl(t0, arg1);
1198: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
1199: } else
1200: #endif
1201: {
1202: tcg_gen_ext32s_tl(t0, arg1);
1203: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
1204: }
1205: tcg_gen_neg_tl(ret, arg1);
1206: if (ov_check) {
1207: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1208: }
1209: tcg_gen_br(l2);
1210: gen_set_label(l1);
1211: tcg_gen_mov_tl(ret, t0);
1212: if (ov_check) {
1213: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1214: }
1215: gen_set_label(l2);
1216: tcg_temp_free(t0);
1217: if (unlikely(Rc(ctx->opcode) != 0))
1218: gen_set_Rc0(ctx, ret);
1219: }
1.1.1.7 root 1220:
1221: static void gen_neg(DisasContext *ctx)
1.1.1.6 root 1222: {
1223: gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1224: }
1.1.1.7 root 1225:
1226: static void gen_nego(DisasContext *ctx)
1.1.1.6 root 1227: {
1228: gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1229: }
1230:
1231: /* Common subf function */
1.1.1.8 root 1232: static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1233: TCGv arg2, int add_ca, int compute_ca,
1234: int compute_ov)
1.1.1.6 root 1235: {
1236: TCGv t0, t1;
1237:
1238: if ((!compute_ca && !compute_ov) ||
1239: (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2))) {
1240: t0 = ret;
1.1.1.5 root 1241: } else {
1.1.1.6 root 1242: t0 = tcg_temp_local_new();
1.1.1.5 root 1243: }
1.1.1.6 root 1244:
1245: if (add_ca) {
1246: t1 = tcg_temp_local_new();
1247: tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1248: tcg_gen_shri_tl(t1, t1, XER_CA);
1.1.1.7 root 1249: } else {
1250: TCGV_UNUSED(t1);
1.1.1.6 root 1251: }
1252:
1253: if (compute_ca && compute_ov) {
1254: /* Start with XER CA and OV disabled, the most likely case */
1255: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
1256: } else if (compute_ca) {
1257: /* Start with XER CA disabled, the most likely case */
1258: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1259: } else if (compute_ov) {
1260: /* Start with XER OV disabled, the most likely case */
1261: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1262: }
1263:
1264: if (add_ca) {
1265: tcg_gen_not_tl(t0, arg1);
1266: tcg_gen_add_tl(t0, t0, arg2);
1267: gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1268: tcg_gen_add_tl(t0, t0, t1);
1269: gen_op_arith_compute_ca(ctx, t0, t1, 0);
1270: tcg_temp_free(t1);
1271: } else {
1272: tcg_gen_sub_tl(t0, arg2, arg1);
1273: if (compute_ca) {
1274: gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1275: }
1276: }
1277: if (compute_ov) {
1278: gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1279: }
1280:
1281: if (unlikely(Rc(ctx->opcode) != 0))
1282: gen_set_Rc0(ctx, t0);
1283:
1284: if (!TCGV_EQUAL(t0, ret)) {
1285: tcg_gen_mov_tl(ret, t0);
1286: tcg_temp_free(t0);
1287: }
1288: }
1289: /* Sub functions with Two operands functions */
1290: #define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
1.1.1.7 root 1291: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 1292: { \
1293: gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1294: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1295: add_ca, compute_ca, compute_ov); \
1296: }
1297: /* Sub functions with one operand and one immediate */
1298: #define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
1299: add_ca, compute_ca, compute_ov) \
1.1.1.7 root 1300: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 1301: { \
1302: TCGv t0 = tcg_const_local_tl(const_val); \
1303: gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1304: cpu_gpr[rA(ctx->opcode)], t0, \
1305: add_ca, compute_ca, compute_ov); \
1306: tcg_temp_free(t0); \
1307: }
1308: /* subf subf. subfo subfo. */
1309: GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1310: GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1311: /* subfc subfc. subfco subfco. */
1312: GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1313: GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1314: /* subfe subfe. subfeo subfo. */
1315: GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1316: GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1317: /* subfme subfme. subfmeo subfmeo. */
1318: GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1319: GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1320: /* subfze subfze. subfzeo subfzeo.*/
1321: GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1322: GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
1.1.1.7 root 1323:
1.1.1.6 root 1324: /* subfic */
1.1.1.7 root 1325: static void gen_subfic(DisasContext *ctx)
1.1.1.6 root 1326: {
1327: /* Start with XER CA and OV disabled, the most likely case */
1328: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1329: TCGv t0 = tcg_temp_local_new();
1330: TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
1331: tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
1332: gen_op_arith_compute_ca(ctx, t0, t1, 1);
1333: tcg_temp_free(t1);
1334: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
1335: tcg_temp_free(t0);
1.1.1.5 root 1336: }
1337:
1.1 root 1338: /*** Integer logical ***/
1.1.1.6 root 1339: #define GEN_LOGICAL2(name, tcg_op, opc, type) \
1.1.1.7 root 1340: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 1341: { \
1.1.1.6 root 1342: tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
1343: cpu_gpr[rB(ctx->opcode)]); \
1.1.1.5 root 1344: if (unlikely(Rc(ctx->opcode) != 0)) \
1.1.1.6 root 1345: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
1.1 root 1346: }
1347:
1.1.1.6 root 1348: #define GEN_LOGICAL1(name, tcg_op, opc, type) \
1.1.1.7 root 1349: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 1350: { \
1.1.1.6 root 1351: tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
1.1.1.5 root 1352: if (unlikely(Rc(ctx->opcode) != 0)) \
1.1.1.6 root 1353: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
1.1 root 1354: }
1355:
1356: /* and & and. */
1.1.1.6 root 1357: GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1.1 root 1358: /* andc & andc. */
1.1.1.6 root 1359: GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1.1.1.7 root 1360:
1.1 root 1361: /* andi. */
1.1.1.7 root 1362: static void gen_andi_(DisasContext *ctx)
1.1 root 1363: {
1.1.1.6 root 1364: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1365: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1366: }
1.1.1.7 root 1367:
1.1 root 1368: /* andis. */
1.1.1.7 root 1369: static void gen_andis_(DisasContext *ctx)
1.1 root 1370: {
1.1.1.6 root 1371: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1372: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1373: }
1.1.1.7 root 1374:
1.1 root 1375: /* cntlzw */
1.1.1.7 root 1376: static void gen_cntlzw(DisasContext *ctx)
1.1.1.6 root 1377: {
1378: gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1379: if (unlikely(Rc(ctx->opcode) != 0))
1380: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1381: }
1.1 root 1382: /* eqv & eqv. */
1.1.1.6 root 1383: GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1.1 root 1384: /* extsb & extsb. */
1.1.1.6 root 1385: GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1.1 root 1386: /* extsh & extsh. */
1.1.1.6 root 1387: GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1.1 root 1388: /* nand & nand. */
1.1.1.6 root 1389: GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1.1 root 1390: /* nor & nor. */
1.1.1.6 root 1391: GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1.1.1.7 root 1392:
1.1 root 1393: /* or & or. */
1.1.1.7 root 1394: static void gen_or(DisasContext *ctx)
1.1 root 1395: {
1.1.1.5 root 1396: int rs, ra, rb;
1397:
1398: rs = rS(ctx->opcode);
1399: ra = rA(ctx->opcode);
1400: rb = rB(ctx->opcode);
1401: /* Optimisation for mr. ri case */
1402: if (rs != ra || rs != rb) {
1.1.1.6 root 1403: if (rs != rb)
1404: tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1405: else
1406: tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1.1.1.5 root 1407: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1408: gen_set_Rc0(ctx, cpu_gpr[ra]);
1.1.1.5 root 1409: } else if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 1410: gen_set_Rc0(ctx, cpu_gpr[rs]);
1.1.1.5 root 1411: #if defined(TARGET_PPC64)
1412: } else {
1.1.1.6 root 1413: int prio = 0;
1414:
1.1.1.5 root 1415: switch (rs) {
1416: case 1:
1417: /* Set process priority to low */
1.1.1.6 root 1418: prio = 2;
1.1.1.5 root 1419: break;
1420: case 6:
1421: /* Set process priority to medium-low */
1.1.1.6 root 1422: prio = 3;
1.1.1.5 root 1423: break;
1424: case 2:
1425: /* Set process priority to normal */
1.1.1.6 root 1426: prio = 4;
1.1.1.5 root 1427: break;
1428: #if !defined(CONFIG_USER_ONLY)
1429: case 31:
1.1.1.6 root 1430: if (ctx->mem_idx > 0) {
1.1.1.5 root 1431: /* Set process priority to very low */
1.1.1.6 root 1432: prio = 1;
1.1.1.5 root 1433: }
1434: break;
1435: case 5:
1.1.1.6 root 1436: if (ctx->mem_idx > 0) {
1.1.1.5 root 1437: /* Set process priority to medium-hight */
1.1.1.6 root 1438: prio = 5;
1.1.1.5 root 1439: }
1440: break;
1441: case 3:
1.1.1.6 root 1442: if (ctx->mem_idx > 0) {
1.1.1.5 root 1443: /* Set process priority to high */
1.1.1.6 root 1444: prio = 6;
1.1.1.5 root 1445: }
1446: break;
1447: case 7:
1.1.1.6 root 1448: if (ctx->mem_idx > 1) {
1.1.1.5 root 1449: /* Set process priority to very high */
1.1.1.6 root 1450: prio = 7;
1.1.1.5 root 1451: }
1452: break;
1453: #endif
1454: default:
1455: /* nop */
1456: break;
1457: }
1.1.1.6 root 1458: if (prio) {
1459: TCGv t0 = tcg_temp_new();
1460: gen_load_spr(t0, SPR_PPR);
1461: tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1462: tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1463: gen_store_spr(SPR_PPR, t0);
1464: tcg_temp_free(t0);
1465: }
1.1.1.5 root 1466: #endif
1.1 root 1467: }
1468: }
1469: /* orc & orc. */
1.1.1.6 root 1470: GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1.1.1.7 root 1471:
1.1 root 1472: /* xor & xor. */
1.1.1.7 root 1473: static void gen_xor(DisasContext *ctx)
1.1 root 1474: {
1475: /* Optimisation for "set to zero" case */
1.1.1.6 root 1476: if (rS(ctx->opcode) != rB(ctx->opcode))
1477: tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1478: else
1479: tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1.1.1.5 root 1480: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1481: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1482: }
1.1.1.7 root 1483:
1.1 root 1484: /* ori */
1.1.1.7 root 1485: static void gen_ori(DisasContext *ctx)
1.1 root 1486: {
1.1.1.5 root 1487: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1488:
1489: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1490: /* NOP */
1.1.1.5 root 1491: /* XXX: should handle special NOPs for POWER series */
1.1 root 1492: return;
1.1.1.5 root 1493: }
1.1.1.6 root 1494: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1.1 root 1495: }
1.1.1.7 root 1496:
1.1 root 1497: /* oris */
1.1.1.7 root 1498: static void gen_oris(DisasContext *ctx)
1.1 root 1499: {
1.1.1.5 root 1500: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1501:
1502: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1503: /* NOP */
1504: return;
1.1.1.5 root 1505: }
1.1.1.6 root 1506: tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1.1 root 1507: }
1.1.1.7 root 1508:
1.1 root 1509: /* xori */
1.1.1.7 root 1510: static void gen_xori(DisasContext *ctx)
1.1 root 1511: {
1.1.1.5 root 1512: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1513:
1514: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1515: /* NOP */
1516: return;
1517: }
1.1.1.6 root 1518: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1.1 root 1519: }
1.1.1.7 root 1520:
1.1 root 1521: /* xoris */
1.1.1.7 root 1522: static void gen_xoris(DisasContext *ctx)
1.1 root 1523: {
1.1.1.5 root 1524: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1525:
1526: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1527: /* NOP */
1528: return;
1529: }
1.1.1.6 root 1530: tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1.1.1.5 root 1531: }
1.1.1.7 root 1532:
1.1.1.5 root 1533: /* popcntb : PowerPC 2.03 specification */
1.1.1.7 root 1534: static void gen_popcntb(DisasContext *ctx)
1.1.1.5 root 1535: {
1.1.1.11 root 1536: gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1537: }
1538:
1539: static void gen_popcntw(DisasContext *ctx)
1540: {
1541: gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1542: }
1543:
1.1.1.5 root 1544: #if defined(TARGET_PPC64)
1.1.1.11 root 1545: /* popcntd: PowerPC 2.06 specification */
1546: static void gen_popcntd(DisasContext *ctx)
1547: {
1548: gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1 root 1549: }
1.1.1.11 root 1550: #endif
1.1 root 1551:
1.1.1.5 root 1552: #if defined(TARGET_PPC64)
1553: /* extsw & extsw. */
1.1.1.6 root 1554: GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1.1.1.7 root 1555:
1.1.1.5 root 1556: /* cntlzd */
1.1.1.7 root 1557: static void gen_cntlzd(DisasContext *ctx)
1.1.1.6 root 1558: {
1559: gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1560: if (unlikely(Rc(ctx->opcode) != 0))
1561: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1562: }
1.1.1.5 root 1563: #endif
1564:
1.1 root 1565: /*** Integer rotate ***/
1.1.1.7 root 1566:
1.1 root 1567: /* rlwimi & rlwimi. */
1.1.1.7 root 1568: static void gen_rlwimi(DisasContext *ctx)
1.1 root 1569: {
1.1.1.5 root 1570: uint32_t mb, me, sh;
1.1 root 1571:
1572: mb = MB(ctx->opcode);
1573: me = ME(ctx->opcode);
1.1.1.5 root 1574: sh = SH(ctx->opcode);
1.1.1.6 root 1575: if (likely(sh == 0 && mb == 0 && me == 31)) {
1576: tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1577: } else {
1578: target_ulong mask;
1579: TCGv t1;
1580: TCGv t0 = tcg_temp_new();
1581: #if defined(TARGET_PPC64)
1582: TCGv_i32 t2 = tcg_temp_new_i32();
1583: tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1584: tcg_gen_rotli_i32(t2, t2, sh);
1585: tcg_gen_extu_i32_i64(t0, t2);
1586: tcg_temp_free_i32(t2);
1587: #else
1588: tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1589: #endif
1590: #if defined(TARGET_PPC64)
1591: mb += 32;
1592: me += 32;
1593: #endif
1594: mask = MASK(mb, me);
1595: t1 = tcg_temp_new();
1596: tcg_gen_andi_tl(t0, t0, mask);
1597: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1598: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1599: tcg_temp_free(t0);
1600: tcg_temp_free(t1);
1601: }
1.1.1.5 root 1602: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1603: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1604: }
1.1.1.7 root 1605:
1.1 root 1606: /* rlwinm & rlwinm. */
1.1.1.7 root 1607: static void gen_rlwinm(DisasContext *ctx)
1.1 root 1608: {
1609: uint32_t mb, me, sh;
1.1.1.5 root 1610:
1.1 root 1611: sh = SH(ctx->opcode);
1612: mb = MB(ctx->opcode);
1613: me = ME(ctx->opcode);
1.1.1.6 root 1614:
1615: if (likely(mb == 0 && me == (31 - sh))) {
1616: if (likely(sh == 0)) {
1617: tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1618: } else {
1619: TCGv t0 = tcg_temp_new();
1620: tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1621: tcg_gen_shli_tl(t0, t0, sh);
1622: tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1623: tcg_temp_free(t0);
1.1 root 1624: }
1.1.1.6 root 1625: } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
1626: TCGv t0 = tcg_temp_new();
1627: tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1628: tcg_gen_shri_tl(t0, t0, mb);
1629: tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1630: tcg_temp_free(t0);
1631: } else {
1632: TCGv t0 = tcg_temp_new();
1633: #if defined(TARGET_PPC64)
1634: TCGv_i32 t1 = tcg_temp_new_i32();
1635: tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1636: tcg_gen_rotli_i32(t1, t1, sh);
1637: tcg_gen_extu_i32_i64(t0, t1);
1638: tcg_temp_free_i32(t1);
1639: #else
1640: tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1641: #endif
1.1.1.5 root 1642: #if defined(TARGET_PPC64)
1.1.1.6 root 1643: mb += 32;
1644: me += 32;
1.1.1.5 root 1645: #endif
1.1.1.6 root 1646: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1647: tcg_temp_free(t0);
1648: }
1.1.1.5 root 1649: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1650: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1651: }
1.1.1.7 root 1652:
1.1 root 1653: /* rlwnm & rlwnm. */
1.1.1.7 root 1654: static void gen_rlwnm(DisasContext *ctx)
1.1 root 1655: {
1656: uint32_t mb, me;
1.1.1.6 root 1657: TCGv t0;
1658: #if defined(TARGET_PPC64)
1659: TCGv_i32 t1, t2;
1660: #endif
1.1 root 1661:
1662: mb = MB(ctx->opcode);
1663: me = ME(ctx->opcode);
1.1.1.6 root 1664: t0 = tcg_temp_new();
1665: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1666: #if defined(TARGET_PPC64)
1667: t1 = tcg_temp_new_i32();
1668: t2 = tcg_temp_new_i32();
1669: tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1670: tcg_gen_trunc_i64_i32(t2, t0);
1671: tcg_gen_rotl_i32(t1, t1, t2);
1672: tcg_gen_extu_i32_i64(t0, t1);
1673: tcg_temp_free_i32(t1);
1674: tcg_temp_free_i32(t2);
1675: #else
1676: tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1677: #endif
1.1.1.5 root 1678: if (unlikely(mb != 0 || me != 31)) {
1679: #if defined(TARGET_PPC64)
1680: mb += 32;
1681: me += 32;
1682: #endif
1.1.1.6 root 1683: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1684: } else {
1685: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1.1 root 1686: }
1.1.1.6 root 1687: tcg_temp_free(t0);
1.1.1.5 root 1688: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1689: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1690: }
1691:
1692: #if defined(TARGET_PPC64)
1693: #define GEN_PPC64_R2(name, opc1, opc2) \
1.1.1.7 root 1694: static void glue(gen_, name##0)(DisasContext *ctx) \
1.1.1.5 root 1695: { \
1696: gen_##name(ctx, 0); \
1697: } \
1.1.1.7 root 1698: \
1699: static void glue(gen_, name##1)(DisasContext *ctx) \
1.1.1.5 root 1700: { \
1701: gen_##name(ctx, 1); \
1702: }
1703: #define GEN_PPC64_R4(name, opc1, opc2) \
1.1.1.7 root 1704: static void glue(gen_, name##0)(DisasContext *ctx) \
1.1.1.5 root 1705: { \
1706: gen_##name(ctx, 0, 0); \
1707: } \
1.1.1.7 root 1708: \
1709: static void glue(gen_, name##1)(DisasContext *ctx) \
1.1.1.5 root 1710: { \
1711: gen_##name(ctx, 0, 1); \
1712: } \
1.1.1.7 root 1713: \
1714: static void glue(gen_, name##2)(DisasContext *ctx) \
1.1.1.5 root 1715: { \
1716: gen_##name(ctx, 1, 0); \
1717: } \
1.1.1.7 root 1718: \
1719: static void glue(gen_, name##3)(DisasContext *ctx) \
1.1.1.5 root 1720: { \
1721: gen_##name(ctx, 1, 1); \
1722: }
1723:
1.1.1.8 root 1724: static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
1725: uint32_t sh)
1.1.1.5 root 1726: {
1.1.1.6 root 1727: if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1728: tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1729: } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1730: tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1731: } else {
1732: TCGv t0 = tcg_temp_new();
1733: tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1734: if (likely(mb == 0 && me == 63)) {
1735: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1736: } else {
1737: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1.1.1.5 root 1738: }
1.1.1.6 root 1739: tcg_temp_free(t0);
1.1.1.5 root 1740: }
1741: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1742: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1743: }
1744: /* rldicl - rldicl. */
1.1.1.8 root 1745: static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1.1.1.5 root 1746: {
1747: uint32_t sh, mb;
1748:
1749: sh = SH(ctx->opcode) | (shn << 5);
1750: mb = MB(ctx->opcode) | (mbn << 5);
1751: gen_rldinm(ctx, mb, 63, sh);
1752: }
1753: GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1754: /* rldicr - rldicr. */
1.1.1.8 root 1755: static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1.1.1.5 root 1756: {
1757: uint32_t sh, me;
1758:
1759: sh = SH(ctx->opcode) | (shn << 5);
1760: me = MB(ctx->opcode) | (men << 5);
1761: gen_rldinm(ctx, 0, me, sh);
1762: }
1763: GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1764: /* rldic - rldic. */
1.1.1.8 root 1765: static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1.1.1.5 root 1766: {
1767: uint32_t sh, mb;
1768:
1769: sh = SH(ctx->opcode) | (shn << 5);
1770: mb = MB(ctx->opcode) | (mbn << 5);
1771: gen_rldinm(ctx, mb, 63 - sh, sh);
1772: }
1773: GEN_PPC64_R4(rldic, 0x1E, 0x04);
1774:
1.1.1.8 root 1775: static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
1.1.1.5 root 1776: {
1.1.1.6 root 1777: TCGv t0;
1778:
1779: mb = MB(ctx->opcode);
1780: me = ME(ctx->opcode);
1781: t0 = tcg_temp_new();
1782: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1783: tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1.1.1.5 root 1784: if (unlikely(mb != 0 || me != 63)) {
1.1.1.6 root 1785: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1786: } else {
1787: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1.1.1.5 root 1788: }
1.1.1.6 root 1789: tcg_temp_free(t0);
1.1.1.5 root 1790: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1791: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1792: }
1793:
1794: /* rldcl - rldcl. */
1.1.1.8 root 1795: static inline void gen_rldcl(DisasContext *ctx, int mbn)
1.1.1.5 root 1796: {
1797: uint32_t mb;
1798:
1799: mb = MB(ctx->opcode) | (mbn << 5);
1800: gen_rldnm(ctx, mb, 63);
1801: }
1802: GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1803: /* rldcr - rldcr. */
1.1.1.8 root 1804: static inline void gen_rldcr(DisasContext *ctx, int men)
1.1.1.5 root 1805: {
1806: uint32_t me;
1807:
1808: me = MB(ctx->opcode) | (men << 5);
1809: gen_rldnm(ctx, 0, me);
1810: }
1811: GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1812: /* rldimi - rldimi. */
1.1.1.8 root 1813: static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1.1.1.5 root 1814: {
1815: uint32_t sh, mb, me;
1816:
1817: sh = SH(ctx->opcode) | (shn << 5);
1818: mb = MB(ctx->opcode) | (mbn << 5);
1819: me = 63 - sh;
1.1.1.6 root 1820: if (unlikely(sh == 0 && mb == 0)) {
1821: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1822: } else {
1823: TCGv t0, t1;
1824: target_ulong mask;
1825:
1826: t0 = tcg_temp_new();
1827: tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1828: t1 = tcg_temp_new();
1829: mask = MASK(mb, me);
1830: tcg_gen_andi_tl(t0, t0, mask);
1831: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1832: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1833: tcg_temp_free(t0);
1834: tcg_temp_free(t1);
1835: }
1.1.1.5 root 1836: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1837: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1838: }
1.1.1.5 root 1839: GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1840: #endif
1.1 root 1841:
1842: /*** Integer shift ***/
1.1.1.7 root 1843:
1.1 root 1844: /* slw & slw. */
1.1.1.7 root 1845: static void gen_slw(DisasContext *ctx)
1.1.1.6 root 1846: {
1.1.1.8 root 1847: TCGv t0, t1;
1.1.1.6 root 1848:
1.1.1.8 root 1849: t0 = tcg_temp_new();
1850: /* AND rS with a mask that is 0 when rB >= 0x20 */
1851: #if defined(TARGET_PPC64)
1852: tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1853: tcg_gen_sari_tl(t0, t0, 0x3f);
1854: #else
1855: tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1856: tcg_gen_sari_tl(t0, t0, 0x1f);
1857: #endif
1858: tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1859: t1 = tcg_temp_new();
1860: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1861: tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1862: tcg_temp_free(t1);
1.1.1.6 root 1863: tcg_temp_free(t0);
1.1.1.8 root 1864: tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.6 root 1865: if (unlikely(Rc(ctx->opcode) != 0))
1866: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1867: }
1.1.1.7 root 1868:
1.1 root 1869: /* sraw & sraw. */
1.1.1.7 root 1870: static void gen_sraw(DisasContext *ctx)
1.1.1.6 root 1871: {
1872: gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
1873: cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1874: if (unlikely(Rc(ctx->opcode) != 0))
1875: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1876: }
1.1.1.7 root 1877:
1.1 root 1878: /* srawi & srawi. */
1.1.1.7 root 1879: static void gen_srawi(DisasContext *ctx)
1.1 root 1880: {
1.1.1.6 root 1881: int sh = SH(ctx->opcode);
1882: if (sh != 0) {
1883: int l1, l2;
1884: TCGv t0;
1885: l1 = gen_new_label();
1886: l2 = gen_new_label();
1887: t0 = tcg_temp_local_new();
1888: tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1889: tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
1890: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1891: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1892: tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1893: tcg_gen_br(l2);
1894: gen_set_label(l1);
1895: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1896: gen_set_label(l2);
1897: tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1898: tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
1899: tcg_temp_free(t0);
1900: } else {
1901: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1902: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1.1.1.5 root 1903: }
1904: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1905: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1 root 1906: }
1.1.1.7 root 1907:
1.1 root 1908: /* srw & srw. */
1.1.1.7 root 1909: static void gen_srw(DisasContext *ctx)
1.1.1.6 root 1910: {
1911: TCGv t0, t1;
1912:
1.1.1.8 root 1913: t0 = tcg_temp_new();
1914: /* AND rS with a mask that is 0 when rB >= 0x20 */
1915: #if defined(TARGET_PPC64)
1916: tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1917: tcg_gen_sari_tl(t0, t0, 0x3f);
1918: #else
1919: tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1920: tcg_gen_sari_tl(t0, t0, 0x1f);
1921: #endif
1922: tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1923: tcg_gen_ext32u_tl(t0, t0);
1.1.1.6 root 1924: t1 = tcg_temp_new();
1.1.1.8 root 1925: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1926: tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1.1.1.6 root 1927: tcg_temp_free(t1);
1928: tcg_temp_free(t0);
1929: if (unlikely(Rc(ctx->opcode) != 0))
1930: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1931: }
1.1.1.7 root 1932:
1.1.1.5 root 1933: #if defined(TARGET_PPC64)
1934: /* sld & sld. */
1.1.1.7 root 1935: static void gen_sld(DisasContext *ctx)
1.1.1.6 root 1936: {
1.1.1.8 root 1937: TCGv t0, t1;
1.1.1.6 root 1938:
1.1.1.8 root 1939: t0 = tcg_temp_new();
1940: /* AND rS with a mask that is 0 when rB >= 0x40 */
1941: tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1942: tcg_gen_sari_tl(t0, t0, 0x3f);
1943: tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1944: t1 = tcg_temp_new();
1945: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1946: tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1947: tcg_temp_free(t1);
1.1.1.6 root 1948: tcg_temp_free(t0);
1949: if (unlikely(Rc(ctx->opcode) != 0))
1950: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1951: }
1.1.1.7 root 1952:
1.1.1.5 root 1953: /* srad & srad. */
1.1.1.7 root 1954: static void gen_srad(DisasContext *ctx)
1.1.1.6 root 1955: {
1956: gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
1957: cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1958: if (unlikely(Rc(ctx->opcode) != 0))
1959: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1960: }
1.1.1.5 root 1961: /* sradi & sradi. */
1.1.1.8 root 1962: static inline void gen_sradi(DisasContext *ctx, int n)
1.1.1.5 root 1963: {
1.1.1.6 root 1964: int sh = SH(ctx->opcode) + (n << 5);
1.1.1.5 root 1965: if (sh != 0) {
1.1.1.6 root 1966: int l1, l2;
1967: TCGv t0;
1968: l1 = gen_new_label();
1969: l2 = gen_new_label();
1970: t0 = tcg_temp_local_new();
1971: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
1972: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1973: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1974: tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1975: tcg_gen_br(l2);
1976: gen_set_label(l1);
1977: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1978: gen_set_label(l2);
1979: tcg_temp_free(t0);
1980: tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1981: } else {
1982: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1983: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1.1.1.5 root 1984: }
1985: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 1986: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 1987: }
1.1.1.7 root 1988:
1989: static void gen_sradi0(DisasContext *ctx)
1.1.1.5 root 1990: {
1991: gen_sradi(ctx, 0);
1992: }
1.1.1.7 root 1993:
1994: static void gen_sradi1(DisasContext *ctx)
1.1.1.5 root 1995: {
1996: gen_sradi(ctx, 1);
1997: }
1.1.1.7 root 1998:
1.1.1.5 root 1999: /* srd & srd. */
1.1.1.7 root 2000: static void gen_srd(DisasContext *ctx)
1.1.1.6 root 2001: {
1.1.1.8 root 2002: TCGv t0, t1;
1.1.1.6 root 2003:
1.1.1.8 root 2004: t0 = tcg_temp_new();
2005: /* AND rS with a mask that is 0 when rB >= 0x40 */
2006: tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
2007: tcg_gen_sari_tl(t0, t0, 0x3f);
2008: tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2009: t1 = tcg_temp_new();
2010: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
2011: tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2012: tcg_temp_free(t1);
1.1.1.6 root 2013: tcg_temp_free(t0);
2014: if (unlikely(Rc(ctx->opcode) != 0))
2015: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2016: }
1.1.1.5 root 2017: #endif
1.1 root 2018:
2019: /*** Floating-Point arithmetic ***/
1.1.1.5 root 2020: #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
1.1.1.7 root 2021: static void gen_f##name(DisasContext *ctx) \
1.1 root 2022: { \
1.1.1.5 root 2023: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2024: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2025: return; \
2026: } \
1.1.1.6 root 2027: /* NIP cannot be restored if the memory exception comes from an helper */ \
2028: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2029: gen_reset_fpstatus(); \
1.1.1.6 root 2030: gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2031: cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
1.1 root 2032: if (isfloat) { \
1.1.1.6 root 2033: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
1.1 root 2034: } \
1.1.1.6 root 2035: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf, \
2036: Rc(ctx->opcode) != 0); \
1.1 root 2037: }
2038:
1.1.1.5 root 2039: #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
2040: _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
2041: _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1.1 root 2042:
1.1.1.5 root 2043: #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1.1.1.7 root 2044: static void gen_f##name(DisasContext *ctx) \
1.1 root 2045: { \
1.1.1.5 root 2046: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2047: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2048: return; \
2049: } \
1.1.1.6 root 2050: /* NIP cannot be restored if the memory exception comes from an helper */ \
2051: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2052: gen_reset_fpstatus(); \
1.1.1.6 root 2053: gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2054: cpu_fpr[rB(ctx->opcode)]); \
1.1 root 2055: if (isfloat) { \
1.1.1.6 root 2056: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
1.1 root 2057: } \
1.1.1.6 root 2058: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2059: set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 2060: }
1.1.1.5 root 2061: #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
2062: _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2063: _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1.1 root 2064:
1.1.1.5 root 2065: #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1.1.1.7 root 2066: static void gen_f##name(DisasContext *ctx) \
1.1 root 2067: { \
1.1.1.5 root 2068: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2069: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2070: return; \
2071: } \
1.1.1.6 root 2072: /* NIP cannot be restored if the memory exception comes from an helper */ \
2073: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2074: gen_reset_fpstatus(); \
1.1.1.6 root 2075: gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2076: cpu_fpr[rC(ctx->opcode)]); \
1.1 root 2077: if (isfloat) { \
1.1.1.6 root 2078: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
1.1 root 2079: } \
1.1.1.6 root 2080: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2081: set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 2082: }
1.1.1.5 root 2083: #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
2084: _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2085: _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1.1 root 2086:
1.1.1.5 root 2087: #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
1.1.1.7 root 2088: static void gen_f##name(DisasContext *ctx) \
1.1 root 2089: { \
1.1.1.5 root 2090: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2091: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2092: return; \
2093: } \
1.1.1.6 root 2094: /* NIP cannot be restored if the memory exception comes from an helper */ \
2095: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2096: gen_reset_fpstatus(); \
1.1.1.6 root 2097: gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
2098: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2099: set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 2100: }
2101:
1.1.1.5 root 2102: #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
1.1.1.7 root 2103: static void gen_f##name(DisasContext *ctx) \
1.1 root 2104: { \
1.1.1.5 root 2105: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 2106: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 2107: return; \
2108: } \
1.1.1.6 root 2109: /* NIP cannot be restored if the memory exception comes from an helper */ \
2110: gen_update_nip(ctx, ctx->nip - 4); \
1.1.1.5 root 2111: gen_reset_fpstatus(); \
1.1.1.6 root 2112: gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
2113: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2114: set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 2115: }
2116:
2117: /* fadd - fadds */
1.1.1.5 root 2118: GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1.1 root 2119: /* fdiv - fdivs */
1.1.1.5 root 2120: GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1.1 root 2121: /* fmul - fmuls */
1.1.1.5 root 2122: GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2123:
2124: /* fre */
2125: GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1.1 root 2126:
2127: /* fres */
1.1.1.5 root 2128: GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
1.1 root 2129:
2130: /* frsqrte */
1.1.1.5 root 2131: GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2132:
2133: /* frsqrtes */
1.1.1.7 root 2134: static void gen_frsqrtes(DisasContext *ctx)
1.1.1.5 root 2135: {
1.1.1.6 root 2136: if (unlikely(!ctx->fpu_enabled)) {
2137: gen_exception(ctx, POWERPC_EXCP_FPU);
2138: return;
2139: }
2140: /* NIP cannot be restored if the memory exception comes from an helper */
2141: gen_update_nip(ctx, ctx->nip - 4);
2142: gen_reset_fpstatus();
2143: gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2144: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2145: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
1.1.1.5 root 2146: }
1.1 root 2147:
2148: /* fsel */
1.1.1.5 root 2149: _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1.1 root 2150: /* fsub - fsubs */
1.1.1.5 root 2151: GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
1.1 root 2152: /* Optional: */
1.1.1.7 root 2153:
1.1 root 2154: /* fsqrt */
1.1.1.7 root 2155: static void gen_fsqrt(DisasContext *ctx)
1.1 root 2156: {
1.1.1.5 root 2157: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2158: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2159: return;
2160: }
1.1.1.6 root 2161: /* NIP cannot be restored if the memory exception comes from an helper */
2162: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2163: gen_reset_fpstatus();
1.1.1.6 root 2164: gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2165: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
1.1 root 2166: }
2167:
1.1.1.7 root 2168: static void gen_fsqrts(DisasContext *ctx)
1.1 root 2169: {
1.1.1.5 root 2170: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2171: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2172: return;
2173: }
1.1.1.6 root 2174: /* NIP cannot be restored if the memory exception comes from an helper */
2175: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2176: gen_reset_fpstatus();
1.1.1.6 root 2177: gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2178: gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2179: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
1.1 root 2180: }
2181:
2182: /*** Floating-Point multiply-and-add ***/
2183: /* fmadd - fmadds */
1.1.1.5 root 2184: GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1.1 root 2185: /* fmsub - fmsubs */
1.1.1.5 root 2186: GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1.1 root 2187: /* fnmadd - fnmadds */
1.1.1.5 root 2188: GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1.1 root 2189: /* fnmsub - fnmsubs */
1.1.1.5 root 2190: GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
1.1 root 2191:
2192: /*** Floating-Point round & convert ***/
2193: /* fctiw */
1.1.1.5 root 2194: GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
1.1 root 2195: /* fctiwz */
1.1.1.5 root 2196: GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
1.1 root 2197: /* frsp */
1.1.1.5 root 2198: GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2199: #if defined(TARGET_PPC64)
2200: /* fcfid */
2201: GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
2202: /* fctid */
2203: GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
2204: /* fctidz */
2205: GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
2206: #endif
2207:
2208: /* frin */
2209: GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2210: /* friz */
2211: GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2212: /* frip */
2213: GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2214: /* frim */
2215: GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1.1 root 2216:
2217: /*** Floating-Point compare ***/
1.1.1.7 root 2218:
1.1 root 2219: /* fcmpo */
1.1.1.7 root 2220: static void gen_fcmpo(DisasContext *ctx)
1.1 root 2221: {
1.1.1.6 root 2222: TCGv_i32 crf;
1.1.1.5 root 2223: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2224: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2225: return;
2226: }
1.1.1.6 root 2227: /* NIP cannot be restored if the memory exception comes from an helper */
2228: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2229: gen_reset_fpstatus();
1.1.1.6 root 2230: crf = tcg_const_i32(crfD(ctx->opcode));
2231: gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2232: tcg_temp_free_i32(crf);
2233: gen_helper_float_check_status();
1.1 root 2234: }
2235:
2236: /* fcmpu */
1.1.1.7 root 2237: static void gen_fcmpu(DisasContext *ctx)
1.1 root 2238: {
1.1.1.6 root 2239: TCGv_i32 crf;
1.1.1.5 root 2240: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2241: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2242: return;
2243: }
1.1.1.6 root 2244: /* NIP cannot be restored if the memory exception comes from an helper */
2245: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2246: gen_reset_fpstatus();
1.1.1.6 root 2247: crf = tcg_const_i32(crfD(ctx->opcode));
2248: gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2249: tcg_temp_free_i32(crf);
2250: gen_helper_float_check_status();
1.1 root 2251: }
2252:
2253: /*** Floating-point move ***/
2254: /* fabs */
1.1.1.5 root 2255: /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2256: GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1.1 root 2257:
2258: /* fmr - fmr. */
1.1.1.5 root 2259: /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1.1.1.7 root 2260: static void gen_fmr(DisasContext *ctx)
1.1 root 2261: {
1.1.1.5 root 2262: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2263: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2264: return;
2265: }
1.1.1.6 root 2266: tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2267: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
1.1 root 2268: }
2269:
2270: /* fnabs */
1.1.1.5 root 2271: /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2272: GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1.1 root 2273: /* fneg */
1.1.1.5 root 2274: /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2275: GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1.1 root 2276:
2277: /*** Floating-Point status & ctrl register ***/
1.1.1.7 root 2278:
1.1 root 2279: /* mcrfs */
1.1.1.7 root 2280: static void gen_mcrfs(DisasContext *ctx)
1.1 root 2281: {
1.1.1.5 root 2282: int bfa;
2283:
2284: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2285: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2286: return;
2287: }
1.1.1.5 root 2288: bfa = 4 * (7 - crfS(ctx->opcode));
1.1.1.6 root 2289: tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2290: tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2291: tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
1.1 root 2292: }
2293:
2294: /* mffs */
1.1.1.7 root 2295: static void gen_mffs(DisasContext *ctx)
1.1 root 2296: {
1.1.1.5 root 2297: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2298: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2299: return;
2300: }
1.1.1.5 root 2301: gen_reset_fpstatus();
1.1.1.6 root 2302: tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2303: gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
1.1 root 2304: }
2305:
2306: /* mtfsb0 */
1.1.1.7 root 2307: static void gen_mtfsb0(DisasContext *ctx)
1.1 root 2308: {
2309: uint8_t crb;
1.1.1.5 root 2310:
2311: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2312: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2313: return;
2314: }
1.1.1.6 root 2315: crb = 31 - crbD(ctx->opcode);
1.1.1.5 root 2316: gen_reset_fpstatus();
1.1.1.6 root 2317: if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2318: TCGv_i32 t0;
2319: /* NIP cannot be restored if the memory exception comes from an helper */
2320: gen_update_nip(ctx, ctx->nip - 4);
2321: t0 = tcg_const_i32(crb);
2322: gen_helper_fpscr_clrbit(t0);
2323: tcg_temp_free_i32(t0);
2324: }
1.1.1.5 root 2325: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2326: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2327: }
1.1 root 2328: }
2329:
2330: /* mtfsb1 */
1.1.1.7 root 2331: static void gen_mtfsb1(DisasContext *ctx)
1.1 root 2332: {
2333: uint8_t crb;
1.1.1.5 root 2334:
2335: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2336: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2337: return;
2338: }
1.1.1.6 root 2339: crb = 31 - crbD(ctx->opcode);
1.1.1.5 root 2340: gen_reset_fpstatus();
2341: /* XXX: we pretend we can only do IEEE floating-point computations */
1.1.1.6 root 2342: if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2343: TCGv_i32 t0;
2344: /* NIP cannot be restored if the memory exception comes from an helper */
2345: gen_update_nip(ctx, ctx->nip - 4);
2346: t0 = tcg_const_i32(crb);
2347: gen_helper_fpscr_setbit(t0);
2348: tcg_temp_free_i32(t0);
2349: }
1.1.1.5 root 2350: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2351: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2352: }
2353: /* We can raise a differed exception */
1.1.1.6 root 2354: gen_helper_float_check_status();
1.1 root 2355: }
2356:
2357: /* mtfsf */
1.1.1.7 root 2358: static void gen_mtfsf(DisasContext *ctx)
1.1 root 2359: {
1.1.1.6 root 2360: TCGv_i32 t0;
1.1.1.7 root 2361: int L = ctx->opcode & 0x02000000;
1.1.1.6 root 2362:
1.1.1.5 root 2363: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2364: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2365: return;
2366: }
1.1.1.6 root 2367: /* NIP cannot be restored if the memory exception comes from an helper */
2368: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2369: gen_reset_fpstatus();
1.1.1.7 root 2370: if (L)
2371: t0 = tcg_const_i32(0xff);
2372: else
2373: t0 = tcg_const_i32(FM(ctx->opcode));
1.1.1.6 root 2374: gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2375: tcg_temp_free_i32(t0);
1.1.1.5 root 2376: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2377: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2378: }
2379: /* We can raise a differed exception */
1.1.1.6 root 2380: gen_helper_float_check_status();
1.1 root 2381: }
2382:
2383: /* mtfsfi */
1.1.1.7 root 2384: static void gen_mtfsfi(DisasContext *ctx)
1.1 root 2385: {
1.1.1.5 root 2386: int bf, sh;
1.1.1.6 root 2387: TCGv_i64 t0;
2388: TCGv_i32 t1;
1.1.1.5 root 2389:
2390: if (unlikely(!ctx->fpu_enabled)) {
1.1.1.6 root 2391: gen_exception(ctx, POWERPC_EXCP_FPU);
1.1 root 2392: return;
2393: }
1.1.1.5 root 2394: bf = crbD(ctx->opcode) >> 2;
2395: sh = 7 - bf;
1.1.1.6 root 2396: /* NIP cannot be restored if the memory exception comes from an helper */
2397: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.5 root 2398: gen_reset_fpstatus();
1.1.1.6 root 2399: t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
2400: t1 = tcg_const_i32(1 << sh);
2401: gen_helper_store_fpscr(t0, t1);
2402: tcg_temp_free_i64(t0);
2403: tcg_temp_free_i32(t1);
1.1.1.5 root 2404: if (unlikely(Rc(ctx->opcode) != 0)) {
1.1.1.6 root 2405: tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
1.1.1.5 root 2406: }
2407: /* We can raise a differed exception */
1.1.1.6 root 2408: gen_helper_float_check_status();
1.1 root 2409: }
2410:
1.1.1.5 root 2411: /*** Addressing modes ***/
2412: /* Register indirect with immediate index : EA = (rA|0) + SIMM */
1.1.1.8 root 2413: static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2414: target_long maskl)
1.1.1.5 root 2415: {
2416: target_long simm = SIMM(ctx->opcode);
2417:
2418: simm &= ~maskl;
2419: if (rA(ctx->opcode) == 0) {
1.1.1.6 root 2420: #if defined(TARGET_PPC64)
2421: if (!ctx->sf_mode) {
2422: tcg_gen_movi_tl(EA, (uint32_t)simm);
2423: } else
2424: #endif
2425: tcg_gen_movi_tl(EA, simm);
2426: } else if (likely(simm != 0)) {
2427: tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2428: #if defined(TARGET_PPC64)
2429: if (!ctx->sf_mode) {
2430: tcg_gen_ext32u_tl(EA, EA);
2431: }
2432: #endif
1.1.1.5 root 2433: } else {
1.1.1.6 root 2434: #if defined(TARGET_PPC64)
2435: if (!ctx->sf_mode) {
2436: tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2437: } else
1.1.1.5 root 2438: #endif
1.1.1.6 root 2439: tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2440: }
1.1.1.5 root 2441: }
2442:
1.1.1.8 root 2443: static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
1.1.1.5 root 2444: {
2445: if (rA(ctx->opcode) == 0) {
1.1.1.6 root 2446: #if defined(TARGET_PPC64)
2447: if (!ctx->sf_mode) {
2448: tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2449: } else
2450: #endif
2451: tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 2452: } else {
1.1.1.6 root 2453: tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2454: #if defined(TARGET_PPC64)
2455: if (!ctx->sf_mode) {
2456: tcg_gen_ext32u_tl(EA, EA);
2457: }
1.1.1.5 root 2458: #endif
1.1.1.6 root 2459: }
1.1.1.5 root 2460: }
2461:
1.1.1.8 root 2462: static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
1.1.1.5 root 2463: {
2464: if (rA(ctx->opcode) == 0) {
1.1.1.6 root 2465: tcg_gen_movi_tl(EA, 0);
1.1.1.5 root 2466: } else {
1.1.1.6 root 2467: #if defined(TARGET_PPC64)
2468: if (!ctx->sf_mode) {
2469: tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2470: } else
2471: #endif
2472: tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2473: }
2474: }
2475:
1.1.1.8 root 2476: static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2477: target_long val)
1.1.1.6 root 2478: {
2479: tcg_gen_addi_tl(ret, arg1, val);
2480: #if defined(TARGET_PPC64)
2481: if (!ctx->sf_mode) {
2482: tcg_gen_ext32u_tl(ret, ret);
1.1.1.5 root 2483: }
2484: #endif
2485: }
2486:
1.1.1.8 root 2487: static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
1.1.1.6 root 2488: {
2489: int l1 = gen_new_label();
2490: TCGv t0 = tcg_temp_new();
2491: TCGv_i32 t1, t2;
2492: /* NIP cannot be restored if the memory exception comes from an helper */
2493: gen_update_nip(ctx, ctx->nip - 4);
2494: tcg_gen_andi_tl(t0, EA, mask);
2495: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2496: t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2497: t2 = tcg_const_i32(0);
2498: gen_helper_raise_exception_err(t1, t2);
2499: tcg_temp_free_i32(t1);
2500: tcg_temp_free_i32(t2);
2501: gen_set_label(l1);
2502: tcg_temp_free(t0);
2503: }
2504:
2505: /*** Integer load ***/
1.1.1.8 root 2506: static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2507: {
2508: tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2509: }
2510:
1.1.1.8 root 2511: static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2512: {
2513: tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2514: }
2515:
1.1.1.8 root 2516: static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2517: {
2518: tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2519: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2520: tcg_gen_bswap16_tl(arg1, arg1);
1.1.1.6 root 2521: }
2522: }
2523:
1.1.1.8 root 2524: static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2525: {
2526: if (unlikely(ctx->le_mode)) {
2527: tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
1.1.1.7 root 2528: tcg_gen_bswap16_tl(arg1, arg1);
1.1.1.6 root 2529: tcg_gen_ext16s_tl(arg1, arg1);
2530: } else {
2531: tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2532: }
2533: }
2534:
1.1.1.8 root 2535: static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2536: {
2537: tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2538: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2539: tcg_gen_bswap32_tl(arg1, arg1);
1.1.1.6 root 2540: }
1.1 root 2541: }
2542:
1.1.1.6 root 2543: #if defined(TARGET_PPC64)
1.1.1.8 root 2544: static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2545: {
2546: if (unlikely(ctx->le_mode)) {
2547: tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
1.1.1.7 root 2548: tcg_gen_bswap32_tl(arg1, arg1);
2549: tcg_gen_ext32s_tl(arg1, arg1);
1.1.1.6 root 2550: } else
2551: tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
2552: }
2553: #endif
2554:
1.1.1.8 root 2555: static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 2556: {
2557: tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2558: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2559: tcg_gen_bswap64_i64(arg1, arg1);
1.1.1.6 root 2560: }
2561: }
2562:
1.1.1.8 root 2563: static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2564: {
2565: tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2566: }
2567:
1.1.1.8 root 2568: static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2569: {
2570: if (unlikely(ctx->le_mode)) {
2571: TCGv t0 = tcg_temp_new();
2572: tcg_gen_ext16u_tl(t0, arg1);
1.1.1.7 root 2573: tcg_gen_bswap16_tl(t0, t0);
1.1.1.6 root 2574: tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2575: tcg_temp_free(t0);
2576: } else {
2577: tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2578: }
2579: }
2580:
1.1.1.8 root 2581: static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2582: {
2583: if (unlikely(ctx->le_mode)) {
1.1.1.7 root 2584: TCGv t0 = tcg_temp_new();
2585: tcg_gen_ext32u_tl(t0, arg1);
2586: tcg_gen_bswap32_tl(t0, t0);
1.1.1.6 root 2587: tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2588: tcg_temp_free(t0);
2589: } else {
2590: tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2591: }
2592: }
2593:
1.1.1.8 root 2594: static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 2595: {
2596: if (unlikely(ctx->le_mode)) {
2597: TCGv_i64 t0 = tcg_temp_new_i64();
1.1.1.7 root 2598: tcg_gen_bswap64_i64(t0, arg1);
1.1.1.6 root 2599: tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
2600: tcg_temp_free_i64(t0);
2601: } else
2602: tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
2603: }
2604:
2605: #define GEN_LD(name, ldop, opc, type) \
1.1.1.7 root 2606: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 2607: { \
2608: TCGv EA; \
2609: gen_set_access_type(ctx, ACCESS_INT); \
2610: EA = tcg_temp_new(); \
2611: gen_addr_imm_index(ctx, EA, 0); \
2612: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2613: tcg_temp_free(EA); \
2614: }
2615:
2616: #define GEN_LDU(name, ldop, opc, type) \
1.1.1.7 root 2617: static void glue(gen_, name##u)(DisasContext *ctx) \
1.1 root 2618: { \
1.1.1.6 root 2619: TCGv EA; \
1.1.1.5 root 2620: if (unlikely(rA(ctx->opcode) == 0 || \
2621: rA(ctx->opcode) == rD(ctx->opcode))) { \
1.1.1.6 root 2622: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2623: return; \
2624: } \
1.1.1.6 root 2625: gen_set_access_type(ctx, ACCESS_INT); \
2626: EA = tcg_temp_new(); \
1.1.1.5 root 2627: if (type == PPC_64B) \
1.1.1.6 root 2628: gen_addr_imm_index(ctx, EA, 0x03); \
1.1.1.5 root 2629: else \
1.1.1.6 root 2630: gen_addr_imm_index(ctx, EA, 0); \
2631: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2632: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2633: tcg_temp_free(EA); \
1.1 root 2634: }
2635:
1.1.1.6 root 2636: #define GEN_LDUX(name, ldop, opc2, opc3, type) \
1.1.1.7 root 2637: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 2638: { \
1.1.1.6 root 2639: TCGv EA; \
1.1.1.5 root 2640: if (unlikely(rA(ctx->opcode) == 0 || \
2641: rA(ctx->opcode) == rD(ctx->opcode))) { \
1.1.1.6 root 2642: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2643: return; \
2644: } \
1.1.1.6 root 2645: gen_set_access_type(ctx, ACCESS_INT); \
2646: EA = tcg_temp_new(); \
2647: gen_addr_reg_index(ctx, EA); \
2648: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2649: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2650: tcg_temp_free(EA); \
2651: }
2652:
1.1.1.13! root 2653: #define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
1.1.1.7 root 2654: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1.1.6 root 2655: { \
2656: TCGv EA; \
2657: gen_set_access_type(ctx, ACCESS_INT); \
2658: EA = tcg_temp_new(); \
2659: gen_addr_reg_index(ctx, EA); \
2660: gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
2661: tcg_temp_free(EA); \
2662: }
1.1.1.13! root 2663: #define GEN_LDX(name, ldop, opc2, opc3, type) \
! 2664: GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
1.1.1.6 root 2665:
2666: #define GEN_LDS(name, ldop, op, type) \
2667: GEN_LD(name, ldop, op | 0x20, type); \
2668: GEN_LDU(name, ldop, op | 0x21, type); \
2669: GEN_LDUX(name, ldop, 0x17, op | 0x01, type); \
2670: GEN_LDX(name, ldop, 0x17, op | 0x00, type)
1.1 root 2671:
2672: /* lbz lbzu lbzux lbzx */
1.1.1.6 root 2673: GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
1.1 root 2674: /* lha lhau lhaux lhax */
1.1.1.6 root 2675: GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
1.1 root 2676: /* lhz lhzu lhzux lhzx */
1.1.1.6 root 2677: GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
1.1 root 2678: /* lwz lwzu lwzux lwzx */
1.1.1.6 root 2679: GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
1.1.1.5 root 2680: #if defined(TARGET_PPC64)
2681: /* lwaux */
1.1.1.6 root 2682: GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
1.1.1.5 root 2683: /* lwax */
1.1.1.6 root 2684: GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
1.1.1.5 root 2685: /* ldux */
1.1.1.6 root 2686: GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
1.1.1.5 root 2687: /* ldx */
1.1.1.6 root 2688: GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
1.1.1.7 root 2689:
2690: static void gen_ld(DisasContext *ctx)
1.1.1.5 root 2691: {
1.1.1.6 root 2692: TCGv EA;
1.1.1.5 root 2693: if (Rc(ctx->opcode)) {
2694: if (unlikely(rA(ctx->opcode) == 0 ||
2695: rA(ctx->opcode) == rD(ctx->opcode))) {
1.1.1.6 root 2696: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2697: return;
2698: }
2699: }
1.1.1.6 root 2700: gen_set_access_type(ctx, ACCESS_INT);
2701: EA = tcg_temp_new();
2702: gen_addr_imm_index(ctx, EA, 0x03);
1.1.1.5 root 2703: if (ctx->opcode & 0x02) {
2704: /* lwa (lwau is undefined) */
1.1.1.6 root 2705: gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
1.1.1.5 root 2706: } else {
2707: /* ld - ldu */
1.1.1.6 root 2708: gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
1.1.1.5 root 2709: }
2710: if (Rc(ctx->opcode))
1.1.1.6 root 2711: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2712: tcg_temp_free(EA);
1.1.1.5 root 2713: }
1.1.1.7 root 2714:
1.1.1.5 root 2715: /* lq */
1.1.1.7 root 2716: static void gen_lq(DisasContext *ctx)
1.1.1.5 root 2717: {
2718: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 2719: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2720: #else
2721: int ra, rd;
1.1.1.6 root 2722: TCGv EA;
1.1.1.5 root 2723:
2724: /* Restore CPU state */
1.1.1.6 root 2725: if (unlikely(ctx->mem_idx == 0)) {
2726: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2727: return;
2728: }
2729: ra = rA(ctx->opcode);
2730: rd = rD(ctx->opcode);
2731: if (unlikely((rd & 1) || rd == ra)) {
1.1.1.6 root 2732: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2733: return;
2734: }
1.1.1.6 root 2735: if (unlikely(ctx->le_mode)) {
1.1.1.5 root 2736: /* Little-endian mode is not handled */
1.1.1.6 root 2737: gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
1.1.1.5 root 2738: return;
2739: }
1.1.1.6 root 2740: gen_set_access_type(ctx, ACCESS_INT);
2741: EA = tcg_temp_new();
2742: gen_addr_imm_index(ctx, EA, 0x0F);
2743: gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2744: gen_addr_add(ctx, EA, EA, 8);
2745: gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2746: tcg_temp_free(EA);
1.1.1.5 root 2747: #endif
2748: }
2749: #endif
1.1 root 2750:
2751: /*** Integer store ***/
1.1.1.6 root 2752: #define GEN_ST(name, stop, opc, type) \
1.1.1.7 root 2753: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 2754: { \
1.1.1.6 root 2755: TCGv EA; \
2756: gen_set_access_type(ctx, ACCESS_INT); \
2757: EA = tcg_temp_new(); \
2758: gen_addr_imm_index(ctx, EA, 0); \
2759: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2760: tcg_temp_free(EA); \
1.1 root 2761: }
2762:
1.1.1.6 root 2763: #define GEN_STU(name, stop, opc, type) \
1.1.1.7 root 2764: static void glue(gen_, stop##u)(DisasContext *ctx) \
1.1 root 2765: { \
1.1.1.6 root 2766: TCGv EA; \
1.1.1.5 root 2767: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 2768: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2769: return; \
2770: } \
1.1.1.6 root 2771: gen_set_access_type(ctx, ACCESS_INT); \
2772: EA = tcg_temp_new(); \
1.1.1.5 root 2773: if (type == PPC_64B) \
1.1.1.6 root 2774: gen_addr_imm_index(ctx, EA, 0x03); \
1.1.1.5 root 2775: else \
1.1.1.6 root 2776: gen_addr_imm_index(ctx, EA, 0); \
2777: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2778: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2779: tcg_temp_free(EA); \
1.1 root 2780: }
2781:
1.1.1.6 root 2782: #define GEN_STUX(name, stop, opc2, opc3, type) \
1.1.1.7 root 2783: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 2784: { \
1.1.1.6 root 2785: TCGv EA; \
1.1.1.5 root 2786: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 2787: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 2788: return; \
2789: } \
1.1.1.6 root 2790: gen_set_access_type(ctx, ACCESS_INT); \
2791: EA = tcg_temp_new(); \
2792: gen_addr_reg_index(ctx, EA); \
2793: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2794: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2795: tcg_temp_free(EA); \
2796: }
2797:
1.1.1.13! root 2798: #define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
! 2799: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1.1.6 root 2800: { \
2801: TCGv EA; \
2802: gen_set_access_type(ctx, ACCESS_INT); \
2803: EA = tcg_temp_new(); \
2804: gen_addr_reg_index(ctx, EA); \
2805: gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
2806: tcg_temp_free(EA); \
2807: }
1.1.1.13! root 2808: #define GEN_STX(name, stop, opc2, opc3, type) \
! 2809: GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
1.1.1.6 root 2810:
2811: #define GEN_STS(name, stop, op, type) \
2812: GEN_ST(name, stop, op | 0x20, type); \
2813: GEN_STU(name, stop, op | 0x21, type); \
2814: GEN_STUX(name, stop, 0x17, op | 0x01, type); \
2815: GEN_STX(name, stop, 0x17, op | 0x00, type)
1.1 root 2816:
2817: /* stb stbu stbux stbx */
1.1.1.6 root 2818: GEN_STS(stb, st8, 0x06, PPC_INTEGER);
1.1 root 2819: /* sth sthu sthux sthx */
1.1.1.6 root 2820: GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
1.1 root 2821: /* stw stwu stwux stwx */
1.1.1.6 root 2822: GEN_STS(stw, st32, 0x04, PPC_INTEGER);
1.1.1.5 root 2823: #if defined(TARGET_PPC64)
1.1.1.6 root 2824: GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2825: GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
1.1.1.7 root 2826:
2827: static void gen_std(DisasContext *ctx)
1.1.1.5 root 2828: {
2829: int rs;
1.1.1.6 root 2830: TCGv EA;
1.1 root 2831:
1.1.1.5 root 2832: rs = rS(ctx->opcode);
2833: if ((ctx->opcode & 0x3) == 0x2) {
2834: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 2835: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2836: #else
2837: /* stq */
1.1.1.6 root 2838: if (unlikely(ctx->mem_idx == 0)) {
2839: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 2840: return;
2841: }
2842: if (unlikely(rs & 1)) {
1.1.1.6 root 2843: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2844: return;
2845: }
1.1.1.6 root 2846: if (unlikely(ctx->le_mode)) {
1.1.1.5 root 2847: /* Little-endian mode is not handled */
1.1.1.6 root 2848: gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
1.1.1.5 root 2849: return;
2850: }
1.1.1.6 root 2851: gen_set_access_type(ctx, ACCESS_INT);
2852: EA = tcg_temp_new();
2853: gen_addr_imm_index(ctx, EA, 0x03);
2854: gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2855: gen_addr_add(ctx, EA, EA, 8);
2856: gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
2857: tcg_temp_free(EA);
1.1.1.5 root 2858: #endif
2859: } else {
2860: /* std / stdu */
2861: if (Rc(ctx->opcode)) {
2862: if (unlikely(rA(ctx->opcode) == 0)) {
1.1.1.6 root 2863: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 2864: return;
2865: }
2866: }
1.1.1.6 root 2867: gen_set_access_type(ctx, ACCESS_INT);
2868: EA = tcg_temp_new();
2869: gen_addr_imm_index(ctx, EA, 0x03);
2870: gen_qemu_st64(ctx, cpu_gpr[rs], EA);
1.1.1.5 root 2871: if (Rc(ctx->opcode))
1.1.1.6 root 2872: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2873: tcg_temp_free(EA);
1.1.1.5 root 2874: }
2875: }
2876: #endif
1.1 root 2877: /*** Integer load and store with byte reverse ***/
2878: /* lhbrx */
1.1.1.8 root 2879: static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2880: {
2881: tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2882: if (likely(!ctx->le_mode)) {
1.1.1.7 root 2883: tcg_gen_bswap16_tl(arg1, arg1);
1.1.1.6 root 2884: }
2885: }
2886: GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
2887:
1.1 root 2888: /* lwbrx */
1.1.1.8 root 2889: static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2890: {
2891: tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2892: if (likely(!ctx->le_mode)) {
1.1.1.7 root 2893: tcg_gen_bswap32_tl(arg1, arg1);
1.1.1.6 root 2894: }
2895: }
2896: GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
2897:
1.1.1.13! root 2898: #if defined(TARGET_PPC64)
! 2899: /* ldbrx */
! 2900: static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
! 2901: {
! 2902: tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
! 2903: if (likely(!ctx->le_mode)) {
! 2904: tcg_gen_bswap64_tl(arg1, arg1);
! 2905: }
! 2906: }
! 2907: GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
! 2908: #endif /* TARGET_PPC64 */
! 2909:
1.1 root 2910: /* sthbrx */
1.1.1.8 root 2911: static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2912: {
2913: if (likely(!ctx->le_mode)) {
2914: TCGv t0 = tcg_temp_new();
2915: tcg_gen_ext16u_tl(t0, arg1);
1.1.1.7 root 2916: tcg_gen_bswap16_tl(t0, t0);
1.1.1.6 root 2917: tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2918: tcg_temp_free(t0);
2919: } else {
2920: tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2921: }
2922: }
2923: GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
2924:
1.1 root 2925: /* stwbrx */
1.1.1.8 root 2926: static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
1.1.1.6 root 2927: {
2928: if (likely(!ctx->le_mode)) {
1.1.1.7 root 2929: TCGv t0 = tcg_temp_new();
2930: tcg_gen_ext32u_tl(t0, arg1);
2931: tcg_gen_bswap32_tl(t0, t0);
1.1.1.6 root 2932: tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2933: tcg_temp_free(t0);
2934: } else {
2935: tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2936: }
2937: }
2938: GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
1.1 root 2939:
1.1.1.13! root 2940: #if defined(TARGET_PPC64)
! 2941: /* stdbrx */
! 2942: static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
! 2943: {
! 2944: if (likely(!ctx->le_mode)) {
! 2945: TCGv t0 = tcg_temp_new();
! 2946: tcg_gen_bswap64_tl(t0, arg1);
! 2947: tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
! 2948: tcg_temp_free(t0);
! 2949: } else {
! 2950: tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
! 2951: }
! 2952: }
! 2953: GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
! 2954: #endif /* TARGET_PPC64 */
! 2955:
1.1 root 2956: /*** Integer load and store multiple ***/
1.1.1.7 root 2957:
1.1 root 2958: /* lmw */
1.1.1.7 root 2959: static void gen_lmw(DisasContext *ctx)
1.1 root 2960: {
1.1.1.6 root 2961: TCGv t0;
2962: TCGv_i32 t1;
2963: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 2964: /* NIP cannot be restored if the memory exception comes from an helper */
2965: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2966: t0 = tcg_temp_new();
2967: t1 = tcg_const_i32(rD(ctx->opcode));
2968: gen_addr_imm_index(ctx, t0, 0);
2969: gen_helper_lmw(t0, t1);
2970: tcg_temp_free(t0);
2971: tcg_temp_free_i32(t1);
1.1 root 2972: }
2973:
2974: /* stmw */
1.1.1.7 root 2975: static void gen_stmw(DisasContext *ctx)
1.1 root 2976: {
1.1.1.6 root 2977: TCGv t0;
2978: TCGv_i32 t1;
2979: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 2980: /* NIP cannot be restored if the memory exception comes from an helper */
2981: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 2982: t0 = tcg_temp_new();
2983: t1 = tcg_const_i32(rS(ctx->opcode));
2984: gen_addr_imm_index(ctx, t0, 0);
2985: gen_helper_stmw(t0, t1);
2986: tcg_temp_free(t0);
2987: tcg_temp_free_i32(t1);
1.1 root 2988: }
2989:
2990: /*** Integer load and store strings ***/
1.1.1.7 root 2991:
1.1 root 2992: /* lswi */
2993: /* PowerPC32 specification says we must generate an exception if
2994: * rA is in the range of registers to be loaded.
2995: * In an other hand, IBM says this is valid, but rA won't be loaded.
2996: * For now, I'll follow the spec...
2997: */
1.1.1.7 root 2998: static void gen_lswi(DisasContext *ctx)
1.1 root 2999: {
1.1.1.6 root 3000: TCGv t0;
3001: TCGv_i32 t1, t2;
1.1 root 3002: int nb = NB(ctx->opcode);
3003: int start = rD(ctx->opcode);
3004: int ra = rA(ctx->opcode);
3005: int nr;
3006:
3007: if (nb == 0)
3008: nb = 32;
3009: nr = nb / 4;
1.1.1.5 root 3010: if (unlikely(((start + nr) > 32 &&
3011: start <= ra && (start + nr - 32) > ra) ||
3012: ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
1.1.1.6 root 3013: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
1.1 root 3014: return;
3015: }
1.1.1.6 root 3016: gen_set_access_type(ctx, ACCESS_INT);
1.1 root 3017: /* NIP cannot be restored if the memory exception comes from an helper */
1.1.1.5 root 3018: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 3019: t0 = tcg_temp_new();
3020: gen_addr_register(ctx, t0);
3021: t1 = tcg_const_i32(nb);
3022: t2 = tcg_const_i32(start);
3023: gen_helper_lsw(t0, t1, t2);
3024: tcg_temp_free(t0);
3025: tcg_temp_free_i32(t1);
3026: tcg_temp_free_i32(t2);
1.1 root 3027: }
3028:
3029: /* lswx */
1.1.1.7 root 3030: static void gen_lswx(DisasContext *ctx)
1.1 root 3031: {
1.1.1.6 root 3032: TCGv t0;
3033: TCGv_i32 t1, t2, t3;
3034: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 3035: /* NIP cannot be restored if the memory exception comes from an helper */
3036: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 3037: t0 = tcg_temp_new();
3038: gen_addr_reg_index(ctx, t0);
3039: t1 = tcg_const_i32(rD(ctx->opcode));
3040: t2 = tcg_const_i32(rA(ctx->opcode));
3041: t3 = tcg_const_i32(rB(ctx->opcode));
3042: gen_helper_lswx(t0, t1, t2, t3);
3043: tcg_temp_free(t0);
3044: tcg_temp_free_i32(t1);
3045: tcg_temp_free_i32(t2);
3046: tcg_temp_free_i32(t3);
1.1 root 3047: }
3048:
3049: /* stswi */
1.1.1.7 root 3050: static void gen_stswi(DisasContext *ctx)
1.1 root 3051: {
1.1.1.6 root 3052: TCGv t0;
3053: TCGv_i32 t1, t2;
1.1 root 3054: int nb = NB(ctx->opcode);
1.1.1.6 root 3055: gen_set_access_type(ctx, ACCESS_INT);
1.1.1.5 root 3056: /* NIP cannot be restored if the memory exception comes from an helper */
3057: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 3058: t0 = tcg_temp_new();
3059: gen_addr_register(ctx, t0);
1.1 root 3060: if (nb == 0)
3061: nb = 32;
1.1.1.6 root 3062: t1 = tcg_const_i32(nb);
3063: t2 = tcg_const_i32(rS(ctx->opcode));
3064: gen_helper_stsw(t0, t1, t2);
3065: tcg_temp_free(t0);
3066: tcg_temp_free_i32(t1);
3067: tcg_temp_free_i32(t2);
1.1 root 3068: }
3069:
3070: /* stswx */
1.1.1.7 root 3071: static void gen_stswx(DisasContext *ctx)
1.1 root 3072: {
1.1.1.6 root 3073: TCGv t0;
3074: TCGv_i32 t1, t2;
3075: gen_set_access_type(ctx, ACCESS_INT);
1.1 root 3076: /* NIP cannot be restored if the memory exception comes from an helper */
1.1.1.5 root 3077: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 3078: t0 = tcg_temp_new();
3079: gen_addr_reg_index(ctx, t0);
3080: t1 = tcg_temp_new_i32();
3081: tcg_gen_trunc_tl_i32(t1, cpu_xer);
3082: tcg_gen_andi_i32(t1, t1, 0x7F);
3083: t2 = tcg_const_i32(rS(ctx->opcode));
3084: gen_helper_stsw(t0, t1, t2);
3085: tcg_temp_free(t0);
3086: tcg_temp_free_i32(t1);
3087: tcg_temp_free_i32(t2);
1.1 root 3088: }
3089:
3090: /*** Memory synchronisation ***/
3091: /* eieio */
1.1.1.7 root 3092: static void gen_eieio(DisasContext *ctx)
1.1 root 3093: {
3094: }
3095:
3096: /* isync */
1.1.1.7 root 3097: static void gen_isync(DisasContext *ctx)
1.1 root 3098: {
1.1.1.6 root 3099: gen_stop_exception(ctx);
1.1 root 3100: }
3101:
3102: /* lwarx */
1.1.1.7 root 3103: static void gen_lwarx(DisasContext *ctx)
1.1 root 3104: {
1.1.1.6 root 3105: TCGv t0;
1.1.1.8 root 3106: TCGv gpr = cpu_gpr[rD(ctx->opcode)];
1.1.1.6 root 3107: gen_set_access_type(ctx, ACCESS_RES);
3108: t0 = tcg_temp_local_new();
3109: gen_addr_reg_index(ctx, t0);
3110: gen_check_align(ctx, t0, 0x03);
1.1.1.8 root 3111: gen_qemu_ld32u(ctx, gpr, t0);
1.1.1.6 root 3112: tcg_gen_mov_tl(cpu_reserve, t0);
1.1.1.13! root 3113: tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
1.1.1.6 root 3114: tcg_temp_free(t0);
1.1 root 3115: }
3116:
1.1.1.8 root 3117: #if defined(CONFIG_USER_ONLY)
3118: static void gen_conditional_store (DisasContext *ctx, TCGv EA,
3119: int reg, int size)
3120: {
3121: TCGv t0 = tcg_temp_new();
3122: uint32_t save_exception = ctx->exception;
3123:
1.1.1.13! root 3124: tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
1.1.1.8 root 3125: tcg_gen_movi_tl(t0, (size << 5) | reg);
1.1.1.13! root 3126: tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
1.1.1.8 root 3127: tcg_temp_free(t0);
3128: gen_update_nip(ctx, ctx->nip-4);
3129: ctx->exception = POWERPC_EXCP_BRANCH;
3130: gen_exception(ctx, POWERPC_EXCP_STCX);
3131: ctx->exception = save_exception;
3132: }
3133: #endif
3134:
1.1 root 3135: /* stwcx. */
1.1.1.7 root 3136: static void gen_stwcx_(DisasContext *ctx)
1.1 root 3137: {
1.1.1.6 root 3138: TCGv t0;
3139: gen_set_access_type(ctx, ACCESS_RES);
3140: t0 = tcg_temp_local_new();
3141: gen_addr_reg_index(ctx, t0);
3142: gen_check_align(ctx, t0, 0x03);
1.1.1.8 root 3143: #if defined(CONFIG_USER_ONLY)
3144: gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
3145: #else
3146: {
3147: int l1;
3148:
3149: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3150: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3151: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3152: l1 = gen_new_label();
3153: tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3154: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3155: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3156: gen_set_label(l1);
3157: tcg_gen_movi_tl(cpu_reserve, -1);
3158: }
3159: #endif
1.1.1.6 root 3160: tcg_temp_free(t0);
1.1 root 3161: }
3162:
1.1.1.5 root 3163: #if defined(TARGET_PPC64)
3164: /* ldarx */
1.1.1.7 root 3165: static void gen_ldarx(DisasContext *ctx)
1.1.1.5 root 3166: {
1.1.1.6 root 3167: TCGv t0;
1.1.1.8 root 3168: TCGv gpr = cpu_gpr[rD(ctx->opcode)];
1.1.1.6 root 3169: gen_set_access_type(ctx, ACCESS_RES);
3170: t0 = tcg_temp_local_new();
3171: gen_addr_reg_index(ctx, t0);
3172: gen_check_align(ctx, t0, 0x07);
1.1.1.8 root 3173: gen_qemu_ld64(ctx, gpr, t0);
1.1.1.6 root 3174: tcg_gen_mov_tl(cpu_reserve, t0);
1.1.1.13! root 3175: tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
1.1.1.6 root 3176: tcg_temp_free(t0);
1.1.1.5 root 3177: }
3178:
3179: /* stdcx. */
1.1.1.7 root 3180: static void gen_stdcx_(DisasContext *ctx)
1.1.1.5 root 3181: {
1.1.1.6 root 3182: TCGv t0;
3183: gen_set_access_type(ctx, ACCESS_RES);
3184: t0 = tcg_temp_local_new();
3185: gen_addr_reg_index(ctx, t0);
3186: gen_check_align(ctx, t0, 0x07);
1.1.1.8 root 3187: #if defined(CONFIG_USER_ONLY)
3188: gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
3189: #else
3190: {
3191: int l1;
3192: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3193: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3194: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3195: l1 = gen_new_label();
3196: tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3197: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3198: gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3199: gen_set_label(l1);
3200: tcg_gen_movi_tl(cpu_reserve, -1);
3201: }
3202: #endif
1.1.1.6 root 3203: tcg_temp_free(t0);
1.1.1.5 root 3204: }
3205: #endif /* defined(TARGET_PPC64) */
3206:
1.1 root 3207: /* sync */
1.1.1.7 root 3208: static void gen_sync(DisasContext *ctx)
1.1 root 3209: {
3210: }
3211:
1.1.1.5 root 3212: /* wait */
1.1.1.7 root 3213: static void gen_wait(DisasContext *ctx)
1.1.1.5 root 3214: {
1.1.1.6 root 3215: TCGv_i32 t0 = tcg_temp_new_i32();
1.1.1.13! root 3216: tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
1.1.1.6 root 3217: tcg_temp_free_i32(t0);
1.1.1.5 root 3218: /* Stop translation, as the CPU is supposed to sleep from now */
1.1.1.6 root 3219: gen_exception_err(ctx, EXCP_HLT, 1);
1.1.1.5 root 3220: }
3221:
1.1 root 3222: /*** Floating-point load ***/
1.1.1.6 root 3223: #define GEN_LDF(name, ldop, opc, type) \
1.1.1.7 root 3224: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 3225: { \
1.1.1.6 root 3226: TCGv EA; \
1.1.1.5 root 3227: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3228: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3229: return; \
3230: } \
1.1.1.6 root 3231: gen_set_access_type(ctx, ACCESS_FLOAT); \
3232: EA = tcg_temp_new(); \
3233: gen_addr_imm_index(ctx, EA, 0); \
3234: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3235: tcg_temp_free(EA); \
1.1 root 3236: }
3237:
1.1.1.6 root 3238: #define GEN_LDUF(name, ldop, opc, type) \
1.1.1.7 root 3239: static void glue(gen_, name##u)(DisasContext *ctx) \
1.1 root 3240: { \
1.1.1.6 root 3241: TCGv EA; \
1.1.1.5 root 3242: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3243: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3244: return; \
3245: } \
1.1.1.5 root 3246: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3247: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3248: return; \
3249: } \
1.1.1.6 root 3250: gen_set_access_type(ctx, ACCESS_FLOAT); \
3251: EA = tcg_temp_new(); \
3252: gen_addr_imm_index(ctx, EA, 0); \
3253: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3254: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3255: tcg_temp_free(EA); \
1.1 root 3256: }
3257:
1.1.1.6 root 3258: #define GEN_LDUXF(name, ldop, opc, type) \
1.1.1.7 root 3259: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 3260: { \
1.1.1.6 root 3261: TCGv EA; \
1.1.1.5 root 3262: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3263: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3264: return; \
3265: } \
1.1.1.5 root 3266: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3267: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3268: return; \
3269: } \
1.1.1.6 root 3270: gen_set_access_type(ctx, ACCESS_FLOAT); \
3271: EA = tcg_temp_new(); \
3272: gen_addr_reg_index(ctx, EA); \
3273: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3274: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3275: tcg_temp_free(EA); \
1.1 root 3276: }
3277:
1.1.1.6 root 3278: #define GEN_LDXF(name, ldop, opc2, opc3, type) \
1.1.1.7 root 3279: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1 root 3280: { \
1.1.1.6 root 3281: TCGv EA; \
1.1.1.5 root 3282: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3283: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3284: return; \
3285: } \
1.1.1.6 root 3286: gen_set_access_type(ctx, ACCESS_FLOAT); \
3287: EA = tcg_temp_new(); \
3288: gen_addr_reg_index(ctx, EA); \
3289: gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
3290: tcg_temp_free(EA); \
3291: }
3292:
3293: #define GEN_LDFS(name, ldop, op, type) \
3294: GEN_LDF(name, ldop, op | 0x20, type); \
3295: GEN_LDUF(name, ldop, op | 0x21, type); \
3296: GEN_LDUXF(name, ldop, op | 0x01, type); \
3297: GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3298:
1.1.1.8 root 3299: static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 3300: {
3301: TCGv t0 = tcg_temp_new();
3302: TCGv_i32 t1 = tcg_temp_new_i32();
3303: gen_qemu_ld32u(ctx, t0, arg2);
3304: tcg_gen_trunc_tl_i32(t1, t0);
3305: tcg_temp_free(t0);
3306: gen_helper_float32_to_float64(arg1, t1);
3307: tcg_temp_free_i32(t1);
3308: }
3309:
3310: /* lfd lfdu lfdux lfdx */
3311: GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3312: /* lfs lfsu lfsux lfsx */
3313: GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
1.1 root 3314:
3315: /*** Floating-point store ***/
1.1.1.6 root 3316: #define GEN_STF(name, stop, opc, type) \
1.1.1.7 root 3317: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 3318: { \
1.1.1.6 root 3319: TCGv EA; \
1.1.1.5 root 3320: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3321: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1.1.5 root 3322: return; \
1.1 root 3323: } \
1.1.1.6 root 3324: gen_set_access_type(ctx, ACCESS_FLOAT); \
3325: EA = tcg_temp_new(); \
3326: gen_addr_imm_index(ctx, EA, 0); \
3327: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3328: tcg_temp_free(EA); \
1.1 root 3329: }
3330:
1.1.1.6 root 3331: #define GEN_STUF(name, stop, opc, type) \
1.1.1.7 root 3332: static void glue(gen_, name##u)(DisasContext *ctx) \
1.1 root 3333: { \
1.1.1.6 root 3334: TCGv EA; \
1.1.1.5 root 3335: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3336: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3337: return; \
3338: } \
1.1.1.5 root 3339: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3340: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3341: return; \
3342: } \
1.1.1.6 root 3343: gen_set_access_type(ctx, ACCESS_FLOAT); \
3344: EA = tcg_temp_new(); \
3345: gen_addr_imm_index(ctx, EA, 0); \
3346: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3347: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3348: tcg_temp_free(EA); \
1.1 root 3349: }
3350:
1.1.1.6 root 3351: #define GEN_STUXF(name, stop, opc, type) \
1.1.1.7 root 3352: static void glue(gen_, name##ux)(DisasContext *ctx) \
1.1 root 3353: { \
1.1.1.6 root 3354: TCGv EA; \
1.1.1.5 root 3355: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3356: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3357: return; \
3358: } \
1.1.1.5 root 3359: if (unlikely(rA(ctx->opcode) == 0)) { \
1.1.1.6 root 3360: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
1.1 root 3361: return; \
3362: } \
1.1.1.6 root 3363: gen_set_access_type(ctx, ACCESS_FLOAT); \
3364: EA = tcg_temp_new(); \
3365: gen_addr_reg_index(ctx, EA); \
3366: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3367: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3368: tcg_temp_free(EA); \
1.1 root 3369: }
3370:
1.1.1.6 root 3371: #define GEN_STXF(name, stop, opc2, opc3, type) \
1.1.1.7 root 3372: static void glue(gen_, name##x)(DisasContext *ctx) \
1.1 root 3373: { \
1.1.1.6 root 3374: TCGv EA; \
1.1.1.5 root 3375: if (unlikely(!ctx->fpu_enabled)) { \
1.1.1.6 root 3376: gen_exception(ctx, POWERPC_EXCP_FPU); \
1.1 root 3377: return; \
3378: } \
1.1.1.6 root 3379: gen_set_access_type(ctx, ACCESS_FLOAT); \
3380: EA = tcg_temp_new(); \
3381: gen_addr_reg_index(ctx, EA); \
3382: gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
3383: tcg_temp_free(EA); \
3384: }
3385:
3386: #define GEN_STFS(name, stop, op, type) \
3387: GEN_STF(name, stop, op | 0x20, type); \
3388: GEN_STUF(name, stop, op | 0x21, type); \
3389: GEN_STUXF(name, stop, op | 0x01, type); \
3390: GEN_STXF(name, stop, 0x17, op | 0x00, type)
3391:
1.1.1.8 root 3392: static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 3393: {
3394: TCGv_i32 t0 = tcg_temp_new_i32();
3395: TCGv t1 = tcg_temp_new();
3396: gen_helper_float64_to_float32(t0, arg1);
3397: tcg_gen_extu_i32_tl(t1, t0);
3398: tcg_temp_free_i32(t0);
3399: gen_qemu_st32(ctx, t1, arg2);
3400: tcg_temp_free(t1);
1.1 root 3401: }
3402:
3403: /* stfd stfdu stfdux stfdx */
1.1.1.6 root 3404: GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
1.1 root 3405: /* stfs stfsu stfsux stfsx */
1.1.1.6 root 3406: GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
1.1 root 3407:
3408: /* Optional: */
1.1.1.8 root 3409: static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
1.1.1.6 root 3410: {
3411: TCGv t0 = tcg_temp_new();
3412: tcg_gen_trunc_i64_tl(t0, arg1),
3413: gen_qemu_st32(ctx, t0, arg2);
3414: tcg_temp_free(t0);
3415: }
1.1 root 3416: /* stfiwx */
1.1.1.6 root 3417: GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
1.1 root 3418:
1.1.1.12 root 3419: static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
3420: {
3421: #if defined(TARGET_PPC64)
3422: if (ctx->has_cfar)
3423: tcg_gen_movi_tl(cpu_cfar, nip);
3424: #endif
3425: }
3426:
1.1 root 3427: /*** Branch ***/
1.1.1.8 root 3428: static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1.1.1.2 root 3429: {
3430: TranslationBlock *tb;
3431: tb = ctx->tb;
1.1.1.5 root 3432: #if defined(TARGET_PPC64)
1.1.1.6 root 3433: if (!ctx->sf_mode)
3434: dest = (uint32_t) dest;
1.1.1.5 root 3435: #endif
1.1.1.6 root 3436: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3437: likely(!ctx->singlestep_enabled)) {
3438: tcg_gen_goto_tb(n);
3439: tcg_gen_movi_tl(cpu_nip, dest & ~3);
1.1.1.11 root 3440: tcg_gen_exit_tb((tcg_target_long)tb + n);
1.1.1.2 root 3441: } else {
1.1.1.6 root 3442: tcg_gen_movi_tl(cpu_nip, dest & ~3);
3443: if (unlikely(ctx->singlestep_enabled)) {
3444: if ((ctx->singlestep_enabled &
3445: (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3446: ctx->exception == POWERPC_EXCP_BRANCH) {
3447: target_ulong tmp = ctx->nip;
3448: ctx->nip = dest;
3449: gen_exception(ctx, POWERPC_EXCP_TRACE);
3450: ctx->nip = tmp;
3451: }
3452: if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3453: gen_debug_exception(ctx);
3454: }
3455: }
3456: tcg_gen_exit_tb(0);
1.1.1.2 root 3457: }
3458: }
3459:
1.1.1.8 root 3460: static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
1.1.1.5 root 3461: {
3462: #if defined(TARGET_PPC64)
1.1.1.6 root 3463: if (ctx->sf_mode == 0)
3464: tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
1.1.1.5 root 3465: else
3466: #endif
1.1.1.6 root 3467: tcg_gen_movi_tl(cpu_lr, nip);
1.1.1.5 root 3468: }
3469:
1.1 root 3470: /* b ba bl bla */
1.1.1.7 root 3471: static void gen_b(DisasContext *ctx)
1.1 root 3472: {
1.1.1.5 root 3473: target_ulong li, target;
1.1 root 3474:
1.1.1.6 root 3475: ctx->exception = POWERPC_EXCP_BRANCH;
1.1 root 3476: /* sign extend LI */
1.1.1.5 root 3477: #if defined(TARGET_PPC64)
3478: if (ctx->sf_mode)
3479: li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3480: else
3481: #endif
3482: li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3483: if (likely(AA(ctx->opcode) == 0))
1.1 root 3484: target = ctx->nip + li - 4;
3485: else
3486: target = li;
1.1.1.5 root 3487: if (LK(ctx->opcode))
3488: gen_setlr(ctx, ctx->nip);
1.1.1.12 root 3489: gen_update_cfar(ctx, ctx->nip);
1.1.1.2 root 3490: gen_goto_tb(ctx, 0, target);
1.1 root 3491: }
3492:
3493: #define BCOND_IM 0
3494: #define BCOND_LR 1
3495: #define BCOND_CTR 2
3496:
1.1.1.8 root 3497: static inline void gen_bcond(DisasContext *ctx, int type)
1.1.1.5 root 3498: {
3499: uint32_t bo = BO(ctx->opcode);
1.1.1.9 root 3500: int l1;
1.1.1.6 root 3501: TCGv target;
1.1 root 3502:
1.1.1.6 root 3503: ctx->exception = POWERPC_EXCP_BRANCH;
3504: if (type == BCOND_LR || type == BCOND_CTR) {
3505: target = tcg_temp_local_new();
3506: if (type == BCOND_CTR)
3507: tcg_gen_mov_tl(target, cpu_ctr);
3508: else
3509: tcg_gen_mov_tl(target, cpu_lr);
1.1.1.7 root 3510: } else {
3511: TCGV_UNUSED(target);
1.1 root 3512: }
1.1.1.5 root 3513: if (LK(ctx->opcode))
3514: gen_setlr(ctx, ctx->nip);
1.1.1.6 root 3515: l1 = gen_new_label();
3516: if ((bo & 0x4) == 0) {
3517: /* Decrement and test CTR */
3518: TCGv temp = tcg_temp_new();
3519: if (unlikely(type == BCOND_CTR)) {
3520: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3521: return;
3522: }
3523: tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
1.1.1.5 root 3524: #if defined(TARGET_PPC64)
1.1.1.6 root 3525: if (!ctx->sf_mode)
3526: tcg_gen_ext32u_tl(temp, cpu_ctr);
3527: else
1.1.1.5 root 3528: #endif
1.1.1.6 root 3529: tcg_gen_mov_tl(temp, cpu_ctr);
3530: if (bo & 0x2) {
3531: tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3532: } else {
3533: tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
1.1 root 3534: }
1.1.1.6 root 3535: tcg_temp_free(temp);
3536: }
3537: if ((bo & 0x10) == 0) {
3538: /* Test CR */
3539: uint32_t bi = BI(ctx->opcode);
3540: uint32_t mask = 1 << (3 - (bi & 0x03));
3541: TCGv_i32 temp = tcg_temp_new_i32();
3542:
1.1.1.5 root 3543: if (bo & 0x8) {
1.1.1.6 root 3544: tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3545: tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
1.1.1.5 root 3546: } else {
1.1.1.6 root 3547: tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3548: tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
1.1.1.5 root 3549: }
1.1.1.6 root 3550: tcg_temp_free_i32(temp);
1.1.1.5 root 3551: }
1.1.1.12 root 3552: gen_update_cfar(ctx, ctx->nip);
1.1 root 3553: if (type == BCOND_IM) {
1.1.1.6 root 3554: target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3555: if (likely(AA(ctx->opcode) == 0)) {
3556: gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3557: } else {
3558: gen_goto_tb(ctx, 0, li);
3559: }
1.1.1.2 root 3560: gen_set_label(l1);
3561: gen_goto_tb(ctx, 1, ctx->nip);
1.1 root 3562: } else {
1.1.1.5 root 3563: #if defined(TARGET_PPC64)
1.1.1.6 root 3564: if (!(ctx->sf_mode))
3565: tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3566: else
3567: #endif
3568: tcg_gen_andi_tl(cpu_nip, target, ~3);
3569: tcg_gen_exit_tb(0);
3570: gen_set_label(l1);
3571: #if defined(TARGET_PPC64)
3572: if (!(ctx->sf_mode))
3573: tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
1.1.1.5 root 3574: else
3575: #endif
1.1.1.6 root 3576: tcg_gen_movi_tl(cpu_nip, ctx->nip);
3577: tcg_gen_exit_tb(0);
1.1 root 3578: }
3579: }
3580:
1.1.1.7 root 3581: static void gen_bc(DisasContext *ctx)
1.1.1.5 root 3582: {
1.1 root 3583: gen_bcond(ctx, BCOND_IM);
3584: }
3585:
1.1.1.7 root 3586: static void gen_bcctr(DisasContext *ctx)
1.1.1.5 root 3587: {
1.1 root 3588: gen_bcond(ctx, BCOND_CTR);
3589: }
3590:
1.1.1.7 root 3591: static void gen_bclr(DisasContext *ctx)
1.1.1.5 root 3592: {
1.1 root 3593: gen_bcond(ctx, BCOND_LR);
3594: }
3595:
3596: /*** Condition register logical ***/
1.1.1.6 root 3597: #define GEN_CRLOGIC(name, tcg_op, opc) \
1.1.1.7 root 3598: static void glue(gen_, name)(DisasContext *ctx) \
1.1 root 3599: { \
1.1.1.5 root 3600: uint8_t bitmask; \
3601: int sh; \
1.1.1.6 root 3602: TCGv_i32 t0, t1; \
1.1.1.5 root 3603: sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
1.1.1.6 root 3604: t0 = tcg_temp_new_i32(); \
1.1.1.5 root 3605: if (sh > 0) \
1.1.1.6 root 3606: tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
1.1.1.5 root 3607: else if (sh < 0) \
1.1.1.6 root 3608: tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
3609: else \
3610: tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
3611: t1 = tcg_temp_new_i32(); \
1.1.1.5 root 3612: sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3613: if (sh > 0) \
1.1.1.6 root 3614: tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
1.1.1.5 root 3615: else if (sh < 0) \
1.1.1.6 root 3616: tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
3617: else \
3618: tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
3619: tcg_op(t0, t0, t1); \
1.1.1.5 root 3620: bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
1.1.1.6 root 3621: tcg_gen_andi_i32(t0, t0, bitmask); \
3622: tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
3623: tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
3624: tcg_temp_free_i32(t0); \
3625: tcg_temp_free_i32(t1); \
1.1 root 3626: }
3627:
3628: /* crand */
1.1.1.6 root 3629: GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
1.1 root 3630: /* crandc */
1.1.1.6 root 3631: GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
1.1 root 3632: /* creqv */
1.1.1.6 root 3633: GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
1.1 root 3634: /* crnand */
1.1.1.6 root 3635: GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
1.1 root 3636: /* crnor */
1.1.1.6 root 3637: GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
1.1 root 3638: /* cror */
1.1.1.6 root 3639: GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
1.1 root 3640: /* crorc */
1.1.1.6 root 3641: GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
1.1 root 3642: /* crxor */
1.1.1.6 root 3643: GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
1.1.1.7 root 3644:
1.1 root 3645: /* mcrf */
1.1.1.7 root 3646: static void gen_mcrf(DisasContext *ctx)
1.1 root 3647: {
1.1.1.6 root 3648: tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
1.1 root 3649: }
3650:
3651: /*** System linkage ***/
1.1.1.7 root 3652:
1.1.1.6 root 3653: /* rfi (mem_idx only) */
1.1.1.7 root 3654: static void gen_rfi(DisasContext *ctx)
1.1 root 3655: {
3656: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3657: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3658: #else
3659: /* Restore CPU state */
1.1.1.6 root 3660: if (unlikely(!ctx->mem_idx)) {
3661: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 3662: return;
3663: }
1.1.1.12 root 3664: gen_update_cfar(ctx, ctx->nip);
1.1.1.6 root 3665: gen_helper_rfi();
3666: gen_sync_exception(ctx);
1.1 root 3667: #endif
3668: }
3669:
1.1.1.5 root 3670: #if defined(TARGET_PPC64)
1.1.1.7 root 3671: static void gen_rfid(DisasContext *ctx)
1.1.1.5 root 3672: {
3673: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3674: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3675: #else
3676: /* Restore CPU state */
1.1.1.6 root 3677: if (unlikely(!ctx->mem_idx)) {
3678: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3679: return;
3680: }
1.1.1.12 root 3681: gen_update_cfar(ctx, ctx->nip);
1.1.1.6 root 3682: gen_helper_rfid();
3683: gen_sync_exception(ctx);
1.1.1.5 root 3684: #endif
3685: }
3686:
1.1.1.7 root 3687: static void gen_hrfid(DisasContext *ctx)
1.1 root 3688: {
3689: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3690: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3691: #else
3692: /* Restore CPU state */
1.1.1.6 root 3693: if (unlikely(ctx->mem_idx <= 1)) {
3694: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 3695: return;
3696: }
1.1.1.6 root 3697: gen_helper_hrfid();
3698: gen_sync_exception(ctx);
1.1.1.5 root 3699: #endif
3700: }
3701: #endif
3702:
3703: /* sc */
3704: #if defined(CONFIG_USER_ONLY)
3705: #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
1.1 root 3706: #else
1.1.1.5 root 3707: #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
1.1 root 3708: #endif
1.1.1.7 root 3709: static void gen_sc(DisasContext *ctx)
1.1.1.5 root 3710: {
3711: uint32_t lev;
3712:
3713: lev = (ctx->opcode >> 5) & 0x7F;
1.1.1.6 root 3714: gen_exception_err(ctx, POWERPC_SYSCALL, lev);
1.1 root 3715: }
3716:
3717: /*** Trap ***/
1.1.1.7 root 3718:
1.1 root 3719: /* tw */
1.1.1.7 root 3720: static void gen_tw(DisasContext *ctx)
1.1 root 3721: {
1.1.1.6 root 3722: TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
1.1.1.4 root 3723: /* Update the nip since this might generate a trap exception */
1.1.1.5 root 3724: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3725: gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3726: tcg_temp_free_i32(t0);
1.1 root 3727: }
3728:
3729: /* twi */
1.1.1.7 root 3730: static void gen_twi(DisasContext *ctx)
1.1 root 3731: {
1.1.1.6 root 3732: TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3733: TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
1.1.1.5 root 3734: /* Update the nip since this might generate a trap exception */
3735: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3736: gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3737: tcg_temp_free(t0);
3738: tcg_temp_free_i32(t1);
1.1 root 3739: }
3740:
1.1.1.5 root 3741: #if defined(TARGET_PPC64)
3742: /* td */
1.1.1.7 root 3743: static void gen_td(DisasContext *ctx)
1.1 root 3744: {
1.1.1.6 root 3745: TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
1.1.1.5 root 3746: /* Update the nip since this might generate a trap exception */
3747: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3748: gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3749: tcg_temp_free_i32(t0);
1.1.1.5 root 3750: }
1.1 root 3751:
1.1.1.5 root 3752: /* tdi */
1.1.1.7 root 3753: static void gen_tdi(DisasContext *ctx)
1.1.1.5 root 3754: {
1.1.1.6 root 3755: TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3756: TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
1.1.1.5 root 3757: /* Update the nip since this might generate a trap exception */
3758: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3759: gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3760: tcg_temp_free(t0);
3761: tcg_temp_free_i32(t1);
1.1 root 3762: }
1.1.1.5 root 3763: #endif
1.1 root 3764:
1.1.1.5 root 3765: /*** Processor control ***/
1.1.1.7 root 3766:
1.1 root 3767: /* mcrxr */
1.1.1.7 root 3768: static void gen_mcrxr(DisasContext *ctx)
1.1 root 3769: {
1.1.1.6 root 3770: tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3771: tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3772: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
1.1 root 3773: }
3774:
1.1.1.6 root 3775: /* mfcr mfocrf */
1.1.1.7 root 3776: static void gen_mfcr(DisasContext *ctx)
1.1 root 3777: {
1.1.1.5 root 3778: uint32_t crm, crn;
3779:
3780: if (likely(ctx->opcode & 0x00100000)) {
3781: crm = CRM(ctx->opcode);
1.1.1.6 root 3782: if (likely(crm && ((crm & (crm - 1)) == 0))) {
3783: crn = ctz32 (crm);
3784: tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
1.1.1.7 root 3785: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
3786: cpu_gpr[rD(ctx->opcode)], crn * 4);
1.1.1.5 root 3787: }
3788: } else {
1.1.1.7 root 3789: TCGv_i32 t0 = tcg_temp_new_i32();
3790: tcg_gen_mov_i32(t0, cpu_crf[0]);
3791: tcg_gen_shli_i32(t0, t0, 4);
3792: tcg_gen_or_i32(t0, t0, cpu_crf[1]);
3793: tcg_gen_shli_i32(t0, t0, 4);
3794: tcg_gen_or_i32(t0, t0, cpu_crf[2]);
3795: tcg_gen_shli_i32(t0, t0, 4);
3796: tcg_gen_or_i32(t0, t0, cpu_crf[3]);
3797: tcg_gen_shli_i32(t0, t0, 4);
3798: tcg_gen_or_i32(t0, t0, cpu_crf[4]);
3799: tcg_gen_shli_i32(t0, t0, 4);
3800: tcg_gen_or_i32(t0, t0, cpu_crf[5]);
3801: tcg_gen_shli_i32(t0, t0, 4);
3802: tcg_gen_or_i32(t0, t0, cpu_crf[6]);
3803: tcg_gen_shli_i32(t0, t0, 4);
3804: tcg_gen_or_i32(t0, t0, cpu_crf[7]);
3805: tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
3806: tcg_temp_free_i32(t0);
1.1.1.5 root 3807: }
1.1 root 3808: }
3809:
3810: /* mfmsr */
1.1.1.7 root 3811: static void gen_mfmsr(DisasContext *ctx)
1.1 root 3812: {
3813: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3814: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3815: #else
1.1.1.6 root 3816: if (unlikely(!ctx->mem_idx)) {
3817: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3818: return;
3819: }
1.1.1.6 root 3820: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
1.1 root 3821: #endif
3822: }
3823:
1.1.1.9 root 3824: static void spr_noaccess(void *opaque, int gprn, int sprn)
1.1 root 3825: {
1.1.1.9 root 3826: #if 0
1.1 root 3827: sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3828: printf("ERROR: try to access SPR %d !\n", sprn);
1.1.1.9 root 3829: #endif
1.1 root 3830: }
3831: #define SPR_NOACCESS (&spr_noaccess)
3832:
3833: /* mfspr */
1.1.1.8 root 3834: static inline void gen_op_mfspr(DisasContext *ctx)
1.1 root 3835: {
1.1.1.6 root 3836: void (*read_cb)(void *opaque, int gprn, int sprn);
1.1 root 3837: uint32_t sprn = SPR(ctx->opcode);
3838:
3839: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 root 3840: if (ctx->mem_idx == 2)
1.1.1.5 root 3841: read_cb = ctx->spr_cb[sprn].hea_read;
1.1.1.6 root 3842: else if (ctx->mem_idx)
1.1 root 3843: read_cb = ctx->spr_cb[sprn].oea_read;
3844: else
3845: #endif
3846: read_cb = ctx->spr_cb[sprn].uea_read;
1.1.1.5 root 3847: if (likely(read_cb != NULL)) {
3848: if (likely(read_cb != SPR_NOACCESS)) {
1.1.1.6 root 3849: (*read_cb)(ctx, rD(ctx->opcode), sprn);
1.1 root 3850: } else {
3851: /* Privilege exception */
1.1.1.5 root 3852: /* This is a hack to avoid warnings when running Linux:
3853: * this OS breaks the PowerPC virtualisation model,
3854: * allowing userland application to read the PVR
3855: */
3856: if (sprn != SPR_PVR) {
1.1.1.6 root 3857: qemu_log("Trying to read privileged spr %d %03x at "
1.1.1.8 root 3858: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3859: printf("Trying to read privileged spr %d %03x at "
3860: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
1.1.1.2 root 3861: }
1.1.1.6 root 3862: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3863: }
3864: } else {
3865: /* Not defined */
1.1.1.6 root 3866: qemu_log("Trying to read invalid spr %d %03x at "
1.1.1.8 root 3867: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3868: printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
1.1.1.5 root 3869: sprn, sprn, ctx->nip);
1.1.1.6 root 3870: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
1.1 root 3871: }
3872: }
3873:
1.1.1.7 root 3874: static void gen_mfspr(DisasContext *ctx)
1.1 root 3875: {
3876: gen_op_mfspr(ctx);
1.1.1.5 root 3877: }
1.1 root 3878:
3879: /* mftb */
1.1.1.7 root 3880: static void gen_mftb(DisasContext *ctx)
1.1 root 3881: {
3882: gen_op_mfspr(ctx);
3883: }
3884:
1.1.1.6 root 3885: /* mtcrf mtocrf*/
1.1.1.7 root 3886: static void gen_mtcrf(DisasContext *ctx)
1.1 root 3887: {
1.1.1.5 root 3888: uint32_t crm, crn;
3889:
3890: crm = CRM(ctx->opcode);
1.1.1.6 root 3891: if (likely((ctx->opcode & 0x00100000))) {
3892: if (crm && ((crm & (crm - 1)) == 0)) {
3893: TCGv_i32 temp = tcg_temp_new_i32();
3894: crn = ctz32 (crm);
3895: tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3896: tcg_gen_shri_i32(temp, temp, crn * 4);
3897: tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
3898: tcg_temp_free_i32(temp);
3899: }
1.1.1.5 root 3900: } else {
1.1.1.7 root 3901: TCGv_i32 temp = tcg_temp_new_i32();
3902: tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3903: for (crn = 0 ; crn < 8 ; crn++) {
3904: if (crm & (1 << crn)) {
3905: tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3906: tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3907: }
3908: }
1.1.1.6 root 3909: tcg_temp_free_i32(temp);
1.1.1.5 root 3910: }
1.1 root 3911: }
3912:
3913: /* mtmsr */
1.1.1.5 root 3914: #if defined(TARGET_PPC64)
1.1.1.7 root 3915: static void gen_mtmsrd(DisasContext *ctx)
1.1.1.5 root 3916: {
3917: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3918: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3919: #else
1.1.1.6 root 3920: if (unlikely(!ctx->mem_idx)) {
3921: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 3922: return;
3923: }
3924: if (ctx->opcode & 0x00010000) {
3925: /* Special form that does not need any synchronisation */
1.1.1.6 root 3926: TCGv t0 = tcg_temp_new();
3927: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3928: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3929: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3930: tcg_temp_free(t0);
1.1.1.5 root 3931: } else {
3932: /* XXX: we need to update nip before the store
3933: * if we enter power saving mode, we will exit the loop
3934: * directly from ppc_store_msr
3935: */
3936: gen_update_nip(ctx, ctx->nip);
1.1.1.6 root 3937: gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 3938: /* Must stop the translation as machine state (may have) changed */
3939: /* Note that mtmsr is not always defined as context-synchronizing */
1.1.1.6 root 3940: gen_stop_exception(ctx);
1.1.1.5 root 3941: }
3942: #endif
3943: }
3944: #endif
3945:
1.1.1.7 root 3946: static void gen_mtmsr(DisasContext *ctx)
1.1 root 3947: {
3948: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 3949: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3950: #else
1.1.1.6 root 3951: if (unlikely(!ctx->mem_idx)) {
3952: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 3953: return;
3954: }
1.1.1.5 root 3955: if (ctx->opcode & 0x00010000) {
3956: /* Special form that does not need any synchronisation */
1.1.1.6 root 3957: TCGv t0 = tcg_temp_new();
3958: tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3959: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3960: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3961: tcg_temp_free(t0);
1.1.1.5 root 3962: } else {
1.1.1.11 root 3963: TCGv msr = tcg_temp_new();
3964:
1.1.1.5 root 3965: /* XXX: we need to update nip before the store
3966: * if we enter power saving mode, we will exit the loop
3967: * directly from ppc_store_msr
3968: */
3969: gen_update_nip(ctx, ctx->nip);
3970: #if defined(TARGET_PPC64)
1.1.1.11 root 3971: tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
3972: #else
3973: tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 3974: #endif
1.1.1.11 root 3975: gen_helper_store_msr(msr);
1.1.1.5 root 3976: /* Must stop the translation as machine state (may have) changed */
1.1.1.6 root 3977: /* Note that mtmsr is not always defined as context-synchronizing */
3978: gen_stop_exception(ctx);
1.1.1.5 root 3979: }
1.1 root 3980: #endif
3981: }
3982:
3983: /* mtspr */
1.1.1.7 root 3984: static void gen_mtspr(DisasContext *ctx)
1.1 root 3985: {
1.1.1.6 root 3986: void (*write_cb)(void *opaque, int sprn, int gprn);
1.1 root 3987: uint32_t sprn = SPR(ctx->opcode);
3988:
3989: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 root 3990: if (ctx->mem_idx == 2)
1.1.1.5 root 3991: write_cb = ctx->spr_cb[sprn].hea_write;
1.1.1.6 root 3992: else if (ctx->mem_idx)
1.1 root 3993: write_cb = ctx->spr_cb[sprn].oea_write;
3994: else
3995: #endif
3996: write_cb = ctx->spr_cb[sprn].uea_write;
1.1.1.5 root 3997: if (likely(write_cb != NULL)) {
3998: if (likely(write_cb != SPR_NOACCESS)) {
1.1.1.6 root 3999: (*write_cb)(ctx, sprn, rS(ctx->opcode));
1.1 root 4000: } else {
4001: /* Privilege exception */
1.1.1.6 root 4002: qemu_log("Trying to write privileged spr %d %03x at "
1.1.1.8 root 4003: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
4004: printf("Trying to write privileged spr %d %03x at " TARGET_FMT_lx
4005: "\n", sprn, sprn, ctx->nip);
1.1.1.6 root 4006: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4007: }
1.1 root 4008: } else {
4009: /* Not defined */
1.1.1.6 root 4010: qemu_log("Trying to write invalid spr %d %03x at "
1.1.1.8 root 4011: TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
4012: printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
1.1.1.5 root 4013: sprn, sprn, ctx->nip);
1.1.1.6 root 4014: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
1.1 root 4015: }
4016: }
4017:
4018: /*** Cache management ***/
1.1.1.7 root 4019:
1.1 root 4020: /* dcbf */
1.1.1.7 root 4021: static void gen_dcbf(DisasContext *ctx)
1.1 root 4022: {
1.1.1.5 root 4023: /* XXX: specification says this is treated as a load by the MMU */
1.1.1.6 root 4024: TCGv t0;
4025: gen_set_access_type(ctx, ACCESS_CACHE);
4026: t0 = tcg_temp_new();
4027: gen_addr_reg_index(ctx, t0);
4028: gen_qemu_ld8u(ctx, t0, t0);
4029: tcg_temp_free(t0);
1.1 root 4030: }
4031:
4032: /* dcbi (Supervisor only) */
1.1.1.7 root 4033: static void gen_dcbi(DisasContext *ctx)
1.1 root 4034: {
4035: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4036: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 4037: #else
1.1.1.6 root 4038: TCGv EA, val;
4039: if (unlikely(!ctx->mem_idx)) {
4040: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 4041: return;
4042: }
1.1.1.6 root 4043: EA = tcg_temp_new();
4044: gen_set_access_type(ctx, ACCESS_CACHE);
4045: gen_addr_reg_index(ctx, EA);
4046: val = tcg_temp_new();
1.1.1.5 root 4047: /* XXX: specification says this should be treated as a store by the MMU */
1.1.1.6 root 4048: gen_qemu_ld8u(ctx, val, EA);
4049: gen_qemu_st8(ctx, val, EA);
4050: tcg_temp_free(val);
4051: tcg_temp_free(EA);
1.1 root 4052: #endif
4053: }
4054:
4055: /* dcdst */
1.1.1.7 root 4056: static void gen_dcbst(DisasContext *ctx)
1.1 root 4057: {
1.1.1.5 root 4058: /* XXX: specification say this is treated as a load by the MMU */
1.1.1.6 root 4059: TCGv t0;
4060: gen_set_access_type(ctx, ACCESS_CACHE);
4061: t0 = tcg_temp_new();
4062: gen_addr_reg_index(ctx, t0);
4063: gen_qemu_ld8u(ctx, t0, t0);
4064: tcg_temp_free(t0);
1.1 root 4065: }
4066:
4067: /* dcbt */
1.1.1.7 root 4068: static void gen_dcbt(DisasContext *ctx)
1.1 root 4069: {
1.1.1.5 root 4070: /* interpreted as no-op */
4071: /* XXX: specification say this is treated as a load by the MMU
4072: * but does not generate any exception
4073: */
1.1 root 4074: }
4075:
4076: /* dcbtst */
1.1.1.7 root 4077: static void gen_dcbtst(DisasContext *ctx)
1.1 root 4078: {
1.1.1.5 root 4079: /* interpreted as no-op */
4080: /* XXX: specification say this is treated as a load by the MMU
4081: * but does not generate any exception
4082: */
1.1 root 4083: }
4084:
4085: /* dcbz */
1.1.1.7 root 4086: static void gen_dcbz(DisasContext *ctx)
1.1.1.6 root 4087: {
4088: TCGv t0;
4089: gen_set_access_type(ctx, ACCESS_CACHE);
4090: /* NIP cannot be restored if the memory exception comes from an helper */
4091: gen_update_nip(ctx, ctx->nip - 4);
4092: t0 = tcg_temp_new();
4093: gen_addr_reg_index(ctx, t0);
4094: gen_helper_dcbz(t0);
4095: tcg_temp_free(t0);
4096: }
1.1 root 4097:
1.1.1.7 root 4098: static void gen_dcbz_970(DisasContext *ctx)
1.1 root 4099: {
1.1.1.6 root 4100: TCGv t0;
4101: gen_set_access_type(ctx, ACCESS_CACHE);
4102: /* NIP cannot be restored if the memory exception comes from an helper */
4103: gen_update_nip(ctx, ctx->nip - 4);
4104: t0 = tcg_temp_new();
4105: gen_addr_reg_index(ctx, t0);
4106: if (ctx->opcode & 0x00200000)
4107: gen_helper_dcbz(t0);
4108: else
4109: gen_helper_dcbz_970(t0);
4110: tcg_temp_free(t0);
4111: }
1.1.1.5 root 4112:
1.1.1.6 root 4113: /* dst / dstt */
1.1.1.7 root 4114: static void gen_dst(DisasContext *ctx)
1.1.1.6 root 4115: {
4116: if (rA(ctx->opcode) == 0) {
4117: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4118: } else {
4119: /* interpreted as no-op */
1.1 root 4120: }
1.1.1.5 root 4121: }
4122:
1.1.1.6 root 4123: /* dstst /dststt */
1.1.1.7 root 4124: static void gen_dstst(DisasContext *ctx)
1.1.1.5 root 4125: {
1.1.1.6 root 4126: if (rA(ctx->opcode) == 0) {
4127: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4128: } else {
4129: /* interpreted as no-op */
4130: }
4131:
1.1.1.5 root 4132: }
4133:
1.1.1.6 root 4134: /* dss / dssall */
1.1.1.7 root 4135: static void gen_dss(DisasContext *ctx)
1.1.1.5 root 4136: {
1.1.1.6 root 4137: /* interpreted as no-op */
1.1 root 4138: }
4139:
4140: /* icbi */
1.1.1.7 root 4141: static void gen_icbi(DisasContext *ctx)
1.1 root 4142: {
1.1.1.6 root 4143: TCGv t0;
4144: gen_set_access_type(ctx, ACCESS_CACHE);
1.1.1.5 root 4145: /* NIP cannot be restored if the memory exception comes from an helper */
4146: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 4147: t0 = tcg_temp_new();
4148: gen_addr_reg_index(ctx, t0);
4149: gen_helper_icbi(t0);
4150: tcg_temp_free(t0);
1.1 root 4151: }
4152:
4153: /* Optional: */
4154: /* dcba */
1.1.1.7 root 4155: static void gen_dcba(DisasContext *ctx)
1.1 root 4156: {
1.1.1.5 root 4157: /* interpreted as no-op */
4158: /* XXX: specification say this is treated as a store by the MMU
4159: * but does not generate any exception
4160: */
1.1 root 4161: }
4162:
4163: /*** Segment register manipulation ***/
4164: /* Supervisor only: */
1.1.1.7 root 4165:
1.1 root 4166: /* mfsr */
1.1.1.7 root 4167: static void gen_mfsr(DisasContext *ctx)
1.1 root 4168: {
4169: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4170: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4171: #else
1.1.1.6 root 4172: TCGv t0;
4173: if (unlikely(!ctx->mem_idx)) {
4174: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4175: return;
4176: }
1.1.1.6 root 4177: t0 = tcg_const_tl(SR(ctx->opcode));
4178: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4179: tcg_temp_free(t0);
1.1 root 4180: #endif
4181: }
4182:
4183: /* mfsrin */
1.1.1.7 root 4184: static void gen_mfsrin(DisasContext *ctx)
1.1 root 4185: {
4186: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4187: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4188: #else
1.1.1.6 root 4189: TCGv t0;
4190: if (unlikely(!ctx->mem_idx)) {
4191: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4192: return;
4193: }
1.1.1.6 root 4194: t0 = tcg_temp_new();
4195: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4196: tcg_gen_andi_tl(t0, t0, 0xF);
4197: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4198: tcg_temp_free(t0);
1.1 root 4199: #endif
4200: }
4201:
4202: /* mtsr */
1.1.1.7 root 4203: static void gen_mtsr(DisasContext *ctx)
1.1 root 4204: {
4205: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4206: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4207: #else
1.1.1.6 root 4208: TCGv t0;
4209: if (unlikely(!ctx->mem_idx)) {
4210: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4211: return;
4212: }
1.1.1.6 root 4213: t0 = tcg_const_tl(SR(ctx->opcode));
4214: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4215: tcg_temp_free(t0);
1.1 root 4216: #endif
4217: }
4218:
4219: /* mtsrin */
1.1.1.7 root 4220: static void gen_mtsrin(DisasContext *ctx)
1.1 root 4221: {
4222: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4223: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4224: #else
1.1.1.6 root 4225: TCGv t0;
4226: if (unlikely(!ctx->mem_idx)) {
4227: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4228: return;
4229: }
1.1.1.6 root 4230: t0 = tcg_temp_new();
4231: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4232: tcg_gen_andi_tl(t0, t0, 0xF);
4233: gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4234: tcg_temp_free(t0);
1.1 root 4235: #endif
4236: }
4237:
1.1.1.5 root 4238: #if defined(TARGET_PPC64)
4239: /* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
1.1.1.7 root 4240:
1.1.1.5 root 4241: /* mfsr */
1.1.1.7 root 4242: static void gen_mfsr_64b(DisasContext *ctx)
1.1 root 4243: {
4244: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4245: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4246: #else
1.1.1.6 root 4247: TCGv t0;
4248: if (unlikely(!ctx->mem_idx)) {
4249: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1 root 4250: return;
4251: }
1.1.1.6 root 4252: t0 = tcg_const_tl(SR(ctx->opcode));
1.1.1.7 root 4253: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.6 root 4254: tcg_temp_free(t0);
1.1.1.5 root 4255: #endif
4256: }
4257:
4258: /* mfsrin */
1.1.1.7 root 4259: static void gen_mfsrin_64b(DisasContext *ctx)
1.1.1.5 root 4260: {
4261: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4262: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4263: #else
1.1.1.6 root 4264: TCGv t0;
4265: if (unlikely(!ctx->mem_idx)) {
4266: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4267: return;
4268: }
1.1.1.6 root 4269: t0 = tcg_temp_new();
4270: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4271: tcg_gen_andi_tl(t0, t0, 0xF);
1.1.1.7 root 4272: gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
1.1.1.6 root 4273: tcg_temp_free(t0);
1.1.1.5 root 4274: #endif
4275: }
4276:
4277: /* mtsr */
1.1.1.7 root 4278: static void gen_mtsr_64b(DisasContext *ctx)
1.1.1.5 root 4279: {
4280: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4281: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4282: #else
1.1.1.6 root 4283: TCGv t0;
4284: if (unlikely(!ctx->mem_idx)) {
4285: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4286: return;
4287: }
1.1.1.6 root 4288: t0 = tcg_const_tl(SR(ctx->opcode));
1.1.1.7 root 4289: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
1.1.1.6 root 4290: tcg_temp_free(t0);
1.1.1.5 root 4291: #endif
4292: }
4293:
4294: /* mtsrin */
1.1.1.7 root 4295: static void gen_mtsrin_64b(DisasContext *ctx)
1.1.1.5 root 4296: {
4297: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4298: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4299: #else
1.1.1.6 root 4300: TCGv t0;
4301: if (unlikely(!ctx->mem_idx)) {
4302: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 4303: return;
4304: }
1.1.1.6 root 4305: t0 = tcg_temp_new();
4306: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4307: tcg_gen_andi_tl(t0, t0, 0xF);
1.1.1.7 root 4308: gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
1.1.1.6 root 4309: tcg_temp_free(t0);
1.1.1.5 root 4310: #endif
4311: }
1.1.1.7 root 4312:
4313: /* slbmte */
4314: static void gen_slbmte(DisasContext *ctx)
4315: {
4316: #if defined(CONFIG_USER_ONLY)
4317: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4318: #else
4319: if (unlikely(!ctx->mem_idx)) {
4320: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4321: return;
4322: }
4323: gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
4324: #endif
4325: }
4326:
1.1.1.11 root 4327: static void gen_slbmfee(DisasContext *ctx)
4328: {
4329: #if defined(CONFIG_USER_ONLY)
4330: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4331: #else
4332: if (unlikely(!ctx->mem_idx)) {
4333: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4334: return;
4335: }
4336: gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)],
4337: cpu_gpr[rB(ctx->opcode)]);
4338: #endif
4339: }
4340:
4341: static void gen_slbmfev(DisasContext *ctx)
4342: {
4343: #if defined(CONFIG_USER_ONLY)
4344: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4345: #else
4346: if (unlikely(!ctx->mem_idx)) {
4347: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4348: return;
4349: }
4350: gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)],
4351: cpu_gpr[rB(ctx->opcode)]);
4352: #endif
4353: }
1.1.1.5 root 4354: #endif /* defined(TARGET_PPC64) */
4355:
4356: /*** Lookaside buffer management ***/
1.1.1.6 root 4357: /* Optional & mem_idx only: */
1.1.1.7 root 4358:
1.1.1.5 root 4359: /* tlbia */
1.1.1.7 root 4360: static void gen_tlbia(DisasContext *ctx)
1.1.1.5 root 4361: {
4362: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4363: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4364: #else
1.1.1.6 root 4365: if (unlikely(!ctx->mem_idx)) {
4366: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4367: return;
4368: }
1.1.1.6 root 4369: gen_helper_tlbia();
1.1 root 4370: #endif
4371: }
4372:
1.1.1.7 root 4373: /* tlbiel */
4374: static void gen_tlbiel(DisasContext *ctx)
4375: {
4376: #if defined(CONFIG_USER_ONLY)
4377: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4378: #else
4379: if (unlikely(!ctx->mem_idx)) {
4380: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4381: return;
4382: }
4383: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4384: #endif
4385: }
4386:
1.1 root 4387: /* tlbie */
1.1.1.7 root 4388: static void gen_tlbie(DisasContext *ctx)
1.1.1.5 root 4389: {
4390: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4391: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4392: #else
1.1.1.6 root 4393: if (unlikely(!ctx->mem_idx)) {
4394: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4395: return;
4396: }
4397: #if defined(TARGET_PPC64)
1.1.1.6 root 4398: if (!ctx->sf_mode) {
4399: TCGv t0 = tcg_temp_new();
4400: tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4401: gen_helper_tlbie(t0);
4402: tcg_temp_free(t0);
4403: } else
1.1.1.5 root 4404: #endif
1.1.1.6 root 4405: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4406: #endif
4407: }
4408:
4409: /* tlbsync */
1.1.1.7 root 4410: static void gen_tlbsync(DisasContext *ctx)
1.1.1.5 root 4411: {
4412: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4413: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4414: #else
1.1.1.6 root 4415: if (unlikely(!ctx->mem_idx)) {
4416: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4417: return;
4418: }
4419: /* This has no effect: it should ensure that all previous
4420: * tlbie have completed
4421: */
1.1.1.6 root 4422: gen_stop_exception(ctx);
1.1.1.5 root 4423: #endif
4424: }
4425:
4426: #if defined(TARGET_PPC64)
4427: /* slbia */
1.1.1.7 root 4428: static void gen_slbia(DisasContext *ctx)
1.1.1.5 root 4429: {
4430: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4431: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4432: #else
1.1.1.6 root 4433: if (unlikely(!ctx->mem_idx)) {
4434: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4435: return;
4436: }
1.1.1.6 root 4437: gen_helper_slbia();
1.1.1.5 root 4438: #endif
4439: }
4440:
4441: /* slbie */
1.1.1.7 root 4442: static void gen_slbie(DisasContext *ctx)
1.1.1.5 root 4443: {
4444: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 4445: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4446: #else
1.1.1.6 root 4447: if (unlikely(!ctx->mem_idx)) {
4448: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 4449: return;
4450: }
1.1.1.6 root 4451: gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4452: #endif
4453: }
4454: #endif
4455:
4456: /*** External control ***/
4457: /* Optional: */
1.1.1.7 root 4458:
1.1.1.5 root 4459: /* eciwx */
1.1.1.7 root 4460: static void gen_eciwx(DisasContext *ctx)
1.1.1.5 root 4461: {
1.1.1.6 root 4462: TCGv t0;
4463: /* Should check EAR[E] ! */
4464: gen_set_access_type(ctx, ACCESS_EXT);
4465: t0 = tcg_temp_new();
4466: gen_addr_reg_index(ctx, t0);
4467: gen_check_align(ctx, t0, 0x03);
4468: gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4469: tcg_temp_free(t0);
1.1.1.5 root 4470: }
4471:
4472: /* ecowx */
1.1.1.7 root 4473: static void gen_ecowx(DisasContext *ctx)
1.1.1.5 root 4474: {
1.1.1.6 root 4475: TCGv t0;
4476: /* Should check EAR[E] ! */
4477: gen_set_access_type(ctx, ACCESS_EXT);
4478: t0 = tcg_temp_new();
4479: gen_addr_reg_index(ctx, t0);
4480: gen_check_align(ctx, t0, 0x03);
4481: gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4482: tcg_temp_free(t0);
1.1.1.5 root 4483: }
4484:
4485: /* PowerPC 601 specific instructions */
1.1.1.7 root 4486:
1.1.1.5 root 4487: /* abs - abs. */
1.1.1.7 root 4488: static void gen_abs(DisasContext *ctx)
1.1.1.5 root 4489: {
1.1.1.6 root 4490: int l1 = gen_new_label();
4491: int l2 = gen_new_label();
4492: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4493: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4494: tcg_gen_br(l2);
4495: gen_set_label(l1);
4496: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4497: gen_set_label(l2);
1.1.1.5 root 4498: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4499: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4500: }
4501:
4502: /* abso - abso. */
1.1.1.7 root 4503: static void gen_abso(DisasContext *ctx)
1.1.1.5 root 4504: {
1.1.1.6 root 4505: int l1 = gen_new_label();
4506: int l2 = gen_new_label();
4507: int l3 = gen_new_label();
4508: /* Start with XER OV disabled, the most likely case */
4509: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4510: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4511: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4512: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4513: tcg_gen_br(l2);
4514: gen_set_label(l1);
4515: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4516: tcg_gen_br(l3);
4517: gen_set_label(l2);
4518: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4519: gen_set_label(l3);
1.1.1.5 root 4520: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4521: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4522: }
4523:
4524: /* clcs */
1.1.1.7 root 4525: static void gen_clcs(DisasContext *ctx)
1.1.1.5 root 4526: {
1.1.1.6 root 4527: TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4528: gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4529: tcg_temp_free_i32(t0);
1.1.1.5 root 4530: /* Rc=1 sets CR0 to an undefined state */
4531: }
4532:
4533: /* div - div. */
1.1.1.7 root 4534: static void gen_div(DisasContext *ctx)
1.1.1.5 root 4535: {
1.1.1.6 root 4536: gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4537: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4538: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4539: }
4540:
4541: /* divo - divo. */
1.1.1.7 root 4542: static void gen_divo(DisasContext *ctx)
1.1.1.5 root 4543: {
1.1.1.6 root 4544: gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4545: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4546: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4547: }
4548:
4549: /* divs - divs. */
1.1.1.7 root 4550: static void gen_divs(DisasContext *ctx)
1.1.1.5 root 4551: {
1.1.1.6 root 4552: gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4553: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4554: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4555: }
4556:
4557: /* divso - divso. */
1.1.1.7 root 4558: static void gen_divso(DisasContext *ctx)
1.1.1.5 root 4559: {
1.1.1.6 root 4560: gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 4561: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4562: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4563: }
4564:
4565: /* doz - doz. */
1.1.1.7 root 4566: static void gen_doz(DisasContext *ctx)
1.1.1.5 root 4567: {
1.1.1.6 root 4568: int l1 = gen_new_label();
4569: int l2 = gen_new_label();
4570: tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4571: tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4572: tcg_gen_br(l2);
4573: gen_set_label(l1);
4574: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4575: gen_set_label(l2);
1.1.1.5 root 4576: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4577: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4578: }
4579:
4580: /* dozo - dozo. */
1.1.1.7 root 4581: static void gen_dozo(DisasContext *ctx)
1.1.1.5 root 4582: {
1.1.1.6 root 4583: int l1 = gen_new_label();
4584: int l2 = gen_new_label();
4585: TCGv t0 = tcg_temp_new();
4586: TCGv t1 = tcg_temp_new();
4587: TCGv t2 = tcg_temp_new();
4588: /* Start with XER OV disabled, the most likely case */
4589: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4590: tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4591: tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4592: tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4593: tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4594: tcg_gen_andc_tl(t1, t1, t2);
4595: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4596: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4597: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4598: tcg_gen_br(l2);
4599: gen_set_label(l1);
4600: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4601: gen_set_label(l2);
4602: tcg_temp_free(t0);
4603: tcg_temp_free(t1);
4604: tcg_temp_free(t2);
1.1.1.5 root 4605: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4606: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4607: }
4608:
4609: /* dozi */
1.1.1.7 root 4610: static void gen_dozi(DisasContext *ctx)
1.1.1.5 root 4611: {
1.1.1.6 root 4612: target_long simm = SIMM(ctx->opcode);
4613: int l1 = gen_new_label();
4614: int l2 = gen_new_label();
4615: tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4616: tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4617: tcg_gen_br(l2);
4618: gen_set_label(l1);
4619: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4620: gen_set_label(l2);
4621: if (unlikely(Rc(ctx->opcode) != 0))
4622: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4623: }
4624:
4625: /* lscbx - lscbx. */
1.1.1.7 root 4626: static void gen_lscbx(DisasContext *ctx)
1.1.1.5 root 4627: {
1.1.1.6 root 4628: TCGv t0 = tcg_temp_new();
4629: TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4630: TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4631: TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
1.1.1.5 root 4632:
1.1.1.6 root 4633: gen_addr_reg_index(ctx, t0);
1.1.1.5 root 4634: /* NIP cannot be restored if the memory exception comes from an helper */
4635: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.6 root 4636: gen_helper_lscbx(t0, t0, t1, t2, t3);
4637: tcg_temp_free_i32(t1);
4638: tcg_temp_free_i32(t2);
4639: tcg_temp_free_i32(t3);
4640: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4641: tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
1.1.1.5 root 4642: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4643: gen_set_Rc0(ctx, t0);
4644: tcg_temp_free(t0);
1.1.1.5 root 4645: }
4646:
4647: /* maskg - maskg. */
1.1.1.7 root 4648: static void gen_maskg(DisasContext *ctx)
1.1.1.5 root 4649: {
1.1.1.6 root 4650: int l1 = gen_new_label();
4651: TCGv t0 = tcg_temp_new();
4652: TCGv t1 = tcg_temp_new();
4653: TCGv t2 = tcg_temp_new();
4654: TCGv t3 = tcg_temp_new();
4655: tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4656: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4657: tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4658: tcg_gen_addi_tl(t2, t0, 1);
4659: tcg_gen_shr_tl(t2, t3, t2);
4660: tcg_gen_shr_tl(t3, t3, t1);
4661: tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4662: tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4663: tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4664: gen_set_label(l1);
4665: tcg_temp_free(t0);
4666: tcg_temp_free(t1);
4667: tcg_temp_free(t2);
4668: tcg_temp_free(t3);
1.1.1.5 root 4669: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4670: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4671: }
4672:
4673: /* maskir - maskir. */
1.1.1.7 root 4674: static void gen_maskir(DisasContext *ctx)
1.1.1.5 root 4675: {
1.1.1.6 root 4676: TCGv t0 = tcg_temp_new();
4677: TCGv t1 = tcg_temp_new();
4678: tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4679: tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4680: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4681: tcg_temp_free(t0);
4682: tcg_temp_free(t1);
1.1.1.5 root 4683: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4684: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4685: }
4686:
4687: /* mul - mul. */
1.1.1.7 root 4688: static void gen_mul(DisasContext *ctx)
1.1.1.5 root 4689: {
1.1.1.6 root 4690: TCGv_i64 t0 = tcg_temp_new_i64();
4691: TCGv_i64 t1 = tcg_temp_new_i64();
4692: TCGv t2 = tcg_temp_new();
4693: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4694: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4695: tcg_gen_mul_i64(t0, t0, t1);
4696: tcg_gen_trunc_i64_tl(t2, t0);
4697: gen_store_spr(SPR_MQ, t2);
4698: tcg_gen_shri_i64(t1, t0, 32);
4699: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4700: tcg_temp_free_i64(t0);
4701: tcg_temp_free_i64(t1);
4702: tcg_temp_free(t2);
1.1.1.5 root 4703: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4704: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4705: }
4706:
4707: /* mulo - mulo. */
1.1.1.7 root 4708: static void gen_mulo(DisasContext *ctx)
1.1.1.5 root 4709: {
1.1.1.6 root 4710: int l1 = gen_new_label();
4711: TCGv_i64 t0 = tcg_temp_new_i64();
4712: TCGv_i64 t1 = tcg_temp_new_i64();
4713: TCGv t2 = tcg_temp_new();
4714: /* Start with XER OV disabled, the most likely case */
4715: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4716: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4717: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4718: tcg_gen_mul_i64(t0, t0, t1);
4719: tcg_gen_trunc_i64_tl(t2, t0);
4720: gen_store_spr(SPR_MQ, t2);
4721: tcg_gen_shri_i64(t1, t0, 32);
4722: tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4723: tcg_gen_ext32s_i64(t1, t0);
4724: tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4725: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4726: gen_set_label(l1);
4727: tcg_temp_free_i64(t0);
4728: tcg_temp_free_i64(t1);
4729: tcg_temp_free(t2);
1.1.1.5 root 4730: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4731: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4732: }
4733:
4734: /* nabs - nabs. */
1.1.1.7 root 4735: static void gen_nabs(DisasContext *ctx)
1.1.1.5 root 4736: {
1.1.1.6 root 4737: int l1 = gen_new_label();
4738: int l2 = gen_new_label();
4739: tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4740: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4741: tcg_gen_br(l2);
4742: gen_set_label(l1);
4743: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4744: gen_set_label(l2);
1.1.1.5 root 4745: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4746: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4747: }
4748:
4749: /* nabso - nabso. */
1.1.1.7 root 4750: static void gen_nabso(DisasContext *ctx)
1.1.1.5 root 4751: {
1.1.1.6 root 4752: int l1 = gen_new_label();
4753: int l2 = gen_new_label();
4754: tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4755: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4756: tcg_gen_br(l2);
4757: gen_set_label(l1);
4758: tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4759: gen_set_label(l2);
4760: /* nabs never overflows */
4761: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1.1.1.5 root 4762: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4763: gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1.1.1.5 root 4764: }
4765:
4766: /* rlmi - rlmi. */
1.1.1.7 root 4767: static void gen_rlmi(DisasContext *ctx)
1.1.1.5 root 4768: {
1.1.1.6 root 4769: uint32_t mb = MB(ctx->opcode);
4770: uint32_t me = ME(ctx->opcode);
4771: TCGv t0 = tcg_temp_new();
4772: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4773: tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4774: tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4775: tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4776: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4777: tcg_temp_free(t0);
1.1.1.5 root 4778: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4779: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4780: }
4781:
4782: /* rrib - rrib. */
1.1.1.7 root 4783: static void gen_rrib(DisasContext *ctx)
1.1.1.5 root 4784: {
1.1.1.6 root 4785: TCGv t0 = tcg_temp_new();
4786: TCGv t1 = tcg_temp_new();
4787: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4788: tcg_gen_movi_tl(t1, 0x80000000);
4789: tcg_gen_shr_tl(t1, t1, t0);
4790: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4791: tcg_gen_and_tl(t0, t0, t1);
4792: tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4793: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4794: tcg_temp_free(t0);
4795: tcg_temp_free(t1);
1.1.1.5 root 4796: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4797: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4798: }
4799:
4800: /* sle - sle. */
1.1.1.7 root 4801: static void gen_sle(DisasContext *ctx)
1.1.1.5 root 4802: {
1.1.1.6 root 4803: TCGv t0 = tcg_temp_new();
4804: TCGv t1 = tcg_temp_new();
4805: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4806: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4807: tcg_gen_subfi_tl(t1, 32, t1);
4808: tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4809: tcg_gen_or_tl(t1, t0, t1);
4810: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4811: gen_store_spr(SPR_MQ, t1);
4812: tcg_temp_free(t0);
4813: tcg_temp_free(t1);
1.1.1.5 root 4814: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4815: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4816: }
4817:
4818: /* sleq - sleq. */
1.1.1.7 root 4819: static void gen_sleq(DisasContext *ctx)
1.1.1.5 root 4820: {
1.1.1.6 root 4821: TCGv t0 = tcg_temp_new();
4822: TCGv t1 = tcg_temp_new();
4823: TCGv t2 = tcg_temp_new();
4824: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4825: tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4826: tcg_gen_shl_tl(t2, t2, t0);
4827: tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4828: gen_load_spr(t1, SPR_MQ);
4829: gen_store_spr(SPR_MQ, t0);
4830: tcg_gen_and_tl(t0, t0, t2);
4831: tcg_gen_andc_tl(t1, t1, t2);
4832: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4833: tcg_temp_free(t0);
4834: tcg_temp_free(t1);
4835: tcg_temp_free(t2);
1.1.1.5 root 4836: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4837: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4838: }
4839:
4840: /* sliq - sliq. */
1.1.1.7 root 4841: static void gen_sliq(DisasContext *ctx)
1.1.1.5 root 4842: {
1.1.1.6 root 4843: int sh = SH(ctx->opcode);
4844: TCGv t0 = tcg_temp_new();
4845: TCGv t1 = tcg_temp_new();
4846: tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4847: tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4848: tcg_gen_or_tl(t1, t0, t1);
4849: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4850: gen_store_spr(SPR_MQ, t1);
4851: tcg_temp_free(t0);
4852: tcg_temp_free(t1);
1.1.1.5 root 4853: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4854: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4855: }
4856:
4857: /* slliq - slliq. */
1.1.1.7 root 4858: static void gen_slliq(DisasContext *ctx)
1.1.1.5 root 4859: {
1.1.1.6 root 4860: int sh = SH(ctx->opcode);
4861: TCGv t0 = tcg_temp_new();
4862: TCGv t1 = tcg_temp_new();
4863: tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4864: gen_load_spr(t1, SPR_MQ);
4865: gen_store_spr(SPR_MQ, t0);
4866: tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
4867: tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4868: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4869: tcg_temp_free(t0);
4870: tcg_temp_free(t1);
1.1.1.5 root 4871: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4872: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4873: }
4874:
4875: /* sllq - sllq. */
1.1.1.7 root 4876: static void gen_sllq(DisasContext *ctx)
1.1.1.5 root 4877: {
1.1.1.6 root 4878: int l1 = gen_new_label();
4879: int l2 = gen_new_label();
4880: TCGv t0 = tcg_temp_local_new();
4881: TCGv t1 = tcg_temp_local_new();
4882: TCGv t2 = tcg_temp_local_new();
4883: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4884: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4885: tcg_gen_shl_tl(t1, t1, t2);
4886: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4887: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4888: gen_load_spr(t0, SPR_MQ);
4889: tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4890: tcg_gen_br(l2);
4891: gen_set_label(l1);
4892: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4893: gen_load_spr(t2, SPR_MQ);
4894: tcg_gen_andc_tl(t1, t2, t1);
4895: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4896: gen_set_label(l2);
4897: tcg_temp_free(t0);
4898: tcg_temp_free(t1);
4899: tcg_temp_free(t2);
1.1.1.5 root 4900: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4901: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4902: }
4903:
4904: /* slq - slq. */
1.1.1.7 root 4905: static void gen_slq(DisasContext *ctx)
1.1.1.5 root 4906: {
1.1.1.6 root 4907: int l1 = gen_new_label();
4908: TCGv t0 = tcg_temp_new();
4909: TCGv t1 = tcg_temp_new();
4910: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4911: tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4912: tcg_gen_subfi_tl(t1, 32, t1);
4913: tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4914: tcg_gen_or_tl(t1, t0, t1);
4915: gen_store_spr(SPR_MQ, t1);
4916: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4917: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4918: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4919: tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4920: gen_set_label(l1);
4921: tcg_temp_free(t0);
4922: tcg_temp_free(t1);
1.1.1.5 root 4923: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4924: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4925: }
4926:
4927: /* sraiq - sraiq. */
1.1.1.7 root 4928: static void gen_sraiq(DisasContext *ctx)
1.1.1.5 root 4929: {
1.1.1.6 root 4930: int sh = SH(ctx->opcode);
4931: int l1 = gen_new_label();
4932: TCGv t0 = tcg_temp_new();
4933: TCGv t1 = tcg_temp_new();
4934: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4935: tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4936: tcg_gen_or_tl(t0, t0, t1);
4937: gen_store_spr(SPR_MQ, t0);
4938: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4939: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4940: tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4941: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4942: gen_set_label(l1);
4943: tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4944: tcg_temp_free(t0);
4945: tcg_temp_free(t1);
1.1.1.5 root 4946: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4947: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4948: }
4949:
4950: /* sraq - sraq. */
1.1.1.7 root 4951: static void gen_sraq(DisasContext *ctx)
1.1.1.5 root 4952: {
1.1.1.6 root 4953: int l1 = gen_new_label();
4954: int l2 = gen_new_label();
4955: TCGv t0 = tcg_temp_new();
4956: TCGv t1 = tcg_temp_local_new();
4957: TCGv t2 = tcg_temp_local_new();
4958: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4959: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4960: tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4961: tcg_gen_subfi_tl(t2, 32, t2);
4962: tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4963: tcg_gen_or_tl(t0, t0, t2);
4964: gen_store_spr(SPR_MQ, t0);
4965: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4966: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4967: tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4968: tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4969: gen_set_label(l1);
4970: tcg_temp_free(t0);
4971: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4972: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4973: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4974: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4975: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4976: gen_set_label(l2);
4977: tcg_temp_free(t1);
4978: tcg_temp_free(t2);
1.1.1.5 root 4979: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4980: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4981: }
4982:
4983: /* sre - sre. */
1.1.1.7 root 4984: static void gen_sre(DisasContext *ctx)
1.1.1.5 root 4985: {
1.1.1.6 root 4986: TCGv t0 = tcg_temp_new();
4987: TCGv t1 = tcg_temp_new();
4988: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4989: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4990: tcg_gen_subfi_tl(t1, 32, t1);
4991: tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4992: tcg_gen_or_tl(t1, t0, t1);
4993: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4994: gen_store_spr(SPR_MQ, t1);
4995: tcg_temp_free(t0);
4996: tcg_temp_free(t1);
1.1.1.5 root 4997: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 4998: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 4999: }
5000:
5001: /* srea - srea. */
1.1.1.7 root 5002: static void gen_srea(DisasContext *ctx)
1.1.1.5 root 5003: {
1.1.1.6 root 5004: TCGv t0 = tcg_temp_new();
5005: TCGv t1 = tcg_temp_new();
5006: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5007: tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5008: gen_store_spr(SPR_MQ, t0);
5009: tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
5010: tcg_temp_free(t0);
5011: tcg_temp_free(t1);
1.1.1.5 root 5012: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 5013: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5014: }
5015:
5016: /* sreq */
1.1.1.7 root 5017: static void gen_sreq(DisasContext *ctx)
1.1.1.5 root 5018: {
1.1.1.6 root 5019: TCGv t0 = tcg_temp_new();
5020: TCGv t1 = tcg_temp_new();
5021: TCGv t2 = tcg_temp_new();
5022: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5023: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5024: tcg_gen_shr_tl(t1, t1, t0);
5025: tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5026: gen_load_spr(t2, SPR_MQ);
5027: gen_store_spr(SPR_MQ, t0);
5028: tcg_gen_and_tl(t0, t0, t1);
5029: tcg_gen_andc_tl(t2, t2, t1);
5030: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5031: tcg_temp_free(t0);
5032: tcg_temp_free(t1);
5033: tcg_temp_free(t2);
1.1.1.5 root 5034: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 5035: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5036: }
5037:
5038: /* sriq */
1.1.1.7 root 5039: static void gen_sriq(DisasContext *ctx)
1.1.1.5 root 5040: {
1.1.1.6 root 5041: int sh = SH(ctx->opcode);
5042: TCGv t0 = tcg_temp_new();
5043: TCGv t1 = tcg_temp_new();
5044: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5045: tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5046: tcg_gen_or_tl(t1, t0, t1);
5047: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5048: gen_store_spr(SPR_MQ, t1);
5049: tcg_temp_free(t0);
5050: tcg_temp_free(t1);
1.1.1.5 root 5051: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 5052: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5053: }
5054:
5055: /* srliq */
1.1.1.7 root 5056: static void gen_srliq(DisasContext *ctx)
1.1.1.5 root 5057: {
1.1.1.6 root 5058: int sh = SH(ctx->opcode);
5059: TCGv t0 = tcg_temp_new();
5060: TCGv t1 = tcg_temp_new();
5061: tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5062: gen_load_spr(t1, SPR_MQ);
5063: gen_store_spr(SPR_MQ, t0);
5064: tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
5065: tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5066: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5067: tcg_temp_free(t0);
5068: tcg_temp_free(t1);
1.1.1.5 root 5069: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 5070: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5071: }
5072:
5073: /* srlq */
1.1.1.7 root 5074: static void gen_srlq(DisasContext *ctx)
1.1.1.5 root 5075: {
1.1.1.6 root 5076: int l1 = gen_new_label();
5077: int l2 = gen_new_label();
5078: TCGv t0 = tcg_temp_local_new();
5079: TCGv t1 = tcg_temp_local_new();
5080: TCGv t2 = tcg_temp_local_new();
5081: tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5082: tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5083: tcg_gen_shr_tl(t2, t1, t2);
5084: tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5085: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5086: gen_load_spr(t0, SPR_MQ);
5087: tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5088: tcg_gen_br(l2);
5089: gen_set_label(l1);
5090: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5091: tcg_gen_and_tl(t0, t0, t2);
5092: gen_load_spr(t1, SPR_MQ);
5093: tcg_gen_andc_tl(t1, t1, t2);
5094: tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5095: gen_set_label(l2);
5096: tcg_temp_free(t0);
5097: tcg_temp_free(t1);
5098: tcg_temp_free(t2);
1.1.1.5 root 5099: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 5100: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5101: }
5102:
5103: /* srq */
1.1.1.7 root 5104: static void gen_srq(DisasContext *ctx)
1.1.1.5 root 5105: {
1.1.1.6 root 5106: int l1 = gen_new_label();
5107: TCGv t0 = tcg_temp_new();
5108: TCGv t1 = tcg_temp_new();
5109: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5110: tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5111: tcg_gen_subfi_tl(t1, 32, t1);
5112: tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5113: tcg_gen_or_tl(t1, t0, t1);
5114: gen_store_spr(SPR_MQ, t1);
5115: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5116: tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5117: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5118: tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5119: gen_set_label(l1);
5120: tcg_temp_free(t0);
5121: tcg_temp_free(t1);
1.1.1.5 root 5122: if (unlikely(Rc(ctx->opcode) != 0))
1.1.1.6 root 5123: gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5124: }
5125:
5126: /* PowerPC 602 specific instructions */
1.1.1.7 root 5127:
1.1.1.5 root 5128: /* dsa */
1.1.1.7 root 5129: static void gen_dsa(DisasContext *ctx)
1.1.1.5 root 5130: {
5131: /* XXX: TODO */
1.1.1.6 root 5132: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5133: }
5134:
5135: /* esa */
1.1.1.7 root 5136: static void gen_esa(DisasContext *ctx)
1.1.1.5 root 5137: {
5138: /* XXX: TODO */
1.1.1.6 root 5139: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5140: }
5141:
5142: /* mfrom */
1.1.1.7 root 5143: static void gen_mfrom(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: if (unlikely(!ctx->mem_idx)) {
5149: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5150: return;
5151: }
1.1.1.6 root 5152: gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5153: #endif
5154: }
5155:
5156: /* 602 - 603 - G2 TLB management */
1.1.1.7 root 5157:
1.1.1.5 root 5158: /* tlbld */
1.1.1.7 root 5159: static void gen_tlbld_6xx(DisasContext *ctx)
1.1.1.5 root 5160: {
5161: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5162: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5163: #else
1.1.1.6 root 5164: if (unlikely(!ctx->mem_idx)) {
5165: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5166: return;
5167: }
1.1.1.6 root 5168: gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5169: #endif
5170: }
5171:
5172: /* tlbli */
1.1.1.7 root 5173: static void gen_tlbli_6xx(DisasContext *ctx)
1.1.1.5 root 5174: {
5175: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5176: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5177: #else
1.1.1.6 root 5178: if (unlikely(!ctx->mem_idx)) {
5179: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5180: return;
5181: }
1.1.1.6 root 5182: gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5183: #endif
5184: }
5185:
5186: /* 74xx TLB management */
1.1.1.7 root 5187:
1.1.1.5 root 5188: /* tlbld */
1.1.1.7 root 5189: static void gen_tlbld_74xx(DisasContext *ctx)
1.1.1.5 root 5190: {
5191: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5192: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5193: #else
1.1.1.6 root 5194: if (unlikely(!ctx->mem_idx)) {
5195: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5196: return;
5197: }
1.1.1.6 root 5198: gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5199: #endif
5200: }
5201:
5202: /* tlbli */
1.1.1.7 root 5203: static void gen_tlbli_74xx(DisasContext *ctx)
1.1.1.5 root 5204: {
5205: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5206: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5207: #else
1.1.1.6 root 5208: if (unlikely(!ctx->mem_idx)) {
5209: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5210: return;
5211: }
1.1.1.6 root 5212: gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
1.1.1.5 root 5213: #endif
5214: }
5215:
5216: /* POWER instructions not in PowerPC 601 */
1.1.1.7 root 5217:
1.1.1.5 root 5218: /* clf */
1.1.1.7 root 5219: static void gen_clf(DisasContext *ctx)
1.1.1.5 root 5220: {
5221: /* Cache line flush: implemented as no-op */
5222: }
5223:
5224: /* cli */
1.1.1.7 root 5225: static void gen_cli(DisasContext *ctx)
1.1.1.5 root 5226: {
5227: /* Cache line invalidate: privileged and treated as no-op */
5228: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5229: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5230: #else
1.1.1.6 root 5231: if (unlikely(!ctx->mem_idx)) {
5232: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5233: return;
5234: }
5235: #endif
5236: }
5237:
5238: /* dclst */
1.1.1.7 root 5239: static void gen_dclst(DisasContext *ctx)
1.1.1.5 root 5240: {
5241: /* Data cache line store: treated as no-op */
5242: }
5243:
1.1.1.7 root 5244: static void gen_mfsri(DisasContext *ctx)
1.1.1.5 root 5245: {
5246: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5247: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5248: #else
5249: int ra = rA(ctx->opcode);
5250: int rd = rD(ctx->opcode);
1.1.1.6 root 5251: TCGv t0;
5252: if (unlikely(!ctx->mem_idx)) {
5253: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5254: return;
5255: }
5256: t0 = tcg_temp_new();
5257: gen_addr_reg_index(ctx, t0);
5258: tcg_gen_shri_tl(t0, t0, 28);
5259: tcg_gen_andi_tl(t0, t0, 0xF);
5260: gen_helper_load_sr(cpu_gpr[rd], t0);
5261: tcg_temp_free(t0);
1.1.1.5 root 5262: if (ra != 0 && ra != rd)
1.1.1.6 root 5263: tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
1.1.1.5 root 5264: #endif
5265: }
5266:
1.1.1.7 root 5267: static void gen_rac(DisasContext *ctx)
1.1.1.5 root 5268: {
5269: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5270: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5271: #else
1.1.1.6 root 5272: TCGv t0;
5273: if (unlikely(!ctx->mem_idx)) {
5274: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5275: return;
5276: }
1.1.1.6 root 5277: t0 = tcg_temp_new();
5278: gen_addr_reg_index(ctx, t0);
5279: gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5280: tcg_temp_free(t0);
1.1.1.5 root 5281: #endif
5282: }
5283:
1.1.1.7 root 5284: static void gen_rfsvc(DisasContext *ctx)
1.1.1.5 root 5285: {
5286: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5287: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5288: #else
1.1.1.6 root 5289: if (unlikely(!ctx->mem_idx)) {
5290: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5291: return;
5292: }
1.1.1.6 root 5293: gen_helper_rfsvc();
5294: gen_sync_exception(ctx);
1.1.1.5 root 5295: #endif
5296: }
5297:
5298: /* svc is not implemented for now */
5299:
5300: /* POWER2 specific instructions */
5301: /* Quad manipulation (load/store two floats at a time) */
5302:
5303: /* lfq */
1.1.1.7 root 5304: static void gen_lfq(DisasContext *ctx)
1.1.1.5 root 5305: {
1.1.1.6 root 5306: int rd = rD(ctx->opcode);
5307: TCGv t0;
5308: gen_set_access_type(ctx, ACCESS_FLOAT);
5309: t0 = tcg_temp_new();
5310: gen_addr_imm_index(ctx, t0, 0);
5311: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5312: gen_addr_add(ctx, t0, t0, 8);
5313: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5314: tcg_temp_free(t0);
1.1.1.5 root 5315: }
5316:
5317: /* lfqu */
1.1.1.7 root 5318: static void gen_lfqu(DisasContext *ctx)
1.1.1.5 root 5319: {
5320: int ra = rA(ctx->opcode);
1.1.1.6 root 5321: int rd = rD(ctx->opcode);
5322: TCGv t0, t1;
5323: gen_set_access_type(ctx, ACCESS_FLOAT);
5324: t0 = tcg_temp_new();
5325: t1 = tcg_temp_new();
5326: gen_addr_imm_index(ctx, t0, 0);
5327: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5328: gen_addr_add(ctx, t1, t0, 8);
5329: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
1.1.1.5 root 5330: if (ra != 0)
1.1.1.6 root 5331: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5332: tcg_temp_free(t0);
5333: tcg_temp_free(t1);
1.1.1.5 root 5334: }
5335:
5336: /* lfqux */
1.1.1.7 root 5337: static void gen_lfqux(DisasContext *ctx)
1.1.1.5 root 5338: {
5339: int ra = rA(ctx->opcode);
1.1.1.6 root 5340: int rd = rD(ctx->opcode);
5341: gen_set_access_type(ctx, ACCESS_FLOAT);
5342: TCGv t0, t1;
5343: t0 = tcg_temp_new();
5344: gen_addr_reg_index(ctx, t0);
5345: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5346: t1 = tcg_temp_new();
5347: gen_addr_add(ctx, t1, t0, 8);
5348: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5349: tcg_temp_free(t1);
1.1.1.5 root 5350: if (ra != 0)
1.1.1.6 root 5351: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5352: tcg_temp_free(t0);
1.1.1.5 root 5353: }
5354:
5355: /* lfqx */
1.1.1.7 root 5356: static void gen_lfqx(DisasContext *ctx)
1.1.1.5 root 5357: {
1.1.1.6 root 5358: int rd = rD(ctx->opcode);
5359: TCGv t0;
5360: gen_set_access_type(ctx, ACCESS_FLOAT);
5361: t0 = tcg_temp_new();
5362: gen_addr_reg_index(ctx, t0);
5363: gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5364: gen_addr_add(ctx, t0, t0, 8);
5365: gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5366: tcg_temp_free(t0);
1.1.1.5 root 5367: }
5368:
5369: /* stfq */
1.1.1.7 root 5370: static void gen_stfq(DisasContext *ctx)
1.1.1.5 root 5371: {
1.1.1.6 root 5372: int rd = rD(ctx->opcode);
5373: TCGv t0;
5374: gen_set_access_type(ctx, ACCESS_FLOAT);
5375: t0 = tcg_temp_new();
5376: gen_addr_imm_index(ctx, t0, 0);
5377: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5378: gen_addr_add(ctx, t0, t0, 8);
5379: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5380: tcg_temp_free(t0);
1.1.1.5 root 5381: }
5382:
5383: /* stfqu */
1.1.1.7 root 5384: static void gen_stfqu(DisasContext *ctx)
1.1.1.5 root 5385: {
5386: int ra = rA(ctx->opcode);
1.1.1.6 root 5387: int rd = rD(ctx->opcode);
5388: TCGv t0, t1;
5389: gen_set_access_type(ctx, ACCESS_FLOAT);
5390: t0 = tcg_temp_new();
5391: gen_addr_imm_index(ctx, t0, 0);
5392: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5393: t1 = tcg_temp_new();
5394: gen_addr_add(ctx, t1, t0, 8);
5395: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5396: tcg_temp_free(t1);
1.1.1.5 root 5397: if (ra != 0)
1.1.1.6 root 5398: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5399: tcg_temp_free(t0);
1.1.1.5 root 5400: }
5401:
5402: /* stfqux */
1.1.1.7 root 5403: static void gen_stfqux(DisasContext *ctx)
1.1.1.5 root 5404: {
5405: int ra = rA(ctx->opcode);
1.1.1.6 root 5406: int rd = rD(ctx->opcode);
5407: TCGv t0, t1;
5408: gen_set_access_type(ctx, ACCESS_FLOAT);
5409: t0 = tcg_temp_new();
5410: gen_addr_reg_index(ctx, t0);
5411: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5412: t1 = tcg_temp_new();
5413: gen_addr_add(ctx, t1, t0, 8);
5414: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5415: tcg_temp_free(t1);
1.1.1.5 root 5416: if (ra != 0)
1.1.1.6 root 5417: tcg_gen_mov_tl(cpu_gpr[ra], t0);
5418: tcg_temp_free(t0);
1.1.1.5 root 5419: }
5420:
5421: /* stfqx */
1.1.1.7 root 5422: static void gen_stfqx(DisasContext *ctx)
1.1.1.5 root 5423: {
1.1.1.6 root 5424: int rd = rD(ctx->opcode);
5425: TCGv t0;
5426: gen_set_access_type(ctx, ACCESS_FLOAT);
5427: t0 = tcg_temp_new();
5428: gen_addr_reg_index(ctx, t0);
5429: gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5430: gen_addr_add(ctx, t0, t0, 8);
5431: gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5432: tcg_temp_free(t0);
1.1.1.5 root 5433: }
5434:
5435: /* BookE specific instructions */
1.1.1.7 root 5436:
1.1.1.5 root 5437: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5438: static void gen_mfapidi(DisasContext *ctx)
1.1.1.5 root 5439: {
5440: /* XXX: TODO */
1.1.1.6 root 5441: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5442: }
5443:
5444: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5445: static void gen_tlbiva(DisasContext *ctx)
1.1.1.5 root 5446: {
5447: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5448: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5449: #else
1.1.1.6 root 5450: TCGv t0;
5451: if (unlikely(!ctx->mem_idx)) {
5452: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5453: return;
5454: }
1.1.1.6 root 5455: t0 = tcg_temp_new();
5456: gen_addr_reg_index(ctx, t0);
5457: gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
5458: tcg_temp_free(t0);
1.1.1.5 root 5459: #endif
5460: }
5461:
5462: /* All 405 MAC instructions are translated here */
1.1.1.8 root 5463: static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
5464: int ra, int rb, int rt, int Rc)
1.1.1.5 root 5465: {
1.1.1.6 root 5466: TCGv t0, t1;
5467:
5468: t0 = tcg_temp_local_new();
5469: t1 = tcg_temp_local_new();
5470:
1.1.1.5 root 5471: switch (opc3 & 0x0D) {
5472: case 0x05:
5473: /* macchw - macchw. - macchwo - macchwo. */
5474: /* macchws - macchws. - macchwso - macchwso. */
5475: /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5476: /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5477: /* mulchw - mulchw. */
1.1.1.6 root 5478: tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5479: tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5480: tcg_gen_ext16s_tl(t1, t1);
1.1.1.5 root 5481: break;
5482: case 0x04:
5483: /* macchwu - macchwu. - macchwuo - macchwuo. */
5484: /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5485: /* mulchwu - mulchwu. */
1.1.1.6 root 5486: tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5487: tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5488: tcg_gen_ext16u_tl(t1, t1);
1.1.1.5 root 5489: break;
5490: case 0x01:
5491: /* machhw - machhw. - machhwo - machhwo. */
5492: /* machhws - machhws. - machhwso - machhwso. */
5493: /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5494: /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5495: /* mulhhw - mulhhw. */
1.1.1.6 root 5496: tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5497: tcg_gen_ext16s_tl(t0, t0);
5498: tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5499: tcg_gen_ext16s_tl(t1, t1);
1.1.1.5 root 5500: break;
5501: case 0x00:
5502: /* machhwu - machhwu. - machhwuo - machhwuo. */
5503: /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5504: /* mulhhwu - mulhhwu. */
1.1.1.6 root 5505: tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5506: tcg_gen_ext16u_tl(t0, t0);
5507: tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5508: tcg_gen_ext16u_tl(t1, t1);
1.1.1.5 root 5509: break;
5510: case 0x0D:
5511: /* maclhw - maclhw. - maclhwo - maclhwo. */
5512: /* maclhws - maclhws. - maclhwso - maclhwso. */
5513: /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5514: /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5515: /* mullhw - mullhw. */
1.1.1.6 root 5516: tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5517: tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
1.1.1.5 root 5518: break;
5519: case 0x0C:
5520: /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5521: /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5522: /* mullhwu - mullhwu. */
1.1.1.6 root 5523: tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5524: tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
1.1.1.5 root 5525: break;
5526: }
5527: if (opc2 & 0x04) {
1.1.1.6 root 5528: /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5529: tcg_gen_mul_tl(t1, t0, t1);
5530: if (opc2 & 0x02) {
5531: /* nmultiply-and-accumulate (0x0E) */
5532: tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5533: } else {
5534: /* multiply-and-accumulate (0x0C) */
5535: tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5536: }
5537:
5538: if (opc3 & 0x12) {
5539: /* Check overflow and/or saturate */
5540: int l1 = gen_new_label();
5541:
5542: if (opc3 & 0x10) {
5543: /* Start with XER OV disabled, the most likely case */
5544: tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5545: }
5546: if (opc3 & 0x01) {
5547: /* Signed */
5548: tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5549: tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5550: tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5551: tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
5552: if (opc3 & 0x02) {
5553: /* Saturate */
5554: tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5555: tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5556: }
5557: } else {
5558: /* Unsigned */
5559: tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5560: if (opc3 & 0x02) {
5561: /* Saturate */
5562: tcg_gen_movi_tl(t0, UINT32_MAX);
5563: }
5564: }
5565: if (opc3 & 0x10) {
5566: /* Check overflow */
5567: tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5568: }
5569: gen_set_label(l1);
5570: tcg_gen_mov_tl(cpu_gpr[rt], t0);
5571: }
5572: } else {
5573: tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
1.1.1.5 root 5574: }
1.1.1.6 root 5575: tcg_temp_free(t0);
5576: tcg_temp_free(t1);
1.1.1.5 root 5577: if (unlikely(Rc) != 0) {
5578: /* Update Rc0 */
1.1.1.6 root 5579: gen_set_Rc0(ctx, cpu_gpr[rt]);
1.1.1.5 root 5580: }
5581: }
5582:
5583: #define GEN_MAC_HANDLER(name, opc2, opc3) \
1.1.1.7 root 5584: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.5 root 5585: { \
5586: gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5587: rD(ctx->opcode), Rc(ctx->opcode)); \
5588: }
5589:
5590: /* macchw - macchw. */
5591: GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5592: /* macchwo - macchwo. */
5593: GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5594: /* macchws - macchws. */
5595: GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5596: /* macchwso - macchwso. */
5597: GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5598: /* macchwsu - macchwsu. */
5599: GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5600: /* macchwsuo - macchwsuo. */
5601: GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5602: /* macchwu - macchwu. */
5603: GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5604: /* macchwuo - macchwuo. */
5605: GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5606: /* machhw - machhw. */
5607: GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5608: /* machhwo - machhwo. */
5609: GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5610: /* machhws - machhws. */
5611: GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5612: /* machhwso - machhwso. */
5613: GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5614: /* machhwsu - machhwsu. */
5615: GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5616: /* machhwsuo - machhwsuo. */
5617: GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5618: /* machhwu - machhwu. */
5619: GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5620: /* machhwuo - machhwuo. */
5621: GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5622: /* maclhw - maclhw. */
5623: GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5624: /* maclhwo - maclhwo. */
5625: GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5626: /* maclhws - maclhws. */
5627: GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5628: /* maclhwso - maclhwso. */
5629: GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5630: /* maclhwu - maclhwu. */
5631: GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5632: /* maclhwuo - maclhwuo. */
5633: GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5634: /* maclhwsu - maclhwsu. */
5635: GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5636: /* maclhwsuo - maclhwsuo. */
5637: GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5638: /* nmacchw - nmacchw. */
5639: GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5640: /* nmacchwo - nmacchwo. */
5641: GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5642: /* nmacchws - nmacchws. */
5643: GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5644: /* nmacchwso - nmacchwso. */
5645: GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5646: /* nmachhw - nmachhw. */
5647: GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5648: /* nmachhwo - nmachhwo. */
5649: GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5650: /* nmachhws - nmachhws. */
5651: GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5652: /* nmachhwso - nmachhwso. */
5653: GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5654: /* nmaclhw - nmaclhw. */
5655: GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5656: /* nmaclhwo - nmaclhwo. */
5657: GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5658: /* nmaclhws - nmaclhws. */
5659: GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5660: /* nmaclhwso - nmaclhwso. */
5661: GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5662:
5663: /* mulchw - mulchw. */
5664: GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5665: /* mulchwu - mulchwu. */
5666: GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5667: /* mulhhw - mulhhw. */
5668: GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5669: /* mulhhwu - mulhhwu. */
5670: GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5671: /* mullhw - mullhw. */
5672: GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5673: /* mullhwu - mullhwu. */
5674: GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5675:
5676: /* mfdcr */
1.1.1.7 root 5677: static void gen_mfdcr(DisasContext *ctx)
1.1.1.5 root 5678: {
5679: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5680: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5681: #else
1.1.1.6 root 5682: TCGv dcrn;
5683: if (unlikely(!ctx->mem_idx)) {
5684: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5685: return;
5686: }
1.1.1.6 root 5687: /* NIP cannot be restored if the memory exception comes from an helper */
5688: gen_update_nip(ctx, ctx->nip - 4);
5689: dcrn = tcg_const_tl(SPR(ctx->opcode));
5690: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5691: tcg_temp_free(dcrn);
1.1.1.5 root 5692: #endif
5693: }
5694:
5695: /* mtdcr */
1.1.1.7 root 5696: static void gen_mtdcr(DisasContext *ctx)
1.1.1.5 root 5697: {
5698: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5699: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5700: #else
1.1.1.6 root 5701: TCGv dcrn;
5702: if (unlikely(!ctx->mem_idx)) {
5703: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5704: return;
5705: }
1.1.1.6 root 5706: /* NIP cannot be restored if the memory exception comes from an helper */
5707: gen_update_nip(ctx, ctx->nip - 4);
5708: dcrn = tcg_const_tl(SPR(ctx->opcode));
5709: gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5710: tcg_temp_free(dcrn);
1.1.1.5 root 5711: #endif
5712: }
5713:
5714: /* mfdcrx */
5715: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5716: static void gen_mfdcrx(DisasContext *ctx)
1.1.1.5 root 5717: {
5718: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5719: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5720: #else
1.1.1.6 root 5721: if (unlikely(!ctx->mem_idx)) {
5722: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5723: return;
5724: }
1.1.1.6 root 5725: /* NIP cannot be restored if the memory exception comes from an helper */
5726: gen_update_nip(ctx, ctx->nip - 4);
5727: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5728: /* Note: Rc update flag set leads to undefined state of Rc0 */
5729: #endif
5730: }
5731:
5732: /* mtdcrx */
5733: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5734: static void gen_mtdcrx(DisasContext *ctx)
1.1.1.5 root 5735: {
5736: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5737: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5738: #else
1.1.1.6 root 5739: if (unlikely(!ctx->mem_idx)) {
5740: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
1.1.1.5 root 5741: return;
5742: }
1.1.1.6 root 5743: /* NIP cannot be restored if the memory exception comes from an helper */
5744: gen_update_nip(ctx, ctx->nip - 4);
5745: gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5746: /* Note: Rc update flag set leads to undefined state of Rc0 */
5747: #endif
5748: }
5749:
5750: /* mfdcrux (PPC 460) : user-mode access to DCR */
1.1.1.7 root 5751: static void gen_mfdcrux(DisasContext *ctx)
1.1.1.5 root 5752: {
1.1.1.6 root 5753: /* NIP cannot be restored if the memory exception comes from an helper */
5754: gen_update_nip(ctx, ctx->nip - 4);
5755: gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5756: /* Note: Rc update flag set leads to undefined state of Rc0 */
5757: }
5758:
5759: /* mtdcrux (PPC 460) : user-mode access to DCR */
1.1.1.7 root 5760: static void gen_mtdcrux(DisasContext *ctx)
1.1.1.5 root 5761: {
1.1.1.6 root 5762: /* NIP cannot be restored if the memory exception comes from an helper */
5763: gen_update_nip(ctx, ctx->nip - 4);
5764: gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5765: /* Note: Rc update flag set leads to undefined state of Rc0 */
5766: }
5767:
5768: /* dccci */
1.1.1.7 root 5769: static void gen_dccci(DisasContext *ctx)
1.1.1.5 root 5770: {
5771: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5772: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5773: #else
1.1.1.6 root 5774: if (unlikely(!ctx->mem_idx)) {
5775: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5776: return;
5777: }
5778: /* interpreted as no-op */
5779: #endif
5780: }
5781:
5782: /* dcread */
1.1.1.7 root 5783: static void gen_dcread(DisasContext *ctx)
1.1.1.5 root 5784: {
5785: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5786: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5787: #else
1.1.1.6 root 5788: TCGv EA, val;
5789: if (unlikely(!ctx->mem_idx)) {
5790: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5791: return;
5792: }
1.1.1.6 root 5793: gen_set_access_type(ctx, ACCESS_CACHE);
5794: EA = tcg_temp_new();
5795: gen_addr_reg_index(ctx, EA);
5796: val = tcg_temp_new();
5797: gen_qemu_ld32u(ctx, val, EA);
5798: tcg_temp_free(val);
5799: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5800: tcg_temp_free(EA);
1.1.1.5 root 5801: #endif
5802: }
5803:
5804: /* icbt */
1.1.1.7 root 5805: static void gen_icbt_40x(DisasContext *ctx)
1.1.1.5 root 5806: {
5807: /* interpreted as no-op */
5808: /* XXX: specification say this is treated as a load by the MMU
5809: * but does not generate any exception
5810: */
5811: }
5812:
5813: /* iccci */
1.1.1.7 root 5814: static void gen_iccci(DisasContext *ctx)
1.1.1.5 root 5815: {
5816: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5817: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5818: #else
1.1.1.6 root 5819: if (unlikely(!ctx->mem_idx)) {
5820: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5821: return;
5822: }
5823: /* interpreted as no-op */
5824: #endif
5825: }
5826:
5827: /* icread */
1.1.1.7 root 5828: static void gen_icread(DisasContext *ctx)
1.1.1.5 root 5829: {
5830: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5831: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5832: #else
1.1.1.6 root 5833: if (unlikely(!ctx->mem_idx)) {
5834: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5835: return;
5836: }
5837: /* interpreted as no-op */
5838: #endif
5839: }
5840:
1.1.1.6 root 5841: /* rfci (mem_idx only) */
1.1.1.7 root 5842: static void gen_rfci_40x(DisasContext *ctx)
1.1.1.5 root 5843: {
5844: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5845: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5846: #else
1.1.1.6 root 5847: if (unlikely(!ctx->mem_idx)) {
5848: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5849: return;
5850: }
5851: /* Restore CPU state */
1.1.1.6 root 5852: gen_helper_40x_rfci();
5853: gen_sync_exception(ctx);
1.1.1.5 root 5854: #endif
5855: }
5856:
1.1.1.7 root 5857: static void gen_rfci(DisasContext *ctx)
1.1.1.5 root 5858: {
5859: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5860: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5861: #else
1.1.1.6 root 5862: if (unlikely(!ctx->mem_idx)) {
5863: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5864: return;
5865: }
5866: /* Restore CPU state */
1.1.1.6 root 5867: gen_helper_rfci();
5868: gen_sync_exception(ctx);
1.1.1.5 root 5869: #endif
5870: }
5871:
5872: /* BookE specific */
1.1.1.7 root 5873:
1.1.1.5 root 5874: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5875: static void gen_rfdi(DisasContext *ctx)
1.1.1.5 root 5876: {
5877: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5878: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5879: #else
1.1.1.6 root 5880: if (unlikely(!ctx->mem_idx)) {
5881: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5882: return;
5883: }
5884: /* Restore CPU state */
1.1.1.6 root 5885: gen_helper_rfdi();
5886: gen_sync_exception(ctx);
1.1.1.5 root 5887: #endif
5888: }
5889:
5890: /* XXX: not implemented on 440 ? */
1.1.1.7 root 5891: static void gen_rfmci(DisasContext *ctx)
1.1.1.5 root 5892: {
5893: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5894: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5895: #else
1.1.1.6 root 5896: if (unlikely(!ctx->mem_idx)) {
5897: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5898: return;
5899: }
5900: /* Restore CPU state */
1.1.1.6 root 5901: gen_helper_rfmci();
5902: gen_sync_exception(ctx);
1.1.1.5 root 5903: #endif
5904: }
5905:
5906: /* TLB management - PowerPC 405 implementation */
1.1.1.7 root 5907:
1.1.1.5 root 5908: /* tlbre */
1.1.1.7 root 5909: static void gen_tlbre_40x(DisasContext *ctx)
1.1.1.5 root 5910: {
5911: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5912: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5913: #else
1.1.1.6 root 5914: if (unlikely(!ctx->mem_idx)) {
5915: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5916: return;
5917: }
5918: switch (rB(ctx->opcode)) {
5919: case 0:
1.1.1.6 root 5920: gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5921: break;
5922: case 1:
1.1.1.6 root 5923: gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.5 root 5924: break;
5925: default:
1.1.1.6 root 5926: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5927: break;
5928: }
5929: #endif
5930: }
5931:
5932: /* tlbsx - tlbsx. */
1.1.1.7 root 5933: static void gen_tlbsx_40x(DisasContext *ctx)
1.1.1.5 root 5934: {
5935: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5936: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5937: #else
1.1.1.6 root 5938: TCGv t0;
5939: if (unlikely(!ctx->mem_idx)) {
5940: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5941: return;
5942: }
1.1.1.6 root 5943: t0 = tcg_temp_new();
5944: gen_addr_reg_index(ctx, t0);
5945: gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5946: tcg_temp_free(t0);
5947: if (Rc(ctx->opcode)) {
5948: int l1 = gen_new_label();
5949: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5950: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5951: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5952: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5953: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5954: gen_set_label(l1);
5955: }
1.1.1.5 root 5956: #endif
5957: }
5958:
5959: /* tlbwe */
1.1.1.7 root 5960: static void gen_tlbwe_40x(DisasContext *ctx)
1.1.1.5 root 5961: {
5962: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5963: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5964: #else
1.1.1.6 root 5965: if (unlikely(!ctx->mem_idx)) {
5966: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5967: return;
5968: }
5969: switch (rB(ctx->opcode)) {
5970: case 0:
1.1.1.6 root 5971: gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5972: break;
5973: case 1:
1.1.1.6 root 5974: gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1.1.1.5 root 5975: break;
5976: default:
1.1.1.6 root 5977: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 5978: break;
5979: }
5980: #endif
5981: }
5982:
5983: /* TLB management - PowerPC 440 implementation */
1.1.1.7 root 5984:
1.1.1.5 root 5985: /* tlbre */
1.1.1.7 root 5986: static void gen_tlbre_440(DisasContext *ctx)
1.1.1.5 root 5987: {
5988: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 5989: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5990: #else
1.1.1.6 root 5991: if (unlikely(!ctx->mem_idx)) {
5992: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 5993: return;
5994: }
5995: switch (rB(ctx->opcode)) {
5996: case 0:
5997: case 1:
5998: case 2:
1.1.1.6 root 5999: {
6000: TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
1.1.1.10 root 6001: gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], t0, cpu_gpr[rA(ctx->opcode)]);
1.1.1.6 root 6002: tcg_temp_free_i32(t0);
6003: }
1.1.1.5 root 6004: break;
6005: default:
1.1.1.6 root 6006: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 6007: break;
6008: }
6009: #endif
6010: }
6011:
6012: /* tlbsx - tlbsx. */
1.1.1.7 root 6013: static void gen_tlbsx_440(DisasContext *ctx)
1.1 root 6014: {
6015: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 6016: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 6017: #else
1.1.1.6 root 6018: TCGv t0;
6019: if (unlikely(!ctx->mem_idx)) {
6020: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 6021: return;
6022: }
1.1.1.6 root 6023: t0 = tcg_temp_new();
6024: gen_addr_reg_index(ctx, t0);
6025: gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
6026: tcg_temp_free(t0);
6027: if (Rc(ctx->opcode)) {
6028: int l1 = gen_new_label();
6029: tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
6030: tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
6031: tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
6032: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6033: tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6034: gen_set_label(l1);
6035: }
1.1 root 6036: #endif
6037: }
6038:
1.1.1.5 root 6039: /* tlbwe */
1.1.1.7 root 6040: static void gen_tlbwe_440(DisasContext *ctx)
1.1 root 6041: {
6042: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 6043: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 6044: #else
1.1.1.6 root 6045: if (unlikely(!ctx->mem_idx)) {
6046: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1 root 6047: return;
6048: }
1.1.1.5 root 6049: switch (rB(ctx->opcode)) {
6050: case 0:
6051: case 1:
6052: case 2:
1.1.1.6 root 6053: {
6054: TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6055: gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
6056: tcg_temp_free_i32(t0);
6057: }
1.1.1.5 root 6058: break;
6059: default:
1.1.1.6 root 6060: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 6061: break;
6062: }
6063: #endif
6064: }
6065:
1.1.1.11 root 6066: /* TLB management - PowerPC BookE 2.06 implementation */
6067:
6068: /* tlbre */
6069: static void gen_tlbre_booke206(DisasContext *ctx)
6070: {
6071: #if defined(CONFIG_USER_ONLY)
6072: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6073: #else
6074: if (unlikely(!ctx->mem_idx)) {
6075: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6076: return;
6077: }
6078:
6079: gen_helper_booke206_tlbre();
6080: #endif
6081: }
6082:
6083: /* tlbsx - tlbsx. */
6084: static void gen_tlbsx_booke206(DisasContext *ctx)
6085: {
6086: #if defined(CONFIG_USER_ONLY)
6087: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6088: #else
6089: TCGv t0;
6090: if (unlikely(!ctx->mem_idx)) {
6091: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6092: return;
6093: }
6094:
6095: if (rA(ctx->opcode)) {
6096: t0 = tcg_temp_new();
6097: tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6098: } else {
6099: t0 = tcg_const_tl(0);
6100: }
6101:
6102: tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
6103: gen_helper_booke206_tlbsx(t0);
6104: #endif
6105: }
6106:
6107: /* tlbwe */
6108: static void gen_tlbwe_booke206(DisasContext *ctx)
6109: {
6110: #if defined(CONFIG_USER_ONLY)
6111: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6112: #else
6113: if (unlikely(!ctx->mem_idx)) {
6114: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6115: return;
6116: }
1.1.1.13! root 6117: gen_update_nip(ctx, ctx->nip - 4);
1.1.1.11 root 6118: gen_helper_booke206_tlbwe();
6119: #endif
6120: }
6121:
6122: static void gen_tlbivax_booke206(DisasContext *ctx)
6123: {
6124: #if defined(CONFIG_USER_ONLY)
6125: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6126: #else
6127: TCGv t0;
6128: if (unlikely(!ctx->mem_idx)) {
6129: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6130: return;
6131: }
6132:
6133: t0 = tcg_temp_new();
6134: gen_addr_reg_index(ctx, t0);
6135:
6136: gen_helper_booke206_tlbivax(t0);
6137: #endif
6138: }
6139:
1.1.1.13! root 6140: static void gen_tlbilx_booke206(DisasContext *ctx)
! 6141: {
! 6142: #if defined(CONFIG_USER_ONLY)
! 6143: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
! 6144: #else
! 6145: TCGv t0;
! 6146: if (unlikely(!ctx->mem_idx)) {
! 6147: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
! 6148: return;
! 6149: }
! 6150:
! 6151: t0 = tcg_temp_new();
! 6152: gen_addr_reg_index(ctx, t0);
! 6153:
! 6154: switch((ctx->opcode >> 21) & 0x3) {
! 6155: case 0:
! 6156: gen_helper_booke206_tlbilx0(t0);
! 6157: break;
! 6158: case 1:
! 6159: gen_helper_booke206_tlbilx1(t0);
! 6160: break;
! 6161: case 3:
! 6162: gen_helper_booke206_tlbilx3(t0);
! 6163: break;
! 6164: default:
! 6165: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
! 6166: break;
! 6167: }
! 6168:
! 6169: tcg_temp_free(t0);
! 6170: #endif
! 6171: }
! 6172:
1.1.1.11 root 6173:
1.1.1.5 root 6174: /* wrtee */
1.1.1.7 root 6175: static void gen_wrtee(DisasContext *ctx)
1.1.1.5 root 6176: {
6177: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 6178: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 6179: #else
1.1.1.6 root 6180: TCGv t0;
6181: if (unlikely(!ctx->mem_idx)) {
6182: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 6183: return;
6184: }
1.1.1.6 root 6185: t0 = tcg_temp_new();
6186: tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6187: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6188: tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6189: tcg_temp_free(t0);
1.1.1.5 root 6190: /* Stop translation to have a chance to raise an exception
6191: * if we just set msr_ee to 1
1.1 root 6192: */
1.1.1.6 root 6193: gen_stop_exception(ctx);
1.1 root 6194: #endif
6195: }
6196:
1.1.1.5 root 6197: /* wrteei */
1.1.1.7 root 6198: static void gen_wrteei(DisasContext *ctx)
1.1.1.5 root 6199: {
1.1 root 6200: #if defined(CONFIG_USER_ONLY)
1.1.1.6 root 6201: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 6202: #else
1.1.1.6 root 6203: if (unlikely(!ctx->mem_idx)) {
6204: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1.1.1.5 root 6205: return;
6206: }
1.1.1.7 root 6207: if (ctx->opcode & 0x00008000) {
1.1.1.6 root 6208: tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6209: /* Stop translation to have a chance to raise an exception */
6210: gen_stop_exception(ctx);
6211: } else {
6212: tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6213: }
1.1.1.5 root 6214: #endif
6215: }
6216:
6217: /* PowerPC 440 specific instructions */
1.1.1.7 root 6218:
1.1.1.5 root 6219: /* dlmzb */
1.1.1.7 root 6220: static void gen_dlmzb(DisasContext *ctx)
1.1.1.5 root 6221: {
1.1.1.6 root 6222: TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6223: gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
6224: cpu_gpr[rB(ctx->opcode)], t0);
6225: tcg_temp_free_i32(t0);
1.1.1.5 root 6226: }
6227:
6228: /* mbar replaces eieio on 440 */
1.1.1.7 root 6229: static void gen_mbar(DisasContext *ctx)
1.1.1.5 root 6230: {
6231: /* interpreted as no-op */
6232: }
6233:
6234: /* msync replaces sync on 440 */
1.1.1.13! root 6235: static void gen_msync_4xx(DisasContext *ctx)
1.1.1.5 root 6236: {
6237: /* interpreted as no-op */
6238: }
6239:
6240: /* icbt */
1.1.1.7 root 6241: static void gen_icbt_440(DisasContext *ctx)
1.1.1.5 root 6242: {
6243: /* interpreted as no-op */
6244: /* XXX: specification say this is treated as a load by the MMU
6245: * but does not generate any exception
6246: */
6247: }
6248:
1.1.1.13! root 6249: /* Embedded.Processor Control */
! 6250:
! 6251: static void gen_msgclr(DisasContext *ctx)
! 6252: {
! 6253: #if defined(CONFIG_USER_ONLY)
! 6254: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
! 6255: #else
! 6256: if (unlikely(ctx->mem_idx == 0)) {
! 6257: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
! 6258: return;
! 6259: }
! 6260:
! 6261: gen_helper_msgclr(cpu_gpr[rB(ctx->opcode)]);
! 6262: #endif
! 6263: }
! 6264:
! 6265: static void gen_msgsnd(DisasContext *ctx)
! 6266: {
! 6267: #if defined(CONFIG_USER_ONLY)
! 6268: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
! 6269: #else
! 6270: if (unlikely(ctx->mem_idx == 0)) {
! 6271: gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
! 6272: return;
! 6273: }
! 6274:
! 6275: gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
! 6276: #endif
! 6277: }
! 6278:
1.1.1.5 root 6279: /*** Altivec vector extension ***/
6280: /* Altivec registers moves */
6281:
1.1.1.8 root 6282: static inline TCGv_ptr gen_avr_ptr(int reg)
1.1.1.6 root 6283: {
6284: TCGv_ptr r = tcg_temp_new_ptr();
6285: tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6286: return r;
6287: }
1.1.1.5 root 6288:
6289: #define GEN_VR_LDX(name, opc2, opc3) \
1.1.1.7 root 6290: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.5 root 6291: { \
1.1.1.6 root 6292: TCGv EA; \
1.1.1.5 root 6293: if (unlikely(!ctx->altivec_enabled)) { \
1.1.1.6 root 6294: gen_exception(ctx, POWERPC_EXCP_VPU); \
1.1.1.5 root 6295: return; \
6296: } \
1.1.1.6 root 6297: gen_set_access_type(ctx, ACCESS_INT); \
6298: EA = tcg_temp_new(); \
6299: gen_addr_reg_index(ctx, EA); \
6300: tcg_gen_andi_tl(EA, EA, ~0xf); \
6301: if (ctx->le_mode) { \
6302: gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6303: tcg_gen_addi_tl(EA, EA, 8); \
6304: gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6305: } else { \
6306: gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6307: tcg_gen_addi_tl(EA, EA, 8); \
6308: gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6309: } \
6310: tcg_temp_free(EA); \
1.1.1.5 root 6311: }
6312:
6313: #define GEN_VR_STX(name, opc2, opc3) \
1.1.1.7 root 6314: static void gen_st##name(DisasContext *ctx) \
1.1.1.5 root 6315: { \
1.1.1.6 root 6316: TCGv EA; \
1.1.1.5 root 6317: if (unlikely(!ctx->altivec_enabled)) { \
1.1.1.6 root 6318: gen_exception(ctx, POWERPC_EXCP_VPU); \
1.1.1.5 root 6319: return; \
6320: } \
1.1.1.6 root 6321: gen_set_access_type(ctx, ACCESS_INT); \
6322: EA = tcg_temp_new(); \
6323: gen_addr_reg_index(ctx, EA); \
6324: tcg_gen_andi_tl(EA, EA, ~0xf); \
6325: if (ctx->le_mode) { \
6326: gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6327: tcg_gen_addi_tl(EA, EA, 8); \
6328: gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6329: } else { \
6330: gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
6331: tcg_gen_addi_tl(EA, EA, 8); \
6332: gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
6333: } \
6334: tcg_temp_free(EA); \
1.1.1.5 root 6335: }
6336:
1.1.1.6 root 6337: #define GEN_VR_LVE(name, opc2, opc3) \
1.1.1.7 root 6338: static void gen_lve##name(DisasContext *ctx) \
1.1.1.6 root 6339: { \
6340: TCGv EA; \
6341: TCGv_ptr rs; \
6342: if (unlikely(!ctx->altivec_enabled)) { \
6343: gen_exception(ctx, POWERPC_EXCP_VPU); \
6344: return; \
6345: } \
6346: gen_set_access_type(ctx, ACCESS_INT); \
6347: EA = tcg_temp_new(); \
6348: gen_addr_reg_index(ctx, EA); \
6349: rs = gen_avr_ptr(rS(ctx->opcode)); \
6350: gen_helper_lve##name (rs, EA); \
6351: tcg_temp_free(EA); \
6352: tcg_temp_free_ptr(rs); \
6353: }
6354:
6355: #define GEN_VR_STVE(name, opc2, opc3) \
1.1.1.7 root 6356: static void gen_stve##name(DisasContext *ctx) \
1.1.1.6 root 6357: { \
6358: TCGv EA; \
6359: TCGv_ptr rs; \
6360: if (unlikely(!ctx->altivec_enabled)) { \
6361: gen_exception(ctx, POWERPC_EXCP_VPU); \
6362: return; \
6363: } \
6364: gen_set_access_type(ctx, ACCESS_INT); \
6365: EA = tcg_temp_new(); \
6366: gen_addr_reg_index(ctx, EA); \
6367: rs = gen_avr_ptr(rS(ctx->opcode)); \
6368: gen_helper_stve##name (rs, EA); \
6369: tcg_temp_free(EA); \
6370: tcg_temp_free_ptr(rs); \
6371: }
6372:
6373: GEN_VR_LDX(lvx, 0x07, 0x03);
1.1.1.5 root 6374: /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
1.1.1.6 root 6375: GEN_VR_LDX(lvxl, 0x07, 0x0B);
1.1.1.5 root 6376:
1.1.1.6 root 6377: GEN_VR_LVE(bx, 0x07, 0x00);
6378: GEN_VR_LVE(hx, 0x07, 0x01);
6379: GEN_VR_LVE(wx, 0x07, 0x02);
6380:
6381: GEN_VR_STX(svx, 0x07, 0x07);
1.1.1.5 root 6382: /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
1.1.1.6 root 6383: GEN_VR_STX(svxl, 0x07, 0x0F);
6384:
6385: GEN_VR_STVE(bx, 0x07, 0x04);
6386: GEN_VR_STVE(hx, 0x07, 0x05);
6387: GEN_VR_STVE(wx, 0x07, 0x06);
6388:
1.1.1.7 root 6389: static void gen_lvsl(DisasContext *ctx)
1.1.1.6 root 6390: {
6391: TCGv_ptr rd;
6392: TCGv EA;
6393: if (unlikely(!ctx->altivec_enabled)) {
6394: gen_exception(ctx, POWERPC_EXCP_VPU);
6395: return;
6396: }
6397: EA = tcg_temp_new();
6398: gen_addr_reg_index(ctx, EA);
6399: rd = gen_avr_ptr(rD(ctx->opcode));
6400: gen_helper_lvsl(rd, EA);
6401: tcg_temp_free(EA);
6402: tcg_temp_free_ptr(rd);
6403: }
6404:
1.1.1.7 root 6405: static void gen_lvsr(DisasContext *ctx)
1.1.1.6 root 6406: {
6407: TCGv_ptr rd;
6408: TCGv EA;
6409: if (unlikely(!ctx->altivec_enabled)) {
6410: gen_exception(ctx, POWERPC_EXCP_VPU);
6411: return;
6412: }
6413: EA = tcg_temp_new();
6414: gen_addr_reg_index(ctx, EA);
6415: rd = gen_avr_ptr(rD(ctx->opcode));
6416: gen_helper_lvsr(rd, EA);
6417: tcg_temp_free(EA);
6418: tcg_temp_free_ptr(rd);
6419: }
6420:
1.1.1.7 root 6421: static void gen_mfvscr(DisasContext *ctx)
1.1.1.6 root 6422: {
6423: TCGv_i32 t;
6424: if (unlikely(!ctx->altivec_enabled)) {
6425: gen_exception(ctx, POWERPC_EXCP_VPU);
6426: return;
6427: }
6428: tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6429: t = tcg_temp_new_i32();
1.1.1.13! root 6430: tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
1.1.1.6 root 6431: tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6432: tcg_temp_free_i32(t);
6433: }
6434:
1.1.1.7 root 6435: static void gen_mtvscr(DisasContext *ctx)
1.1.1.6 root 6436: {
6437: TCGv_ptr p;
6438: if (unlikely(!ctx->altivec_enabled)) {
6439: gen_exception(ctx, POWERPC_EXCP_VPU);
6440: return;
6441: }
6442: p = gen_avr_ptr(rD(ctx->opcode));
6443: gen_helper_mtvscr(p);
6444: tcg_temp_free_ptr(p);
6445: }
6446:
6447: /* Logical operations */
6448: #define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
1.1.1.7 root 6449: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6450: { \
6451: if (unlikely(!ctx->altivec_enabled)) { \
6452: gen_exception(ctx, POWERPC_EXCP_VPU); \
6453: return; \
6454: } \
6455: tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6456: tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6457: }
6458:
6459: GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6460: GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6461: GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6462: GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6463: GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6464:
6465: #define GEN_VXFORM(name, opc2, opc3) \
1.1.1.7 root 6466: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6467: { \
6468: TCGv_ptr ra, rb, rd; \
6469: if (unlikely(!ctx->altivec_enabled)) { \
6470: gen_exception(ctx, POWERPC_EXCP_VPU); \
6471: return; \
6472: } \
6473: ra = gen_avr_ptr(rA(ctx->opcode)); \
6474: rb = gen_avr_ptr(rB(ctx->opcode)); \
6475: rd = gen_avr_ptr(rD(ctx->opcode)); \
6476: gen_helper_##name (rd, ra, rb); \
6477: tcg_temp_free_ptr(ra); \
6478: tcg_temp_free_ptr(rb); \
6479: tcg_temp_free_ptr(rd); \
6480: }
6481:
6482: GEN_VXFORM(vaddubm, 0, 0);
6483: GEN_VXFORM(vadduhm, 0, 1);
6484: GEN_VXFORM(vadduwm, 0, 2);
6485: GEN_VXFORM(vsububm, 0, 16);
6486: GEN_VXFORM(vsubuhm, 0, 17);
6487: GEN_VXFORM(vsubuwm, 0, 18);
6488: GEN_VXFORM(vmaxub, 1, 0);
6489: GEN_VXFORM(vmaxuh, 1, 1);
6490: GEN_VXFORM(vmaxuw, 1, 2);
6491: GEN_VXFORM(vmaxsb, 1, 4);
6492: GEN_VXFORM(vmaxsh, 1, 5);
6493: GEN_VXFORM(vmaxsw, 1, 6);
6494: GEN_VXFORM(vminub, 1, 8);
6495: GEN_VXFORM(vminuh, 1, 9);
6496: GEN_VXFORM(vminuw, 1, 10);
6497: GEN_VXFORM(vminsb, 1, 12);
6498: GEN_VXFORM(vminsh, 1, 13);
6499: GEN_VXFORM(vminsw, 1, 14);
6500: GEN_VXFORM(vavgub, 1, 16);
6501: GEN_VXFORM(vavguh, 1, 17);
6502: GEN_VXFORM(vavguw, 1, 18);
6503: GEN_VXFORM(vavgsb, 1, 20);
6504: GEN_VXFORM(vavgsh, 1, 21);
6505: GEN_VXFORM(vavgsw, 1, 22);
6506: GEN_VXFORM(vmrghb, 6, 0);
6507: GEN_VXFORM(vmrghh, 6, 1);
6508: GEN_VXFORM(vmrghw, 6, 2);
6509: GEN_VXFORM(vmrglb, 6, 4);
6510: GEN_VXFORM(vmrglh, 6, 5);
6511: GEN_VXFORM(vmrglw, 6, 6);
6512: GEN_VXFORM(vmuloub, 4, 0);
6513: GEN_VXFORM(vmulouh, 4, 1);
6514: GEN_VXFORM(vmulosb, 4, 4);
6515: GEN_VXFORM(vmulosh, 4, 5);
6516: GEN_VXFORM(vmuleub, 4, 8);
6517: GEN_VXFORM(vmuleuh, 4, 9);
6518: GEN_VXFORM(vmulesb, 4, 12);
6519: GEN_VXFORM(vmulesh, 4, 13);
6520: GEN_VXFORM(vslb, 2, 4);
6521: GEN_VXFORM(vslh, 2, 5);
6522: GEN_VXFORM(vslw, 2, 6);
6523: GEN_VXFORM(vsrb, 2, 8);
6524: GEN_VXFORM(vsrh, 2, 9);
6525: GEN_VXFORM(vsrw, 2, 10);
6526: GEN_VXFORM(vsrab, 2, 12);
6527: GEN_VXFORM(vsrah, 2, 13);
6528: GEN_VXFORM(vsraw, 2, 14);
6529: GEN_VXFORM(vslo, 6, 16);
6530: GEN_VXFORM(vsro, 6, 17);
6531: GEN_VXFORM(vaddcuw, 0, 6);
6532: GEN_VXFORM(vsubcuw, 0, 22);
6533: GEN_VXFORM(vaddubs, 0, 8);
6534: GEN_VXFORM(vadduhs, 0, 9);
6535: GEN_VXFORM(vadduws, 0, 10);
6536: GEN_VXFORM(vaddsbs, 0, 12);
6537: GEN_VXFORM(vaddshs, 0, 13);
6538: GEN_VXFORM(vaddsws, 0, 14);
6539: GEN_VXFORM(vsububs, 0, 24);
6540: GEN_VXFORM(vsubuhs, 0, 25);
6541: GEN_VXFORM(vsubuws, 0, 26);
6542: GEN_VXFORM(vsubsbs, 0, 28);
6543: GEN_VXFORM(vsubshs, 0, 29);
6544: GEN_VXFORM(vsubsws, 0, 30);
6545: GEN_VXFORM(vrlb, 2, 0);
6546: GEN_VXFORM(vrlh, 2, 1);
6547: GEN_VXFORM(vrlw, 2, 2);
6548: GEN_VXFORM(vsl, 2, 7);
6549: GEN_VXFORM(vsr, 2, 11);
6550: GEN_VXFORM(vpkuhum, 7, 0);
6551: GEN_VXFORM(vpkuwum, 7, 1);
6552: GEN_VXFORM(vpkuhus, 7, 2);
6553: GEN_VXFORM(vpkuwus, 7, 3);
6554: GEN_VXFORM(vpkshus, 7, 4);
6555: GEN_VXFORM(vpkswus, 7, 5);
6556: GEN_VXFORM(vpkshss, 7, 6);
6557: GEN_VXFORM(vpkswss, 7, 7);
6558: GEN_VXFORM(vpkpx, 7, 12);
6559: GEN_VXFORM(vsum4ubs, 4, 24);
6560: GEN_VXFORM(vsum4sbs, 4, 28);
6561: GEN_VXFORM(vsum4shs, 4, 25);
6562: GEN_VXFORM(vsum2sws, 4, 26);
6563: GEN_VXFORM(vsumsws, 4, 30);
6564: GEN_VXFORM(vaddfp, 5, 0);
6565: GEN_VXFORM(vsubfp, 5, 1);
6566: GEN_VXFORM(vmaxfp, 5, 16);
6567: GEN_VXFORM(vminfp, 5, 17);
6568:
6569: #define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
1.1.1.7 root 6570: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6571: { \
6572: TCGv_ptr ra, rb, rd; \
6573: if (unlikely(!ctx->altivec_enabled)) { \
6574: gen_exception(ctx, POWERPC_EXCP_VPU); \
6575: return; \
6576: } \
6577: ra = gen_avr_ptr(rA(ctx->opcode)); \
6578: rb = gen_avr_ptr(rB(ctx->opcode)); \
6579: rd = gen_avr_ptr(rD(ctx->opcode)); \
6580: gen_helper_##opname (rd, ra, rb); \
6581: tcg_temp_free_ptr(ra); \
6582: tcg_temp_free_ptr(rb); \
6583: tcg_temp_free_ptr(rd); \
6584: }
6585:
6586: #define GEN_VXRFORM(name, opc2, opc3) \
6587: GEN_VXRFORM1(name, name, #name, opc2, opc3) \
6588: GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
6589:
6590: GEN_VXRFORM(vcmpequb, 3, 0)
6591: GEN_VXRFORM(vcmpequh, 3, 1)
6592: GEN_VXRFORM(vcmpequw, 3, 2)
6593: GEN_VXRFORM(vcmpgtsb, 3, 12)
6594: GEN_VXRFORM(vcmpgtsh, 3, 13)
6595: GEN_VXRFORM(vcmpgtsw, 3, 14)
6596: GEN_VXRFORM(vcmpgtub, 3, 8)
6597: GEN_VXRFORM(vcmpgtuh, 3, 9)
6598: GEN_VXRFORM(vcmpgtuw, 3, 10)
6599: GEN_VXRFORM(vcmpeqfp, 3, 3)
6600: GEN_VXRFORM(vcmpgefp, 3, 7)
6601: GEN_VXRFORM(vcmpgtfp, 3, 11)
6602: GEN_VXRFORM(vcmpbfp, 3, 15)
6603:
6604: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
1.1.1.7 root 6605: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6606: { \
6607: TCGv_ptr rd; \
6608: TCGv_i32 simm; \
6609: if (unlikely(!ctx->altivec_enabled)) { \
6610: gen_exception(ctx, POWERPC_EXCP_VPU); \
6611: return; \
6612: } \
6613: simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6614: rd = gen_avr_ptr(rD(ctx->opcode)); \
6615: gen_helper_##name (rd, simm); \
6616: tcg_temp_free_i32(simm); \
6617: tcg_temp_free_ptr(rd); \
6618: }
6619:
6620: GEN_VXFORM_SIMM(vspltisb, 6, 12);
6621: GEN_VXFORM_SIMM(vspltish, 6, 13);
6622: GEN_VXFORM_SIMM(vspltisw, 6, 14);
6623:
6624: #define GEN_VXFORM_NOA(name, opc2, opc3) \
1.1.1.7 root 6625: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6626: { \
6627: TCGv_ptr rb, rd; \
6628: if (unlikely(!ctx->altivec_enabled)) { \
6629: gen_exception(ctx, POWERPC_EXCP_VPU); \
6630: return; \
6631: } \
6632: rb = gen_avr_ptr(rB(ctx->opcode)); \
6633: rd = gen_avr_ptr(rD(ctx->opcode)); \
6634: gen_helper_##name (rd, rb); \
6635: tcg_temp_free_ptr(rb); \
6636: tcg_temp_free_ptr(rd); \
6637: }
6638:
6639: GEN_VXFORM_NOA(vupkhsb, 7, 8);
6640: GEN_VXFORM_NOA(vupkhsh, 7, 9);
6641: GEN_VXFORM_NOA(vupklsb, 7, 10);
6642: GEN_VXFORM_NOA(vupklsh, 7, 11);
6643: GEN_VXFORM_NOA(vupkhpx, 7, 13);
6644: GEN_VXFORM_NOA(vupklpx, 7, 15);
6645: GEN_VXFORM_NOA(vrefp, 5, 4);
6646: GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
1.1.1.9 root 6647: GEN_VXFORM_NOA(vexptefp, 5, 6);
1.1.1.6 root 6648: GEN_VXFORM_NOA(vlogefp, 5, 7);
6649: GEN_VXFORM_NOA(vrfim, 5, 8);
6650: GEN_VXFORM_NOA(vrfin, 5, 9);
6651: GEN_VXFORM_NOA(vrfip, 5, 10);
6652: GEN_VXFORM_NOA(vrfiz, 5, 11);
6653:
6654: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
1.1.1.7 root 6655: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6656: { \
6657: TCGv_ptr rd; \
6658: TCGv_i32 simm; \
6659: if (unlikely(!ctx->altivec_enabled)) { \
6660: gen_exception(ctx, POWERPC_EXCP_VPU); \
6661: return; \
6662: } \
6663: simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6664: rd = gen_avr_ptr(rD(ctx->opcode)); \
6665: gen_helper_##name (rd, simm); \
6666: tcg_temp_free_i32(simm); \
6667: tcg_temp_free_ptr(rd); \
6668: }
6669:
6670: #define GEN_VXFORM_UIMM(name, opc2, opc3) \
1.1.1.7 root 6671: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 6672: { \
6673: TCGv_ptr rb, rd; \
6674: TCGv_i32 uimm; \
6675: if (unlikely(!ctx->altivec_enabled)) { \
6676: gen_exception(ctx, POWERPC_EXCP_VPU); \
6677: return; \
6678: } \
6679: uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
6680: rb = gen_avr_ptr(rB(ctx->opcode)); \
6681: rd = gen_avr_ptr(rD(ctx->opcode)); \
6682: gen_helper_##name (rd, rb, uimm); \
6683: tcg_temp_free_i32(uimm); \
6684: tcg_temp_free_ptr(rb); \
6685: tcg_temp_free_ptr(rd); \
6686: }
6687:
6688: GEN_VXFORM_UIMM(vspltb, 6, 8);
6689: GEN_VXFORM_UIMM(vsplth, 6, 9);
6690: GEN_VXFORM_UIMM(vspltw, 6, 10);
6691: GEN_VXFORM_UIMM(vcfux, 5, 12);
6692: GEN_VXFORM_UIMM(vcfsx, 5, 13);
6693: GEN_VXFORM_UIMM(vctuxs, 5, 14);
6694: GEN_VXFORM_UIMM(vctsxs, 5, 15);
6695:
1.1.1.7 root 6696: static void gen_vsldoi(DisasContext *ctx)
1.1.1.6 root 6697: {
6698: TCGv_ptr ra, rb, rd;
6699: TCGv_i32 sh;
6700: if (unlikely(!ctx->altivec_enabled)) {
6701: gen_exception(ctx, POWERPC_EXCP_VPU);
6702: return;
6703: }
6704: ra = gen_avr_ptr(rA(ctx->opcode));
6705: rb = gen_avr_ptr(rB(ctx->opcode));
6706: rd = gen_avr_ptr(rD(ctx->opcode));
6707: sh = tcg_const_i32(VSH(ctx->opcode));
6708: gen_helper_vsldoi (rd, ra, rb, sh);
6709: tcg_temp_free_ptr(ra);
6710: tcg_temp_free_ptr(rb);
6711: tcg_temp_free_ptr(rd);
6712: tcg_temp_free_i32(sh);
6713: }
6714:
6715: #define GEN_VAFORM_PAIRED(name0, name1, opc2) \
1.1.1.7 root 6716: static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
1.1.1.6 root 6717: { \
6718: TCGv_ptr ra, rb, rc, rd; \
6719: if (unlikely(!ctx->altivec_enabled)) { \
6720: gen_exception(ctx, POWERPC_EXCP_VPU); \
6721: return; \
6722: } \
6723: ra = gen_avr_ptr(rA(ctx->opcode)); \
6724: rb = gen_avr_ptr(rB(ctx->opcode)); \
6725: rc = gen_avr_ptr(rC(ctx->opcode)); \
6726: rd = gen_avr_ptr(rD(ctx->opcode)); \
6727: if (Rc(ctx->opcode)) { \
6728: gen_helper_##name1 (rd, ra, rb, rc); \
6729: } else { \
6730: gen_helper_##name0 (rd, ra, rb, rc); \
6731: } \
6732: tcg_temp_free_ptr(ra); \
6733: tcg_temp_free_ptr(rb); \
6734: tcg_temp_free_ptr(rc); \
6735: tcg_temp_free_ptr(rd); \
6736: }
6737:
6738: GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
6739:
1.1.1.7 root 6740: static void gen_vmladduhm(DisasContext *ctx)
1.1.1.6 root 6741: {
6742: TCGv_ptr ra, rb, rc, rd;
6743: if (unlikely(!ctx->altivec_enabled)) {
6744: gen_exception(ctx, POWERPC_EXCP_VPU);
6745: return;
6746: }
6747: ra = gen_avr_ptr(rA(ctx->opcode));
6748: rb = gen_avr_ptr(rB(ctx->opcode));
6749: rc = gen_avr_ptr(rC(ctx->opcode));
6750: rd = gen_avr_ptr(rD(ctx->opcode));
6751: gen_helper_vmladduhm(rd, ra, rb, rc);
6752: tcg_temp_free_ptr(ra);
6753: tcg_temp_free_ptr(rb);
6754: tcg_temp_free_ptr(rc);
6755: tcg_temp_free_ptr(rd);
6756: }
6757:
6758: GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
6759: GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
6760: GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
6761: GEN_VAFORM_PAIRED(vsel, vperm, 21)
6762: GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
1.1.1.5 root 6763:
6764: /*** SPE extension ***/
6765: /* Register moves */
6766:
1.1.1.11 root 6767:
6768: static inline void gen_evmra(DisasContext *ctx)
6769: {
6770:
6771: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 6772: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.11 root 6773: return;
6774: }
6775:
6776: #if defined(TARGET_PPC64)
6777: /* rD := rA */
6778: tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6779:
6780: /* spe_acc := rA */
6781: tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
6782: cpu_env,
1.1.1.13! root 6783: offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 6784: #else
6785: TCGv_i64 tmp = tcg_temp_new_i64();
6786:
6787: /* tmp := rA_lo + rA_hi << 32 */
6788: tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6789:
6790: /* spe_acc := tmp */
1.1.1.13! root 6791: tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 6792: tcg_temp_free_i64(tmp);
6793:
6794: /* rD := rA */
6795: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6796: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6797: #endif
6798: }
6799:
1.1.1.8 root 6800: static inline void gen_load_gpr64(TCGv_i64 t, int reg)
6801: {
1.1.1.6 root 6802: #if defined(TARGET_PPC64)
6803: tcg_gen_mov_i64(t, cpu_gpr[reg]);
6804: #else
6805: tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
1.1.1.5 root 6806: #endif
1.1.1.6 root 6807: }
1.1.1.5 root 6808:
1.1.1.8 root 6809: static inline void gen_store_gpr64(int reg, TCGv_i64 t)
6810: {
1.1.1.6 root 6811: #if defined(TARGET_PPC64)
6812: tcg_gen_mov_i64(cpu_gpr[reg], t);
6813: #else
6814: TCGv_i64 tmp = tcg_temp_new_i64();
6815: tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
6816: tcg_gen_shri_i64(tmp, t, 32);
6817: tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
6818: tcg_temp_free_i64(tmp);
1.1.1.5 root 6819: #endif
1.1.1.6 root 6820: }
1.1.1.5 root 6821:
1.1.1.12 root 6822: #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
1.1.1.7 root 6823: static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
1.1.1.5 root 6824: { \
6825: if (Rc(ctx->opcode)) \
6826: gen_##name1(ctx); \
6827: else \
6828: gen_##name0(ctx); \
6829: }
6830:
6831: /* Handler for undefined SPE opcodes */
1.1.1.8 root 6832: static inline void gen_speundef(DisasContext *ctx)
1.1 root 6833: {
1.1.1.6 root 6834: gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
1.1.1.5 root 6835: }
6836:
1.1.1.6 root 6837: /* SPE logic */
6838: #if defined(TARGET_PPC64)
6839: #define GEN_SPEOP_LOGIC2(name, tcg_op) \
1.1.1.8 root 6840: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6841: { \
6842: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 6843: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 6844: return; \
6845: } \
6846: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6847: cpu_gpr[rB(ctx->opcode)]); \
6848: }
6849: #else
6850: #define GEN_SPEOP_LOGIC2(name, tcg_op) \
1.1.1.8 root 6851: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 6852: { \
6853: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 6854: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 6855: return; \
6856: } \
6857: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6858: cpu_gpr[rB(ctx->opcode)]); \
6859: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6860: cpu_gprh[rB(ctx->opcode)]); \
1.1.1.5 root 6861: }
1.1.1.6 root 6862: #endif
1.1.1.5 root 6863:
1.1.1.6 root 6864: GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6865: GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6866: GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6867: GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6868: GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6869: GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6870: GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6871: GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
1.1.1.5 root 6872:
1.1.1.6 root 6873: /* SPE logic immediate */
6874: #if defined(TARGET_PPC64)
6875: #define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
1.1.1.8 root 6876: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6877: { \
6878: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 6879: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 6880: return; \
6881: } \
1.1.1.6 root 6882: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6883: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6884: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6885: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6886: tcg_opi(t0, t0, rB(ctx->opcode)); \
6887: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6888: tcg_gen_trunc_i64_i32(t1, t2); \
6889: tcg_temp_free_i64(t2); \
6890: tcg_opi(t1, t1, rB(ctx->opcode)); \
6891: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6892: tcg_temp_free_i32(t0); \
6893: tcg_temp_free_i32(t1); \
1.1.1.5 root 6894: }
1.1.1.6 root 6895: #else
6896: #define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
1.1.1.8 root 6897: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6898: { \
6899: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 6900: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 6901: return; \
6902: } \
1.1.1.6 root 6903: tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6904: rB(ctx->opcode)); \
6905: tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6906: rB(ctx->opcode)); \
1.1.1.5 root 6907: }
1.1.1.6 root 6908: #endif
6909: GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6910: GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6911: GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6912: GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
1.1.1.5 root 6913:
1.1.1.6 root 6914: /* SPE arithmetic */
6915: #if defined(TARGET_PPC64)
6916: #define GEN_SPEOP_ARITH1(name, tcg_op) \
1.1.1.8 root 6917: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6918: { \
6919: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 6920: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 6921: return; \
6922: } \
1.1.1.6 root 6923: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6924: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6925: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
6926: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6927: tcg_op(t0, t0); \
6928: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6929: tcg_gen_trunc_i64_i32(t1, t2); \
6930: tcg_temp_free_i64(t2); \
6931: tcg_op(t1, t1); \
6932: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6933: tcg_temp_free_i32(t0); \
6934: tcg_temp_free_i32(t1); \
1.1.1.5 root 6935: }
1.1.1.6 root 6936: #else
6937: #define GEN_SPEOP_ARITH1(name, tcg_op) \
1.1.1.8 root 6938: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6939: { \
6940: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 6941: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 6942: return; \
6943: } \
1.1.1.6 root 6944: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
6945: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
1.1.1.5 root 6946: }
1.1.1.6 root 6947: #endif
1.1.1.5 root 6948:
1.1.1.8 root 6949: static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
1.1.1.6 root 6950: {
6951: int l1 = gen_new_label();
6952: int l2 = gen_new_label();
1.1.1.5 root 6953:
1.1.1.6 root 6954: tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6955: tcg_gen_neg_i32(ret, arg1);
6956: tcg_gen_br(l2);
6957: gen_set_label(l1);
6958: tcg_gen_mov_i32(ret, arg1);
6959: gen_set_label(l2);
6960: }
6961: GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6962: GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6963: GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6964: GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
1.1.1.8 root 6965: static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
1.1.1.6 root 6966: {
6967: tcg_gen_addi_i32(ret, arg1, 0x8000);
6968: tcg_gen_ext16u_i32(ret, ret);
6969: }
6970: GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
6971: GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6972: GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
1.1.1.5 root 6973:
1.1.1.6 root 6974: #if defined(TARGET_PPC64)
6975: #define GEN_SPEOP_ARITH2(name, tcg_op) \
1.1.1.8 root 6976: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 6977: { \
6978: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 6979: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 6980: return; \
6981: } \
1.1.1.6 root 6982: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6983: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6984: TCGv_i32 t2 = tcg_temp_local_new_i32(); \
6985: TCGv_i64 t3 = tcg_temp_local_new_i64(); \
6986: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6987: tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
6988: tcg_op(t0, t0, t2); \
6989: tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
6990: tcg_gen_trunc_i64_i32(t1, t3); \
6991: tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
6992: tcg_gen_trunc_i64_i32(t2, t3); \
6993: tcg_temp_free_i64(t3); \
6994: tcg_op(t1, t1, t2); \
6995: tcg_temp_free_i32(t2); \
6996: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6997: tcg_temp_free_i32(t0); \
6998: tcg_temp_free_i32(t1); \
1.1.1.5 root 6999: }
1.1.1.6 root 7000: #else
7001: #define GEN_SPEOP_ARITH2(name, tcg_op) \
1.1.1.8 root 7002: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 7003: { \
7004: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 7005: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 7006: return; \
7007: } \
1.1.1.6 root 7008: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7009: cpu_gpr[rB(ctx->opcode)]); \
7010: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
7011: cpu_gprh[rB(ctx->opcode)]); \
7012: }
7013: #endif
7014:
1.1.1.8 root 7015: static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 7016: {
7017: TCGv_i32 t0;
7018: int l1, l2;
7019:
7020: l1 = gen_new_label();
7021: l2 = gen_new_label();
7022: t0 = tcg_temp_local_new_i32();
7023: /* No error here: 6 bits are used */
7024: tcg_gen_andi_i32(t0, arg2, 0x3F);
7025: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
7026: tcg_gen_shr_i32(ret, arg1, t0);
7027: tcg_gen_br(l2);
7028: gen_set_label(l1);
7029: tcg_gen_movi_i32(ret, 0);
1.1.1.9 root 7030: gen_set_label(l2);
1.1.1.6 root 7031: tcg_temp_free_i32(t0);
7032: }
7033: GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
1.1.1.8 root 7034: static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 7035: {
7036: TCGv_i32 t0;
7037: int l1, l2;
7038:
7039: l1 = gen_new_label();
7040: l2 = gen_new_label();
7041: t0 = tcg_temp_local_new_i32();
7042: /* No error here: 6 bits are used */
7043: tcg_gen_andi_i32(t0, arg2, 0x3F);
7044: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
7045: tcg_gen_sar_i32(ret, arg1, t0);
7046: tcg_gen_br(l2);
7047: gen_set_label(l1);
7048: tcg_gen_movi_i32(ret, 0);
1.1.1.9 root 7049: gen_set_label(l2);
1.1.1.6 root 7050: tcg_temp_free_i32(t0);
7051: }
7052: GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
1.1.1.8 root 7053: static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 7054: {
7055: TCGv_i32 t0;
7056: int l1, l2;
7057:
7058: l1 = gen_new_label();
7059: l2 = gen_new_label();
7060: t0 = tcg_temp_local_new_i32();
7061: /* No error here: 6 bits are used */
7062: tcg_gen_andi_i32(t0, arg2, 0x3F);
7063: tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
7064: tcg_gen_shl_i32(ret, arg1, t0);
7065: tcg_gen_br(l2);
7066: gen_set_label(l1);
7067: tcg_gen_movi_i32(ret, 0);
1.1.1.9 root 7068: gen_set_label(l2);
1.1.1.6 root 7069: tcg_temp_free_i32(t0);
7070: }
7071: GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
1.1.1.8 root 7072: static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 7073: {
7074: TCGv_i32 t0 = tcg_temp_new_i32();
7075: tcg_gen_andi_i32(t0, arg2, 0x1F);
7076: tcg_gen_rotl_i32(ret, arg1, t0);
7077: tcg_temp_free_i32(t0);
7078: }
7079: GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
1.1.1.8 root 7080: static inline void gen_evmergehi(DisasContext *ctx)
1.1.1.6 root 7081: {
7082: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7083: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 7084: return;
7085: }
7086: #if defined(TARGET_PPC64)
7087: TCGv t0 = tcg_temp_new();
7088: TCGv t1 = tcg_temp_new();
7089: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
7090: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
7091: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7092: tcg_temp_free(t0);
7093: tcg_temp_free(t1);
7094: #else
7095: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7096: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7097: #endif
7098: }
7099: GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
1.1.1.8 root 7100: static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1.1.1.6 root 7101: {
7102: tcg_gen_sub_i32(ret, arg2, arg1);
1.1.1.5 root 7103: }
1.1.1.6 root 7104: GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
1.1.1.5 root 7105:
1.1.1.6 root 7106: /* SPE arithmetic immediate */
7107: #if defined(TARGET_PPC64)
7108: #define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
1.1.1.8 root 7109: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 7110: { \
7111: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 7112: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 7113: return; \
7114: } \
1.1.1.6 root 7115: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7116: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7117: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
7118: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7119: tcg_op(t0, t0, rA(ctx->opcode)); \
7120: tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
7121: tcg_gen_trunc_i64_i32(t1, t2); \
7122: tcg_temp_free_i64(t2); \
7123: tcg_op(t1, t1, rA(ctx->opcode)); \
7124: tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
7125: tcg_temp_free_i32(t0); \
7126: tcg_temp_free_i32(t1); \
1.1 root 7127: }
1.1.1.6 root 7128: #else
7129: #define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
1.1.1.8 root 7130: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 7131: { \
7132: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 7133: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 7134: return; \
7135: } \
1.1.1.6 root 7136: tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
7137: rA(ctx->opcode)); \
7138: tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
7139: rA(ctx->opcode)); \
1.1.1.5 root 7140: }
1.1.1.6 root 7141: #endif
7142: GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
7143: GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
1.1.1.5 root 7144:
1.1.1.6 root 7145: /* SPE comparison */
7146: #if defined(TARGET_PPC64)
7147: #define GEN_SPEOP_COMP(name, tcg_cond) \
1.1.1.8 root 7148: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 7149: { \
7150: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 7151: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 7152: return; \
7153: } \
7154: int l1 = gen_new_label(); \
7155: int l2 = gen_new_label(); \
7156: int l3 = gen_new_label(); \
7157: int l4 = gen_new_label(); \
7158: TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7159: TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7160: TCGv_i64 t2 = tcg_temp_local_new_i64(); \
7161: tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7162: tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7163: tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
7164: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
7165: tcg_gen_br(l2); \
7166: gen_set_label(l1); \
7167: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
7168: CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
7169: gen_set_label(l2); \
7170: tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
7171: tcg_gen_trunc_i64_i32(t0, t2); \
7172: tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
7173: tcg_gen_trunc_i64_i32(t1, t2); \
7174: tcg_temp_free_i64(t2); \
7175: tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
7176: tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7177: ~(CRF_CH | CRF_CH_AND_CL)); \
7178: tcg_gen_br(l4); \
7179: gen_set_label(l3); \
7180: tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7181: CRF_CH | CRF_CH_OR_CL); \
7182: gen_set_label(l4); \
7183: tcg_temp_free_i32(t0); \
7184: tcg_temp_free_i32(t1); \
7185: }
7186: #else
7187: #define GEN_SPEOP_COMP(name, tcg_cond) \
1.1.1.8 root 7188: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 7189: { \
7190: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 7191: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.5 root 7192: return; \
7193: } \
1.1.1.6 root 7194: int l1 = gen_new_label(); \
7195: int l2 = gen_new_label(); \
7196: int l3 = gen_new_label(); \
7197: int l4 = gen_new_label(); \
7198: \
7199: tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
7200: cpu_gpr[rB(ctx->opcode)], l1); \
7201: tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
7202: tcg_gen_br(l2); \
7203: gen_set_label(l1); \
7204: tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
7205: CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
7206: gen_set_label(l2); \
7207: tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
7208: cpu_gprh[rB(ctx->opcode)], l3); \
7209: tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7210: ~(CRF_CH | CRF_CH_AND_CL)); \
7211: tcg_gen_br(l4); \
7212: gen_set_label(l3); \
7213: tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7214: CRF_CH | CRF_CH_OR_CL); \
7215: gen_set_label(l4); \
7216: }
7217: #endif
7218: GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
7219: GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
7220: GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
7221: GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
7222: GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
1.1.1.5 root 7223:
1.1.1.6 root 7224: /* SPE misc */
1.1.1.8 root 7225: static inline void gen_brinc(DisasContext *ctx)
1.1.1.6 root 7226: {
7227: /* Note: brinc is usable even if SPE is disabled */
7228: gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
7229: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7230: }
1.1.1.8 root 7231: static inline void gen_evmergelo(DisasContext *ctx)
1.1.1.6 root 7232: {
7233: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7234: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 7235: return;
7236: }
7237: #if defined(TARGET_PPC64)
7238: TCGv t0 = tcg_temp_new();
7239: TCGv t1 = tcg_temp_new();
1.1.1.11 root 7240: tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
1.1.1.6 root 7241: tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7242: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7243: tcg_temp_free(t0);
7244: tcg_temp_free(t1);
7245: #else
7246: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1.1.1.7 root 7247: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1.1.1.6 root 7248: #endif
7249: }
1.1.1.8 root 7250: static inline void gen_evmergehilo(DisasContext *ctx)
1.1.1.6 root 7251: {
7252: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7253: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 7254: return;
7255: }
7256: #if defined(TARGET_PPC64)
7257: TCGv t0 = tcg_temp_new();
7258: TCGv t1 = tcg_temp_new();
1.1.1.11 root 7259: tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
1.1.1.6 root 7260: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
7261: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7262: tcg_temp_free(t0);
7263: tcg_temp_free(t1);
7264: #else
7265: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7266: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7267: #endif
7268: }
1.1.1.8 root 7269: static inline void gen_evmergelohi(DisasContext *ctx)
1.1.1.6 root 7270: {
7271: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7272: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 7273: return;
7274: }
7275: #if defined(TARGET_PPC64)
7276: TCGv t0 = tcg_temp_new();
7277: TCGv t1 = tcg_temp_new();
7278: tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
7279: tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7280: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7281: tcg_temp_free(t0);
7282: tcg_temp_free(t1);
7283: #else
1.1.1.7 root 7284: if (rD(ctx->opcode) == rA(ctx->opcode)) {
7285: TCGv_i32 tmp = tcg_temp_new_i32();
7286: tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
7287: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7288: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
7289: tcg_temp_free_i32(tmp);
7290: } else {
7291: tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7292: tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7293: }
1.1.1.6 root 7294: #endif
7295: }
1.1.1.8 root 7296: static inline void gen_evsplati(DisasContext *ctx)
1.1.1.5 root 7297: {
1.1.1.9 root 7298: uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
1.1.1.5 root 7299:
1.1.1.6 root 7300: #if defined(TARGET_PPC64)
7301: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7302: #else
7303: tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7304: tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7305: #endif
1.1.1.5 root 7306: }
1.1.1.8 root 7307: static inline void gen_evsplatfi(DisasContext *ctx)
1.1.1.5 root 7308: {
1.1.1.9 root 7309: uint64_t imm = rA(ctx->opcode) << 27;
1.1.1.5 root 7310:
1.1.1.6 root 7311: #if defined(TARGET_PPC64)
7312: tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7313: #else
7314: tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7315: tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7316: #endif
1.1.1.5 root 7317: }
7318:
1.1.1.8 root 7319: static inline void gen_evsel(DisasContext *ctx)
1.1.1.6 root 7320: {
7321: int l1 = gen_new_label();
7322: int l2 = gen_new_label();
7323: int l3 = gen_new_label();
7324: int l4 = gen_new_label();
7325: TCGv_i32 t0 = tcg_temp_local_new_i32();
7326: #if defined(TARGET_PPC64)
7327: TCGv t1 = tcg_temp_local_new();
7328: TCGv t2 = tcg_temp_local_new();
7329: #endif
7330: tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
7331: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
7332: #if defined(TARGET_PPC64)
7333: tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7334: #else
7335: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7336: #endif
7337: tcg_gen_br(l2);
7338: gen_set_label(l1);
7339: #if defined(TARGET_PPC64)
7340: tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7341: #else
7342: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7343: #endif
7344: gen_set_label(l2);
7345: tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
7346: tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
7347: #if defined(TARGET_PPC64)
1.1.1.11 root 7348: tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
1.1.1.6 root 7349: #else
7350: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7351: #endif
7352: tcg_gen_br(l4);
7353: gen_set_label(l3);
7354: #if defined(TARGET_PPC64)
1.1.1.11 root 7355: tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
1.1.1.6 root 7356: #else
7357: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7358: #endif
7359: gen_set_label(l4);
7360: tcg_temp_free_i32(t0);
7361: #if defined(TARGET_PPC64)
7362: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
7363: tcg_temp_free(t1);
7364: tcg_temp_free(t2);
7365: #endif
7366: }
1.1.1.7 root 7367:
7368: static void gen_evsel0(DisasContext *ctx)
1.1.1.6 root 7369: {
7370: gen_evsel(ctx);
7371: }
1.1.1.7 root 7372:
7373: static void gen_evsel1(DisasContext *ctx)
1.1.1.6 root 7374: {
7375: gen_evsel(ctx);
7376: }
1.1.1.7 root 7377:
7378: static void gen_evsel2(DisasContext *ctx)
1.1.1.6 root 7379: {
7380: gen_evsel(ctx);
7381: }
1.1.1.7 root 7382:
7383: static void gen_evsel3(DisasContext *ctx)
1.1.1.6 root 7384: {
7385: gen_evsel(ctx);
7386: }
1.1.1.5 root 7387:
1.1.1.11 root 7388: /* Multiply */
7389:
7390: static inline void gen_evmwumi(DisasContext *ctx)
7391: {
7392: TCGv_i64 t0, t1;
7393:
7394: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7395: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.11 root 7396: return;
7397: }
7398:
7399: t0 = tcg_temp_new_i64();
7400: t1 = tcg_temp_new_i64();
7401:
7402: /* t0 := rA; t1 := rB */
7403: #if defined(TARGET_PPC64)
7404: tcg_gen_ext32u_tl(t0, cpu_gpr[rA(ctx->opcode)]);
7405: tcg_gen_ext32u_tl(t1, cpu_gpr[rB(ctx->opcode)]);
7406: #else
7407: tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
7408: tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
7409: #endif
7410:
7411: tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
7412:
7413: gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
7414:
7415: tcg_temp_free_i64(t0);
7416: tcg_temp_free_i64(t1);
7417: }
7418:
7419: static inline void gen_evmwumia(DisasContext *ctx)
7420: {
7421: TCGv_i64 tmp;
7422:
7423: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7424: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.11 root 7425: return;
7426: }
7427:
7428: gen_evmwumi(ctx); /* rD := rA * rB */
7429:
7430: tmp = tcg_temp_new_i64();
7431:
7432: /* acc := rD */
7433: gen_load_gpr64(tmp, rD(ctx->opcode));
1.1.1.13! root 7434: tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 7435: tcg_temp_free_i64(tmp);
7436: }
7437:
7438: static inline void gen_evmwumiaa(DisasContext *ctx)
7439: {
7440: TCGv_i64 acc;
7441: TCGv_i64 tmp;
7442:
7443: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7444: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.11 root 7445: return;
7446: }
7447:
7448: gen_evmwumi(ctx); /* rD := rA * rB */
7449:
7450: acc = tcg_temp_new_i64();
7451: tmp = tcg_temp_new_i64();
7452:
7453: /* tmp := rD */
7454: gen_load_gpr64(tmp, rD(ctx->opcode));
7455:
7456: /* Load acc */
1.1.1.13! root 7457: tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 7458:
7459: /* acc := tmp + acc */
7460: tcg_gen_add_i64(acc, acc, tmp);
7461:
7462: /* Store acc */
1.1.1.13! root 7463: tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 7464:
7465: /* rD := acc */
7466: gen_store_gpr64(rD(ctx->opcode), acc);
7467:
7468: tcg_temp_free_i64(acc);
7469: tcg_temp_free_i64(tmp);
7470: }
7471:
7472: static inline void gen_evmwsmi(DisasContext *ctx)
7473: {
7474: TCGv_i64 t0, t1;
7475:
7476: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 7477: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.11 root 7478: return;
7479: }
7480:
7481: t0 = tcg_temp_new_i64();
7482: t1 = tcg_temp_new_i64();
7483:
7484: /* t0 := rA; t1 := rB */
7485: #if defined(TARGET_PPC64)
7486: tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
7487: tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
7488: #else
7489: tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
7490: tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
7491: #endif
7492:
7493: tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
7494:
7495: gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
7496:
7497: tcg_temp_free_i64(t0);
7498: tcg_temp_free_i64(t1);
7499: }
7500:
7501: static inline void gen_evmwsmia(DisasContext *ctx)
7502: {
7503: TCGv_i64 tmp;
7504:
7505: gen_evmwsmi(ctx); /* rD := rA * rB */
7506:
7507: tmp = tcg_temp_new_i64();
7508:
7509: /* acc := rD */
7510: gen_load_gpr64(tmp, rD(ctx->opcode));
1.1.1.13! root 7511: tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 7512:
7513: tcg_temp_free_i64(tmp);
7514: }
7515:
7516: static inline void gen_evmwsmiaa(DisasContext *ctx)
7517: {
7518: TCGv_i64 acc = tcg_temp_new_i64();
7519: TCGv_i64 tmp = tcg_temp_new_i64();
7520:
7521: gen_evmwsmi(ctx); /* rD := rA * rB */
7522:
7523: acc = tcg_temp_new_i64();
7524: tmp = tcg_temp_new_i64();
7525:
7526: /* tmp := rD */
7527: gen_load_gpr64(tmp, rD(ctx->opcode));
7528:
7529: /* Load acc */
1.1.1.13! root 7530: tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 7531:
7532: /* acc := tmp + acc */
7533: tcg_gen_add_i64(acc, acc, tmp);
7534:
7535: /* Store acc */
1.1.1.13! root 7536: tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
1.1.1.11 root 7537:
7538: /* rD := acc */
7539: gen_store_gpr64(rD(ctx->opcode), acc);
7540:
7541: tcg_temp_free_i64(acc);
7542: tcg_temp_free_i64(tmp);
7543: }
7544:
1.1.1.12 root 7545: GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
7546: GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
7547: GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
7548: GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
7549: GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
7550: GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
7551: GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
7552: GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
7553: GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
7554: GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
7555: GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
7556: GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
7557: GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
7558: GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
7559: GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
7560: GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
7561: GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
7562: GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
7563: GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
7564: GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
7565: GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
7566: GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
7567: GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
7568: GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
7569: GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
7570: GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
7571: GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
7572: GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
7573: GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
1.1.1.5 root 7574:
1.1.1.6 root 7575: /* SPE load and stores */
1.1.1.8 root 7576: static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
1.1 root 7577: {
1.1.1.6 root 7578: target_ulong uimm = rB(ctx->opcode);
7579:
7580: if (rA(ctx->opcode) == 0) {
7581: tcg_gen_movi_tl(EA, uimm << sh);
7582: } else {
7583: tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
7584: #if defined(TARGET_PPC64)
7585: if (!ctx->sf_mode) {
7586: tcg_gen_ext32u_tl(EA, EA);
7587: }
7588: #endif
1.1 root 7589: }
1.1.1.5 root 7590: }
7591:
1.1.1.8 root 7592: static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7593: {
1.1.1.6 root 7594: #if defined(TARGET_PPC64)
7595: gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7596: #else
7597: TCGv_i64 t0 = tcg_temp_new_i64();
7598: gen_qemu_ld64(ctx, t0, addr);
7599: tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
7600: tcg_gen_shri_i64(t0, t0, 32);
7601: tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
7602: tcg_temp_free_i64(t0);
7603: #endif
1.1.1.5 root 7604: }
1.1.1.6 root 7605:
1.1.1.8 root 7606: static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7607: {
1.1.1.6 root 7608: #if defined(TARGET_PPC64)
7609: TCGv t0 = tcg_temp_new();
7610: gen_qemu_ld32u(ctx, t0, addr);
7611: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7612: gen_addr_add(ctx, addr, addr, 4);
7613: gen_qemu_ld32u(ctx, t0, addr);
7614: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7615: tcg_temp_free(t0);
7616: #else
7617: gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7618: gen_addr_add(ctx, addr, addr, 4);
7619: gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7620: #endif
1.1.1.5 root 7621: }
1.1.1.6 root 7622:
1.1.1.8 root 7623: static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7624: {
1.1.1.6 root 7625: TCGv t0 = tcg_temp_new();
7626: #if defined(TARGET_PPC64)
7627: gen_qemu_ld16u(ctx, t0, addr);
7628: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7629: gen_addr_add(ctx, addr, addr, 2);
7630: gen_qemu_ld16u(ctx, t0, addr);
7631: tcg_gen_shli_tl(t0, t0, 32);
7632: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7633: gen_addr_add(ctx, addr, addr, 2);
7634: gen_qemu_ld16u(ctx, t0, addr);
7635: tcg_gen_shli_tl(t0, t0, 16);
7636: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7637: gen_addr_add(ctx, addr, addr, 2);
7638: gen_qemu_ld16u(ctx, t0, addr);
7639: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7640: #else
7641: gen_qemu_ld16u(ctx, t0, addr);
7642: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7643: gen_addr_add(ctx, addr, addr, 2);
7644: gen_qemu_ld16u(ctx, t0, addr);
7645: tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7646: gen_addr_add(ctx, addr, addr, 2);
7647: gen_qemu_ld16u(ctx, t0, addr);
7648: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7649: gen_addr_add(ctx, addr, addr, 2);
7650: gen_qemu_ld16u(ctx, t0, addr);
7651: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7652: #endif
7653: tcg_temp_free(t0);
1.1.1.5 root 7654: }
1.1.1.6 root 7655:
1.1.1.8 root 7656: static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
1.1.1.5 root 7657: {
1.1.1.6 root 7658: TCGv t0 = tcg_temp_new();
7659: gen_qemu_ld16u(ctx, t0, addr);
7660: #if defined(TARGET_PPC64)
7661: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7662: tcg_gen_shli_tl(t0, t0, 16);
7663: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7664: #else
7665: tcg_gen_shli_tl(t0, t0, 16);
7666: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7667: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7668: #endif
7669: tcg_temp_free(t0);
1.1.1.5 root 7670: }
7671:
1.1.1.8 root 7672: static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7673: {
7674: TCGv t0 = tcg_temp_new();
7675: gen_qemu_ld16u(ctx, t0, addr);
1.1.1.5 root 7676: #if defined(TARGET_PPC64)
1.1.1.6 root 7677: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7678: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7679: #else
7680: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7681: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7682: #endif
7683: tcg_temp_free(t0);
7684: }
7685:
1.1.1.8 root 7686: static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7687: {
7688: TCGv t0 = tcg_temp_new();
7689: gen_qemu_ld16s(ctx, t0, addr);
7690: #if defined(TARGET_PPC64)
7691: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7692: tcg_gen_ext32u_tl(t0, t0);
7693: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7694: #else
7695: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7696: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7697: #endif
7698: tcg_temp_free(t0);
7699: }
7700:
1.1.1.8 root 7701: static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7702: {
7703: TCGv t0 = tcg_temp_new();
7704: #if defined(TARGET_PPC64)
7705: gen_qemu_ld16u(ctx, t0, addr);
7706: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7707: gen_addr_add(ctx, addr, addr, 2);
7708: gen_qemu_ld16u(ctx, t0, addr);
7709: tcg_gen_shli_tl(t0, t0, 16);
7710: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7711: #else
7712: gen_qemu_ld16u(ctx, t0, addr);
7713: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7714: gen_addr_add(ctx, addr, addr, 2);
7715: gen_qemu_ld16u(ctx, t0, addr);
7716: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7717: #endif
7718: tcg_temp_free(t0);
7719: }
7720:
1.1.1.8 root 7721: static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7722: {
7723: #if defined(TARGET_PPC64)
7724: TCGv t0 = tcg_temp_new();
7725: gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7726: gen_addr_add(ctx, addr, addr, 2);
7727: gen_qemu_ld16u(ctx, t0, addr);
7728: tcg_gen_shli_tl(t0, t0, 32);
7729: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7730: tcg_temp_free(t0);
7731: #else
7732: gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7733: gen_addr_add(ctx, addr, addr, 2);
7734: gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7735: #endif
7736: }
7737:
1.1.1.8 root 7738: static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7739: {
7740: #if defined(TARGET_PPC64)
7741: TCGv t0 = tcg_temp_new();
7742: gen_qemu_ld16s(ctx, t0, addr);
7743: tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
7744: gen_addr_add(ctx, addr, addr, 2);
7745: gen_qemu_ld16s(ctx, t0, addr);
7746: tcg_gen_shli_tl(t0, t0, 32);
7747: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7748: tcg_temp_free(t0);
7749: #else
7750: gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7751: gen_addr_add(ctx, addr, addr, 2);
7752: gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7753: #endif
7754: }
7755:
1.1.1.8 root 7756: static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7757: {
7758: TCGv t0 = tcg_temp_new();
7759: gen_qemu_ld32u(ctx, t0, addr);
7760: #if defined(TARGET_PPC64)
7761: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7762: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7763: #else
7764: tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7765: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7766: #endif
7767: tcg_temp_free(t0);
7768: }
7769:
1.1.1.8 root 7770: static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7771: {
7772: TCGv t0 = tcg_temp_new();
7773: #if defined(TARGET_PPC64)
7774: gen_qemu_ld16u(ctx, t0, addr);
7775: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7776: tcg_gen_shli_tl(t0, t0, 32);
7777: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7778: gen_addr_add(ctx, addr, addr, 2);
7779: gen_qemu_ld16u(ctx, t0, addr);
7780: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7781: tcg_gen_shli_tl(t0, t0, 16);
7782: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7783: #else
7784: gen_qemu_ld16u(ctx, t0, addr);
7785: tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7786: tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7787: gen_addr_add(ctx, addr, addr, 2);
7788: gen_qemu_ld16u(ctx, t0, addr);
7789: tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7790: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7791: #endif
7792: tcg_temp_free(t0);
7793: }
7794:
1.1.1.8 root 7795: static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7796: {
7797: #if defined(TARGET_PPC64)
7798: gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7799: #else
7800: TCGv_i64 t0 = tcg_temp_new_i64();
7801: tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
7802: gen_qemu_st64(ctx, t0, addr);
7803: tcg_temp_free_i64(t0);
7804: #endif
7805: }
7806:
1.1.1.8 root 7807: static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7808: {
7809: #if defined(TARGET_PPC64)
7810: TCGv t0 = tcg_temp_new();
7811: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7812: gen_qemu_st32(ctx, t0, addr);
7813: tcg_temp_free(t0);
7814: #else
7815: gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7816: #endif
7817: gen_addr_add(ctx, addr, addr, 4);
7818: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
1.1.1.5 root 7819: }
1.1.1.6 root 7820:
1.1.1.8 root 7821: static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7822: {
7823: TCGv t0 = tcg_temp_new();
7824: #if defined(TARGET_PPC64)
7825: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
1.1.1.5 root 7826: #else
1.1.1.6 root 7827: tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7828: #endif
7829: gen_qemu_st16(ctx, t0, addr);
7830: gen_addr_add(ctx, addr, addr, 2);
7831: #if defined(TARGET_PPC64)
7832: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7833: gen_qemu_st16(ctx, t0, addr);
7834: #else
7835: gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7836: #endif
7837: gen_addr_add(ctx, addr, addr, 2);
7838: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7839: gen_qemu_st16(ctx, t0, addr);
7840: tcg_temp_free(t0);
7841: gen_addr_add(ctx, addr, addr, 2);
7842: gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7843: }
7844:
1.1.1.8 root 7845: static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7846: {
7847: TCGv t0 = tcg_temp_new();
7848: #if defined(TARGET_PPC64)
7849: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7850: #else
7851: tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7852: #endif
7853: gen_qemu_st16(ctx, t0, addr);
7854: gen_addr_add(ctx, addr, addr, 2);
7855: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7856: gen_qemu_st16(ctx, t0, addr);
7857: tcg_temp_free(t0);
7858: }
7859:
1.1.1.8 root 7860: static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7861: {
7862: #if defined(TARGET_PPC64)
7863: TCGv t0 = tcg_temp_new();
7864: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7865: gen_qemu_st16(ctx, t0, addr);
7866: tcg_temp_free(t0);
7867: #else
7868: gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7869: #endif
7870: gen_addr_add(ctx, addr, addr, 2);
7871: gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7872: }
7873:
1.1.1.8 root 7874: static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7875: {
7876: #if defined(TARGET_PPC64)
7877: TCGv t0 = tcg_temp_new();
7878: tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7879: gen_qemu_st32(ctx, t0, addr);
7880: tcg_temp_free(t0);
7881: #else
7882: gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7883: #endif
7884: }
7885:
1.1.1.8 root 7886: static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
1.1.1.6 root 7887: {
7888: gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7889: }
7890:
7891: #define GEN_SPEOP_LDST(name, opc2, sh) \
1.1.1.7 root 7892: static void glue(gen_, name)(DisasContext *ctx) \
1.1.1.6 root 7893: { \
7894: TCGv t0; \
7895: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 7896: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 7897: return; \
7898: } \
7899: gen_set_access_type(ctx, ACCESS_INT); \
7900: t0 = tcg_temp_new(); \
7901: if (Rc(ctx->opcode)) { \
7902: gen_addr_spe_imm_index(ctx, t0, sh); \
7903: } else { \
7904: gen_addr_reg_index(ctx, t0); \
7905: } \
7906: gen_op_##name(ctx, t0); \
7907: tcg_temp_free(t0); \
7908: }
7909:
7910: GEN_SPEOP_LDST(evldd, 0x00, 3);
7911: GEN_SPEOP_LDST(evldw, 0x01, 3);
7912: GEN_SPEOP_LDST(evldh, 0x02, 3);
7913: GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7914: GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7915: GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7916: GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7917: GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7918: GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7919: GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7920: GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7921:
7922: GEN_SPEOP_LDST(evstdd, 0x10, 3);
7923: GEN_SPEOP_LDST(evstdw, 0x11, 3);
7924: GEN_SPEOP_LDST(evstdh, 0x12, 3);
7925: GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7926: GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7927: GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7928: GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
1.1.1.5 root 7929:
7930: /* Multiply and add - TODO */
7931: #if 0
1.1.1.12 root 7932: GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
7933: GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7934: GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
7935: GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7936: GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
7937: GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7938: GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7939: GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7940: GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
7941: GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7942: GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
7943: GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7944:
7945: GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7946: GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
7947: GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE);
7948: GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7949: GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7950: GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7951: GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7952: GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
7953: GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE);
7954: GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7955: GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7956: GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7957:
7958: GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
7959: GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
7960: GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
7961: GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
7962: GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE);
7963:
7964: GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE);
7965: GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7966: GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE);
7967: GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7968: GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE);
7969: GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7970: GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE);
7971: GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7972: GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE);
7973: GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7974: GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE);
7975: GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7976:
7977: GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE);
7978: GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE);
7979: GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7980: GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7981:
7982: GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE);
7983: GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7984: GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE);
7985: GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7986: GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE);
7987: GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7988: GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE);
7989: GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7990: GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE);
7991: GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7992: GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE);
7993: GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7994:
7995: GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE);
7996: GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE);
7997: GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
7998: GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE);
7999: GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
1.1.1.5 root 8000: #endif
8001:
8002: /*** SPE floating-point extension ***/
1.1.1.6 root 8003: #if defined(TARGET_PPC64)
8004: #define GEN_SPEFPUOP_CONV_32_32(name) \
1.1.1.8 root 8005: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8006: { \
8007: TCGv_i32 t0; \
8008: TCGv t1; \
8009: t0 = tcg_temp_new_i32(); \
8010: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
8011: gen_helper_##name(t0, t0); \
8012: t1 = tcg_temp_new(); \
8013: tcg_gen_extu_i32_tl(t1, t0); \
8014: tcg_temp_free_i32(t0); \
8015: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
8016: 0xFFFFFFFF00000000ULL); \
8017: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
8018: tcg_temp_free(t1); \
8019: }
8020: #define GEN_SPEFPUOP_CONV_32_64(name) \
1.1.1.8 root 8021: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8022: { \
8023: TCGv_i32 t0; \
8024: TCGv t1; \
8025: t0 = tcg_temp_new_i32(); \
8026: gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
8027: t1 = tcg_temp_new(); \
8028: tcg_gen_extu_i32_tl(t1, t0); \
8029: tcg_temp_free_i32(t0); \
8030: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
8031: 0xFFFFFFFF00000000ULL); \
8032: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
8033: tcg_temp_free(t1); \
8034: }
8035: #define GEN_SPEFPUOP_CONV_64_32(name) \
1.1.1.8 root 8036: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8037: { \
8038: TCGv_i32 t0 = tcg_temp_new_i32(); \
8039: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
8040: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
8041: tcg_temp_free_i32(t0); \
8042: }
8043: #define GEN_SPEFPUOP_CONV_64_64(name) \
1.1.1.8 root 8044: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8045: { \
8046: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8047: }
8048: #define GEN_SPEFPUOP_ARITH2_32_32(name) \
1.1.1.8 root 8049: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8050: { \
8051: TCGv_i32 t0, t1; \
8052: TCGv_i64 t2; \
8053: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8054: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8055: return; \
8056: } \
8057: t0 = tcg_temp_new_i32(); \
8058: t1 = tcg_temp_new_i32(); \
8059: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
8060: tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
8061: gen_helper_##name(t0, t0, t1); \
8062: tcg_temp_free_i32(t1); \
8063: t2 = tcg_temp_new(); \
8064: tcg_gen_extu_i32_tl(t2, t0); \
8065: tcg_temp_free_i32(t0); \
8066: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
8067: 0xFFFFFFFF00000000ULL); \
8068: tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
8069: tcg_temp_free(t2); \
8070: }
8071: #define GEN_SPEFPUOP_ARITH2_64_64(name) \
1.1.1.8 root 8072: static inline void gen_##name(DisasContext *ctx) \
1.1.1.5 root 8073: { \
1.1.1.6 root 8074: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8075: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8076: return; \
8077: } \
8078: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
8079: cpu_gpr[rB(ctx->opcode)]); \
1.1 root 8080: }
1.1.1.6 root 8081: #define GEN_SPEFPUOP_COMP_32(name) \
1.1.1.8 root 8082: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8083: { \
8084: TCGv_i32 t0, t1; \
8085: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8086: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8087: return; \
8088: } \
8089: t0 = tcg_temp_new_i32(); \
8090: t1 = tcg_temp_new_i32(); \
8091: tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
8092: tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
8093: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
8094: tcg_temp_free_i32(t0); \
8095: tcg_temp_free_i32(t1); \
8096: }
8097: #define GEN_SPEFPUOP_COMP_64(name) \
1.1.1.8 root 8098: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8099: { \
8100: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8101: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8102: return; \
8103: } \
8104: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8105: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8106: }
8107: #else
8108: #define GEN_SPEFPUOP_CONV_32_32(name) \
1.1.1.8 root 8109: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8110: { \
8111: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8112: }
8113: #define GEN_SPEFPUOP_CONV_32_64(name) \
1.1.1.8 root 8114: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8115: { \
8116: TCGv_i64 t0 = tcg_temp_new_i64(); \
8117: gen_load_gpr64(t0, rB(ctx->opcode)); \
8118: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
8119: tcg_temp_free_i64(t0); \
8120: }
8121: #define GEN_SPEFPUOP_CONV_64_32(name) \
1.1.1.8 root 8122: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8123: { \
8124: TCGv_i64 t0 = tcg_temp_new_i64(); \
8125: gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
8126: gen_store_gpr64(rD(ctx->opcode), t0); \
8127: tcg_temp_free_i64(t0); \
8128: }
8129: #define GEN_SPEFPUOP_CONV_64_64(name) \
1.1.1.8 root 8130: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8131: { \
8132: TCGv_i64 t0 = tcg_temp_new_i64(); \
8133: gen_load_gpr64(t0, rB(ctx->opcode)); \
8134: gen_helper_##name(t0, t0); \
8135: gen_store_gpr64(rD(ctx->opcode), t0); \
8136: tcg_temp_free_i64(t0); \
8137: }
8138: #define GEN_SPEFPUOP_ARITH2_32_32(name) \
1.1.1.8 root 8139: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8140: { \
8141: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8142: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8143: return; \
8144: } \
8145: gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \
8146: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8147: }
8148: #define GEN_SPEFPUOP_ARITH2_64_64(name) \
1.1.1.8 root 8149: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8150: { \
8151: TCGv_i64 t0, t1; \
8152: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8153: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8154: return; \
8155: } \
8156: t0 = tcg_temp_new_i64(); \
8157: t1 = tcg_temp_new_i64(); \
8158: gen_load_gpr64(t0, rA(ctx->opcode)); \
8159: gen_load_gpr64(t1, rB(ctx->opcode)); \
8160: gen_helper_##name(t0, t0, t1); \
8161: gen_store_gpr64(rD(ctx->opcode), t0); \
8162: tcg_temp_free_i64(t0); \
8163: tcg_temp_free_i64(t1); \
8164: }
8165: #define GEN_SPEFPUOP_COMP_32(name) \
1.1.1.8 root 8166: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8167: { \
8168: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8169: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8170: return; \
8171: } \
8172: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8173: cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8174: }
8175: #define GEN_SPEFPUOP_COMP_64(name) \
1.1.1.8 root 8176: static inline void gen_##name(DisasContext *ctx) \
1.1.1.6 root 8177: { \
8178: TCGv_i64 t0, t1; \
8179: if (unlikely(!ctx->spe_enabled)) { \
1.1.1.12 root 8180: gen_exception(ctx, POWERPC_EXCP_SPEU); \
1.1.1.6 root 8181: return; \
8182: } \
8183: t0 = tcg_temp_new_i64(); \
8184: t1 = tcg_temp_new_i64(); \
8185: gen_load_gpr64(t0, rA(ctx->opcode)); \
8186: gen_load_gpr64(t1, rB(ctx->opcode)); \
8187: gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
8188: tcg_temp_free_i64(t0); \
8189: tcg_temp_free_i64(t1); \
8190: }
8191: #endif
1.1 root 8192:
1.1.1.5 root 8193: /* Single precision floating-point vectors operations */
8194: /* Arithmetic */
1.1.1.6 root 8195: GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
8196: GEN_SPEFPUOP_ARITH2_64_64(evfssub);
8197: GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
8198: GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
1.1.1.8 root 8199: static inline void gen_evfsabs(DisasContext *ctx)
1.1.1.6 root 8200: {
8201: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8202: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8203: return;
8204: }
8205: #if defined(TARGET_PPC64)
1.1.1.10 root 8206: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
1.1.1.6 root 8207: #else
1.1.1.10 root 8208: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
8209: tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
1.1.1.6 root 8210: #endif
8211: }
1.1.1.8 root 8212: static inline void gen_evfsnabs(DisasContext *ctx)
1.1.1.6 root 8213: {
8214: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8215: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8216: return;
8217: }
8218: #if defined(TARGET_PPC64)
1.1.1.10 root 8219: tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
1.1.1.6 root 8220: #else
1.1.1.10 root 8221: tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
8222: tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1.1.1.6 root 8223: #endif
8224: }
1.1.1.8 root 8225: static inline void gen_evfsneg(DisasContext *ctx)
1.1.1.6 root 8226: {
8227: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8228: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8229: return;
8230: }
8231: #if defined(TARGET_PPC64)
1.1.1.10 root 8232: tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
1.1.1.6 root 8233: #else
1.1.1.10 root 8234: tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
8235: tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1.1.1.6 root 8236: #endif
8237: }
8238:
1.1.1.5 root 8239: /* Conversion */
1.1.1.6 root 8240: GEN_SPEFPUOP_CONV_64_64(evfscfui);
8241: GEN_SPEFPUOP_CONV_64_64(evfscfsi);
8242: GEN_SPEFPUOP_CONV_64_64(evfscfuf);
8243: GEN_SPEFPUOP_CONV_64_64(evfscfsf);
8244: GEN_SPEFPUOP_CONV_64_64(evfsctui);
8245: GEN_SPEFPUOP_CONV_64_64(evfsctsi);
8246: GEN_SPEFPUOP_CONV_64_64(evfsctuf);
8247: GEN_SPEFPUOP_CONV_64_64(evfsctsf);
8248: GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
8249: GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
8250:
1.1.1.5 root 8251: /* Comparison */
1.1.1.6 root 8252: GEN_SPEFPUOP_COMP_64(evfscmpgt);
8253: GEN_SPEFPUOP_COMP_64(evfscmplt);
8254: GEN_SPEFPUOP_COMP_64(evfscmpeq);
8255: GEN_SPEFPUOP_COMP_64(evfststgt);
8256: GEN_SPEFPUOP_COMP_64(evfststlt);
8257: GEN_SPEFPUOP_COMP_64(evfststeq);
1.1.1.5 root 8258:
8259: /* Opcodes definitions */
1.1.1.12 root 8260: GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8261: GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
8262: GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8263: GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8264: GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8265: GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8266: GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8267: GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8268: GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8269: GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8270: GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8271: GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8272: GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8273: GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
1.1.1.5 root 8274:
8275: /* Single precision floating-point operations */
8276: /* Arithmetic */
1.1.1.6 root 8277: GEN_SPEFPUOP_ARITH2_32_32(efsadd);
8278: GEN_SPEFPUOP_ARITH2_32_32(efssub);
8279: GEN_SPEFPUOP_ARITH2_32_32(efsmul);
8280: GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
1.1.1.8 root 8281: static inline void gen_efsabs(DisasContext *ctx)
1.1.1.6 root 8282: {
8283: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8284: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8285: return;
8286: }
1.1.1.10 root 8287: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
1.1.1.6 root 8288: }
1.1.1.8 root 8289: static inline void gen_efsnabs(DisasContext *ctx)
1.1.1.6 root 8290: {
8291: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8292: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8293: return;
8294: }
1.1.1.10 root 8295: tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1.1.1.6 root 8296: }
1.1.1.8 root 8297: static inline void gen_efsneg(DisasContext *ctx)
1.1.1.6 root 8298: {
8299: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8300: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8301: return;
8302: }
1.1.1.10 root 8303: tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1.1.1.6 root 8304: }
8305:
1.1.1.5 root 8306: /* Conversion */
1.1.1.6 root 8307: GEN_SPEFPUOP_CONV_32_32(efscfui);
8308: GEN_SPEFPUOP_CONV_32_32(efscfsi);
8309: GEN_SPEFPUOP_CONV_32_32(efscfuf);
8310: GEN_SPEFPUOP_CONV_32_32(efscfsf);
8311: GEN_SPEFPUOP_CONV_32_32(efsctui);
8312: GEN_SPEFPUOP_CONV_32_32(efsctsi);
8313: GEN_SPEFPUOP_CONV_32_32(efsctuf);
8314: GEN_SPEFPUOP_CONV_32_32(efsctsf);
8315: GEN_SPEFPUOP_CONV_32_32(efsctuiz);
8316: GEN_SPEFPUOP_CONV_32_32(efsctsiz);
8317: GEN_SPEFPUOP_CONV_32_64(efscfd);
8318:
1.1.1.5 root 8319: /* Comparison */
1.1.1.6 root 8320: GEN_SPEFPUOP_COMP_32(efscmpgt);
8321: GEN_SPEFPUOP_COMP_32(efscmplt);
8322: GEN_SPEFPUOP_COMP_32(efscmpeq);
8323: GEN_SPEFPUOP_COMP_32(efststgt);
8324: GEN_SPEFPUOP_COMP_32(efststlt);
8325: GEN_SPEFPUOP_COMP_32(efststeq);
1.1.1.5 root 8326:
8327: /* Opcodes definitions */
1.1.1.12 root 8328: GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8329: GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
8330: GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8331: GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8332: GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8333: GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
8334: GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8335: GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8336: GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8337: GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8338: GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8339: GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8340: GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8341: GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
1.1.1.5 root 8342:
8343: /* Double precision floating-point operations */
8344: /* Arithmetic */
1.1.1.6 root 8345: GEN_SPEFPUOP_ARITH2_64_64(efdadd);
8346: GEN_SPEFPUOP_ARITH2_64_64(efdsub);
8347: GEN_SPEFPUOP_ARITH2_64_64(efdmul);
8348: GEN_SPEFPUOP_ARITH2_64_64(efddiv);
1.1.1.8 root 8349: static inline void gen_efdabs(DisasContext *ctx)
1.1.1.6 root 8350: {
8351: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8352: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8353: return;
8354: }
8355: #if defined(TARGET_PPC64)
1.1.1.10 root 8356: tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
1.1.1.6 root 8357: #else
1.1.1.10 root 8358: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8359: tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
1.1.1.6 root 8360: #endif
8361: }
1.1.1.8 root 8362: static inline void gen_efdnabs(DisasContext *ctx)
1.1.1.6 root 8363: {
8364: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8365: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8366: return;
8367: }
8368: #if defined(TARGET_PPC64)
1.1.1.10 root 8369: tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
1.1.1.6 root 8370: #else
1.1.1.10 root 8371: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8372: tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1.1.1.6 root 8373: #endif
8374: }
1.1.1.8 root 8375: static inline void gen_efdneg(DisasContext *ctx)
1.1.1.6 root 8376: {
8377: if (unlikely(!ctx->spe_enabled)) {
1.1.1.12 root 8378: gen_exception(ctx, POWERPC_EXCP_SPEU);
1.1.1.6 root 8379: return;
8380: }
8381: #if defined(TARGET_PPC64)
1.1.1.10 root 8382: tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
1.1.1.6 root 8383: #else
1.1.1.10 root 8384: tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8385: tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1.1.1.6 root 8386: #endif
8387: }
8388:
1.1.1.5 root 8389: /* Conversion */
1.1.1.6 root 8390: GEN_SPEFPUOP_CONV_64_32(efdcfui);
8391: GEN_SPEFPUOP_CONV_64_32(efdcfsi);
8392: GEN_SPEFPUOP_CONV_64_32(efdcfuf);
8393: GEN_SPEFPUOP_CONV_64_32(efdcfsf);
8394: GEN_SPEFPUOP_CONV_32_64(efdctui);
8395: GEN_SPEFPUOP_CONV_32_64(efdctsi);
8396: GEN_SPEFPUOP_CONV_32_64(efdctuf);
8397: GEN_SPEFPUOP_CONV_32_64(efdctsf);
8398: GEN_SPEFPUOP_CONV_32_64(efdctuiz);
8399: GEN_SPEFPUOP_CONV_32_64(efdctsiz);
8400: GEN_SPEFPUOP_CONV_64_32(efdcfs);
8401: GEN_SPEFPUOP_CONV_64_64(efdcfuid);
8402: GEN_SPEFPUOP_CONV_64_64(efdcfsid);
8403: GEN_SPEFPUOP_CONV_64_64(efdctuidz);
8404: GEN_SPEFPUOP_CONV_64_64(efdctsidz);
1.1.1.5 root 8405:
8406: /* Comparison */
1.1.1.6 root 8407: GEN_SPEFPUOP_COMP_64(efdcmpgt);
8408: GEN_SPEFPUOP_COMP_64(efdcmplt);
8409: GEN_SPEFPUOP_COMP_64(efdcmpeq);
8410: GEN_SPEFPUOP_COMP_64(efdtstgt);
8411: GEN_SPEFPUOP_COMP_64(efdtstlt);
8412: GEN_SPEFPUOP_COMP_64(efdtsteq);
1.1.1.5 root 8413:
8414: /* Opcodes definitions */
1.1.1.12 root 8415: GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
8416: GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8417: GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
8418: GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8419: GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
8420: GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8421: GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
8422: GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
8423: GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8424: GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8425: GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8426: GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8427: GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8428: GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8429: GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
8430: GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
1.1.1.5 root 8431:
1.1.1.7 root 8432: static opcode_t opcodes[] = {
8433: GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
8434: GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
8435: GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
8436: GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
8437: GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
8438: GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
8439: GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8440: GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8441: GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8442: GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8443: GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
8444: GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
8445: GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
8446: GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
8447: GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8448: #if defined(TARGET_PPC64)
8449: GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
8450: #endif
8451: GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
8452: GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
8453: GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8454: GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8455: GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8456: GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
8457: GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
8458: GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
8459: GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8460: GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8461: GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8462: GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8463: GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
1.1.1.11 root 8464: GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
1.1.1.7 root 8465: #if defined(TARGET_PPC64)
1.1.1.11 root 8466: GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
1.1.1.7 root 8467: GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
8468: #endif
8469: GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8470: GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8471: GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8472: GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
8473: GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
8474: GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
8475: GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
8476: #if defined(TARGET_PPC64)
8477: GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
8478: GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
8479: GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
8480: GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
8481: GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
8482: #endif
8483: GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
8484: GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8485: GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8486: GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
8487: GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
8488: GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
8489: GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
8490: GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
8491: GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
8492: GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
8493: GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
8494: GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
8495: #if defined(TARGET_PPC64)
8496: GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
8497: GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
8498: GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
8499: #endif
8500: GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8501: GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8502: GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
8503: GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
8504: GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
8505: GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
8506: GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
8507: GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
1.1.1.10 root 8508: GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
1.1.1.7 root 8509: GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
8510: #if defined(TARGET_PPC64)
1.1.1.10 root 8511: GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
1.1.1.7 root 8512: GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
8513: #endif
8514: GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
8515: GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
8516: GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8517: GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8518: GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
8519: GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
8520: GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
8521: GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
8522: #if defined(TARGET_PPC64)
8523: GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
8524: GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
8525: #endif
8526: GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
8527: GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
8528: GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8529: #if defined(TARGET_PPC64)
8530: GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
8531: GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
8532: #endif
8533: GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
8534: GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
8535: GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
8536: GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
8537: GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
8538: GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
8539: #if defined(TARGET_PPC64)
8540: GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
8541: #endif
8542: GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
8543: GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC),
8544: GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
8545: GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
8546: GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
8547: GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE),
8548: GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE),
8549: GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ),
8550: GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT),
8551: GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
8552: GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
8553: GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
8554: GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
8555: GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
8556: GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
8557: GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
8558: GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
8559: GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
8560: #if defined(TARGET_PPC64)
8561: GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
8562: GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
8563: PPC_SEGMENT_64B),
8564: GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
8565: GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
8566: PPC_SEGMENT_64B),
1.1.1.11 root 8567: GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
8568: GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
8569: GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
1.1.1.7 root 8570: #endif
8571: GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
8572: GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
8573: GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
8574: GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
8575: #if defined(TARGET_PPC64)
8576: GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
8577: GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
8578: #endif
8579: GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
8580: GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
8581: GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
8582: GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
8583: GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
8584: GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
8585: GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
8586: GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
8587: GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
8588: GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
8589: GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
8590: GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8591: GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
8592: GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
8593: GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
8594: GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
8595: GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
8596: GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
8597: GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
8598: GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8599: GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
8600: GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
8601: GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
8602: GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
8603: GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
8604: GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
8605: GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
8606: GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
8607: GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
8608: GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
8609: GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
8610: GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
8611: GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
8612: GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
8613: GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
8614: GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
8615: GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
8616: GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
8617: GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
8618: GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
8619: GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
8620: GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
8621: GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
8622: GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
8623: GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
8624: GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
8625: GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
8626: GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
8627: GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
8628: GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8629: GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8630: GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
8631: GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
8632: GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8633: GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8634: GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
8635: GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
8636: GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
8637: GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
8638: GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
8639: GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
8640: GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
8641: GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
8642: GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
8643: GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
8644: GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
8645: GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
8646: GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
8647: GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
8648: GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
8649: GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
1.1.1.11 root 8650: GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
1.1.1.7 root 8651: GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
8652: GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
8653: GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
8654: GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
8655: GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
8656: GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
8657: GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
8658: GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
1.1.1.11 root 8659: GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
8660: PPC_NONE, PPC2_BOOKE206),
8661: GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
8662: PPC_NONE, PPC2_BOOKE206),
8663: GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
8664: PPC_NONE, PPC2_BOOKE206),
8665: GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
8666: PPC_NONE, PPC2_BOOKE206),
1.1.1.13! root 8667: GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
! 8668: PPC_NONE, PPC2_BOOKE206),
! 8669: GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
! 8670: PPC_NONE, PPC2_PRCNTL),
! 8671: GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
! 8672: PPC_NONE, PPC2_PRCNTL),
1.1.1.7 root 8673: GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8674: GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8675: GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
1.1.1.11 root 8676: GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
8677: PPC_BOOKE, PPC2_BOOKE206),
1.1.1.13! root 8678: GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
1.1.1.11 root 8679: GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
8680: PPC_BOOKE, PPC2_BOOKE206),
1.1.1.7 root 8681: GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
8682: GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
8683: GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
8684: GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
8685: GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC),
8686: GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
8687: GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
8688: GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
8689: GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
8690: GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
8691:
8692: #undef GEN_INT_ARITH_ADD
8693: #undef GEN_INT_ARITH_ADD_CONST
8694: #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
8695: GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
8696: #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
8697: add_ca, compute_ca, compute_ov) \
8698: GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
8699: GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
8700: GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
8701: GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
8702: GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
8703: GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
8704: GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
8705: GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
8706: GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
8707: GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
8708: GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
8709:
8710: #undef GEN_INT_ARITH_DIVW
8711: #define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
8712: GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
8713: GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
8714: GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
8715: GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
8716: GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
8717:
8718: #if defined(TARGET_PPC64)
8719: #undef GEN_INT_ARITH_DIVD
8720: #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
8721: GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8722: GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
8723: GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
8724: GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
8725: GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
8726:
8727: #undef GEN_INT_ARITH_MUL_HELPER
8728: #define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
8729: GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8730: GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
8731: GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
8732: GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
8733: #endif
8734:
8735: #undef GEN_INT_ARITH_SUBF
8736: #undef GEN_INT_ARITH_SUBF_CONST
8737: #define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
8738: GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
8739: #define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
8740: add_ca, compute_ca, compute_ov) \
8741: GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
8742: GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
8743: GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
8744: GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
8745: GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
8746: GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
8747: GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
8748: GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
8749: GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
8750: GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
8751: GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
8752:
8753: #undef GEN_LOGICAL1
8754: #undef GEN_LOGICAL2
8755: #define GEN_LOGICAL2(name, tcg_op, opc, type) \
8756: GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
8757: #define GEN_LOGICAL1(name, tcg_op, opc, type) \
8758: GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
8759: GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
8760: GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
8761: GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
8762: GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
8763: GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
8764: GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
8765: GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
8766: GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
8767: #if defined(TARGET_PPC64)
8768: GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
8769: #endif
8770:
8771: #if defined(TARGET_PPC64)
8772: #undef GEN_PPC64_R2
8773: #undef GEN_PPC64_R4
8774: #define GEN_PPC64_R2(name, opc1, opc2) \
8775: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8776: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8777: PPC_64B)
8778: #define GEN_PPC64_R4(name, opc1, opc2) \
8779: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8780: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
8781: PPC_64B), \
8782: GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8783: PPC_64B), \
8784: GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
8785: PPC_64B)
8786: GEN_PPC64_R4(rldicl, 0x1E, 0x00),
8787: GEN_PPC64_R4(rldicr, 0x1E, 0x02),
8788: GEN_PPC64_R4(rldic, 0x1E, 0x04),
8789: GEN_PPC64_R2(rldcl, 0x1E, 0x08),
8790: GEN_PPC64_R2(rldcr, 0x1E, 0x09),
8791: GEN_PPC64_R4(rldimi, 0x1E, 0x06),
8792: #endif
8793:
8794: #undef _GEN_FLOAT_ACB
8795: #undef GEN_FLOAT_ACB
8796: #undef _GEN_FLOAT_AB
8797: #undef GEN_FLOAT_AB
8798: #undef _GEN_FLOAT_AC
8799: #undef GEN_FLOAT_AC
8800: #undef GEN_FLOAT_B
8801: #undef GEN_FLOAT_BS
8802: #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
8803: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
8804: #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
8805: _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type), \
8806: _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
8807: #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8808: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8809: #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
8810: _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8811: _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8812: #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8813: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8814: #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
8815: _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8816: _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8817: #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
8818: GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
8819: #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
8820: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
8821:
8822: GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
8823: GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
8824: GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
8825: GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
8826: GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
8827: GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
8828: _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
8829: GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
8830: GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
8831: GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
8832: GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
8833: GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
8834: GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
8835: GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
8836: GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
8837: #if defined(TARGET_PPC64)
8838: GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
8839: GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
8840: GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
8841: #endif
8842: GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
8843: GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
8844: GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
8845: GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
8846: GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT),
8847: GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT),
8848: GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
8849:
8850: #undef GEN_LD
8851: #undef GEN_LDU
8852: #undef GEN_LDUX
1.1.1.13! root 8853: #undef GEN_LDX_E
1.1.1.7 root 8854: #undef GEN_LDS
8855: #define GEN_LD(name, ldop, opc, type) \
8856: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8857: #define GEN_LDU(name, ldop, opc, type) \
8858: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8859: #define GEN_LDUX(name, ldop, opc2, opc3, type) \
8860: GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
1.1.1.13! root 8861: #define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
! 8862: GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
1.1.1.7 root 8863: #define GEN_LDS(name, ldop, op, type) \
8864: GEN_LD(name, ldop, op | 0x20, type) \
8865: GEN_LDU(name, ldop, op | 0x21, type) \
8866: GEN_LDUX(name, ldop, 0x17, op | 0x01, type) \
8867: GEN_LDX(name, ldop, 0x17, op | 0x00, type)
8868:
8869: GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
8870: GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
8871: GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
8872: GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
8873: #if defined(TARGET_PPC64)
8874: GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
8875: GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
8876: GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
8877: GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
1.1.1.13! root 8878: GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
1.1.1.7 root 8879: #endif
8880: GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
8881: GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
8882:
8883: #undef GEN_ST
8884: #undef GEN_STU
8885: #undef GEN_STUX
1.1.1.13! root 8886: #undef GEN_STX_E
1.1.1.7 root 8887: #undef GEN_STS
8888: #define GEN_ST(name, stop, opc, type) \
8889: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8890: #define GEN_STU(name, stop, opc, type) \
8891: GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
8892: #define GEN_STUX(name, stop, opc2, opc3, type) \
8893: GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
1.1.1.13! root 8894: #define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
! 8895: GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
1.1.1.7 root 8896: #define GEN_STS(name, stop, op, type) \
8897: GEN_ST(name, stop, op | 0x20, type) \
8898: GEN_STU(name, stop, op | 0x21, type) \
8899: GEN_STUX(name, stop, 0x17, op | 0x01, type) \
8900: GEN_STX(name, stop, 0x17, op | 0x00, type)
8901:
8902: GEN_STS(stb, st8, 0x06, PPC_INTEGER)
8903: GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
8904: GEN_STS(stw, st32, 0x04, PPC_INTEGER)
8905: #if defined(TARGET_PPC64)
8906: GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
8907: GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
1.1.1.13! root 8908: GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
1.1.1.7 root 8909: #endif
8910: GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
8911: GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
8912:
8913: #undef GEN_LDF
8914: #undef GEN_LDUF
8915: #undef GEN_LDUXF
8916: #undef GEN_LDXF
8917: #undef GEN_LDFS
8918: #define GEN_LDF(name, ldop, opc, type) \
8919: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8920: #define GEN_LDUF(name, ldop, opc, type) \
8921: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8922: #define GEN_LDUXF(name, ldop, opc, type) \
8923: GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8924: #define GEN_LDXF(name, ldop, opc2, opc3, type) \
8925: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8926: #define GEN_LDFS(name, ldop, op, type) \
8927: GEN_LDF(name, ldop, op | 0x20, type) \
8928: GEN_LDUF(name, ldop, op | 0x21, type) \
8929: GEN_LDUXF(name, ldop, op | 0x01, type) \
8930: GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
8931:
8932: GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
8933: GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
8934:
8935: #undef GEN_STF
8936: #undef GEN_STUF
8937: #undef GEN_STUXF
8938: #undef GEN_STXF
8939: #undef GEN_STFS
8940: #define GEN_STF(name, stop, opc, type) \
8941: GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8942: #define GEN_STUF(name, stop, opc, type) \
8943: GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8944: #define GEN_STUXF(name, stop, opc, type) \
8945: GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8946: #define GEN_STXF(name, stop, opc2, opc3, type) \
8947: GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8948: #define GEN_STFS(name, stop, op, type) \
8949: GEN_STF(name, stop, op | 0x20, type) \
8950: GEN_STUF(name, stop, op | 0x21, type) \
8951: GEN_STUXF(name, stop, op | 0x01, type) \
8952: GEN_STXF(name, stop, 0x17, op | 0x00, type)
8953:
8954: GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
8955: GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
8956: GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
8957:
8958: #undef GEN_CRLOGIC
8959: #define GEN_CRLOGIC(name, tcg_op, opc) \
8960: GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
8961: GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
8962: GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
8963: GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
8964: GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
8965: GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
8966: GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
8967: GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
8968: GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
8969:
8970: #undef GEN_MAC_HANDLER
8971: #define GEN_MAC_HANDLER(name, opc2, opc3) \
8972: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
8973: GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
8974: GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
8975: GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
8976: GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
8977: GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
8978: GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
8979: GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
8980: GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
8981: GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
8982: GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
8983: GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
8984: GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
8985: GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
8986: GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
8987: GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
8988: GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
8989: GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
8990: GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
8991: GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
8992: GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
8993: GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
8994: GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
8995: GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
8996: GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
8997: GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
8998: GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
8999: GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
9000: GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
9001: GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
9002: GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
9003: GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
9004: GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
9005: GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
9006: GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
9007: GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
9008: GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
9009: GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
9010: GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
9011: GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
9012: GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
9013: GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
9014: GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
9015:
9016: #undef GEN_VR_LDX
9017: #undef GEN_VR_STX
9018: #undef GEN_VR_LVE
9019: #undef GEN_VR_STVE
9020: #define GEN_VR_LDX(name, opc2, opc3) \
9021: GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9022: #define GEN_VR_STX(name, opc2, opc3) \
9023: GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9024: #define GEN_VR_LVE(name, opc2, opc3) \
9025: GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9026: #define GEN_VR_STVE(name, opc2, opc3) \
9027: GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9028: GEN_VR_LDX(lvx, 0x07, 0x03),
9029: GEN_VR_LDX(lvxl, 0x07, 0x0B),
9030: GEN_VR_LVE(bx, 0x07, 0x00),
9031: GEN_VR_LVE(hx, 0x07, 0x01),
9032: GEN_VR_LVE(wx, 0x07, 0x02),
9033: GEN_VR_STX(svx, 0x07, 0x07),
9034: GEN_VR_STX(svxl, 0x07, 0x0F),
9035: GEN_VR_STVE(bx, 0x07, 0x04),
9036: GEN_VR_STVE(hx, 0x07, 0x05),
9037: GEN_VR_STVE(wx, 0x07, 0x06),
9038:
9039: #undef GEN_VX_LOGICAL
9040: #define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
9041: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9042: GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
9043: GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
9044: GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
9045: GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
9046: GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
9047:
9048: #undef GEN_VXFORM
9049: #define GEN_VXFORM(name, opc2, opc3) \
9050: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9051: GEN_VXFORM(vaddubm, 0, 0),
9052: GEN_VXFORM(vadduhm, 0, 1),
9053: GEN_VXFORM(vadduwm, 0, 2),
9054: GEN_VXFORM(vsububm, 0, 16),
9055: GEN_VXFORM(vsubuhm, 0, 17),
9056: GEN_VXFORM(vsubuwm, 0, 18),
9057: GEN_VXFORM(vmaxub, 1, 0),
9058: GEN_VXFORM(vmaxuh, 1, 1),
9059: GEN_VXFORM(vmaxuw, 1, 2),
9060: GEN_VXFORM(vmaxsb, 1, 4),
9061: GEN_VXFORM(vmaxsh, 1, 5),
9062: GEN_VXFORM(vmaxsw, 1, 6),
9063: GEN_VXFORM(vminub, 1, 8),
9064: GEN_VXFORM(vminuh, 1, 9),
9065: GEN_VXFORM(vminuw, 1, 10),
9066: GEN_VXFORM(vminsb, 1, 12),
9067: GEN_VXFORM(vminsh, 1, 13),
9068: GEN_VXFORM(vminsw, 1, 14),
9069: GEN_VXFORM(vavgub, 1, 16),
9070: GEN_VXFORM(vavguh, 1, 17),
9071: GEN_VXFORM(vavguw, 1, 18),
9072: GEN_VXFORM(vavgsb, 1, 20),
9073: GEN_VXFORM(vavgsh, 1, 21),
9074: GEN_VXFORM(vavgsw, 1, 22),
9075: GEN_VXFORM(vmrghb, 6, 0),
9076: GEN_VXFORM(vmrghh, 6, 1),
9077: GEN_VXFORM(vmrghw, 6, 2),
9078: GEN_VXFORM(vmrglb, 6, 4),
9079: GEN_VXFORM(vmrglh, 6, 5),
9080: GEN_VXFORM(vmrglw, 6, 6),
9081: GEN_VXFORM(vmuloub, 4, 0),
9082: GEN_VXFORM(vmulouh, 4, 1),
9083: GEN_VXFORM(vmulosb, 4, 4),
9084: GEN_VXFORM(vmulosh, 4, 5),
9085: GEN_VXFORM(vmuleub, 4, 8),
9086: GEN_VXFORM(vmuleuh, 4, 9),
9087: GEN_VXFORM(vmulesb, 4, 12),
9088: GEN_VXFORM(vmulesh, 4, 13),
9089: GEN_VXFORM(vslb, 2, 4),
9090: GEN_VXFORM(vslh, 2, 5),
9091: GEN_VXFORM(vslw, 2, 6),
9092: GEN_VXFORM(vsrb, 2, 8),
9093: GEN_VXFORM(vsrh, 2, 9),
9094: GEN_VXFORM(vsrw, 2, 10),
9095: GEN_VXFORM(vsrab, 2, 12),
9096: GEN_VXFORM(vsrah, 2, 13),
9097: GEN_VXFORM(vsraw, 2, 14),
9098: GEN_VXFORM(vslo, 6, 16),
9099: GEN_VXFORM(vsro, 6, 17),
9100: GEN_VXFORM(vaddcuw, 0, 6),
9101: GEN_VXFORM(vsubcuw, 0, 22),
9102: GEN_VXFORM(vaddubs, 0, 8),
9103: GEN_VXFORM(vadduhs, 0, 9),
9104: GEN_VXFORM(vadduws, 0, 10),
9105: GEN_VXFORM(vaddsbs, 0, 12),
9106: GEN_VXFORM(vaddshs, 0, 13),
9107: GEN_VXFORM(vaddsws, 0, 14),
9108: GEN_VXFORM(vsububs, 0, 24),
9109: GEN_VXFORM(vsubuhs, 0, 25),
9110: GEN_VXFORM(vsubuws, 0, 26),
9111: GEN_VXFORM(vsubsbs, 0, 28),
9112: GEN_VXFORM(vsubshs, 0, 29),
9113: GEN_VXFORM(vsubsws, 0, 30),
9114: GEN_VXFORM(vrlb, 2, 0),
9115: GEN_VXFORM(vrlh, 2, 1),
9116: GEN_VXFORM(vrlw, 2, 2),
9117: GEN_VXFORM(vsl, 2, 7),
9118: GEN_VXFORM(vsr, 2, 11),
9119: GEN_VXFORM(vpkuhum, 7, 0),
9120: GEN_VXFORM(vpkuwum, 7, 1),
9121: GEN_VXFORM(vpkuhus, 7, 2),
9122: GEN_VXFORM(vpkuwus, 7, 3),
9123: GEN_VXFORM(vpkshus, 7, 4),
9124: GEN_VXFORM(vpkswus, 7, 5),
9125: GEN_VXFORM(vpkshss, 7, 6),
9126: GEN_VXFORM(vpkswss, 7, 7),
9127: GEN_VXFORM(vpkpx, 7, 12),
9128: GEN_VXFORM(vsum4ubs, 4, 24),
9129: GEN_VXFORM(vsum4sbs, 4, 28),
9130: GEN_VXFORM(vsum4shs, 4, 25),
9131: GEN_VXFORM(vsum2sws, 4, 26),
9132: GEN_VXFORM(vsumsws, 4, 30),
9133: GEN_VXFORM(vaddfp, 5, 0),
9134: GEN_VXFORM(vsubfp, 5, 1),
9135: GEN_VXFORM(vmaxfp, 5, 16),
9136: GEN_VXFORM(vminfp, 5, 17),
9137:
9138: #undef GEN_VXRFORM1
9139: #undef GEN_VXRFORM
9140: #define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
9141: GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
9142: #define GEN_VXRFORM(name, opc2, opc3) \
9143: GEN_VXRFORM1(name, name, #name, opc2, opc3) \
9144: GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
9145: GEN_VXRFORM(vcmpequb, 3, 0)
9146: GEN_VXRFORM(vcmpequh, 3, 1)
9147: GEN_VXRFORM(vcmpequw, 3, 2)
9148: GEN_VXRFORM(vcmpgtsb, 3, 12)
9149: GEN_VXRFORM(vcmpgtsh, 3, 13)
9150: GEN_VXRFORM(vcmpgtsw, 3, 14)
9151: GEN_VXRFORM(vcmpgtub, 3, 8)
9152: GEN_VXRFORM(vcmpgtuh, 3, 9)
9153: GEN_VXRFORM(vcmpgtuw, 3, 10)
9154: GEN_VXRFORM(vcmpeqfp, 3, 3)
9155: GEN_VXRFORM(vcmpgefp, 3, 7)
9156: GEN_VXRFORM(vcmpgtfp, 3, 11)
9157: GEN_VXRFORM(vcmpbfp, 3, 15)
9158:
9159: #undef GEN_VXFORM_SIMM
9160: #define GEN_VXFORM_SIMM(name, opc2, opc3) \
9161: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9162: GEN_VXFORM_SIMM(vspltisb, 6, 12),
9163: GEN_VXFORM_SIMM(vspltish, 6, 13),
9164: GEN_VXFORM_SIMM(vspltisw, 6, 14),
9165:
9166: #undef GEN_VXFORM_NOA
9167: #define GEN_VXFORM_NOA(name, opc2, opc3) \
9168: GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
9169: GEN_VXFORM_NOA(vupkhsb, 7, 8),
9170: GEN_VXFORM_NOA(vupkhsh, 7, 9),
9171: GEN_VXFORM_NOA(vupklsb, 7, 10),
9172: GEN_VXFORM_NOA(vupklsh, 7, 11),
9173: GEN_VXFORM_NOA(vupkhpx, 7, 13),
9174: GEN_VXFORM_NOA(vupklpx, 7, 15),
9175: GEN_VXFORM_NOA(vrefp, 5, 4),
9176: GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
1.1.1.9 root 9177: GEN_VXFORM_NOA(vexptefp, 5, 6),
1.1.1.7 root 9178: GEN_VXFORM_NOA(vlogefp, 5, 7),
9179: GEN_VXFORM_NOA(vrfim, 5, 8),
9180: GEN_VXFORM_NOA(vrfin, 5, 9),
9181: GEN_VXFORM_NOA(vrfip, 5, 10),
9182: GEN_VXFORM_NOA(vrfiz, 5, 11),
9183:
9184: #undef GEN_VXFORM_UIMM
9185: #define GEN_VXFORM_UIMM(name, opc2, opc3) \
9186: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9187: GEN_VXFORM_UIMM(vspltb, 6, 8),
9188: GEN_VXFORM_UIMM(vsplth, 6, 9),
9189: GEN_VXFORM_UIMM(vspltw, 6, 10),
9190: GEN_VXFORM_UIMM(vcfux, 5, 12),
9191: GEN_VXFORM_UIMM(vcfsx, 5, 13),
9192: GEN_VXFORM_UIMM(vctuxs, 5, 14),
9193: GEN_VXFORM_UIMM(vctsxs, 5, 15),
9194:
9195: #undef GEN_VAFORM_PAIRED
9196: #define GEN_VAFORM_PAIRED(name0, name1, opc2) \
9197: GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
9198: GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
9199: GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
9200: GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
9201: GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
9202: GEN_VAFORM_PAIRED(vsel, vperm, 21),
9203: GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
9204:
9205: #undef GEN_SPE
1.1.1.12 root 9206: #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
9207: GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
9208: GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9209: GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9210: GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9211: GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9212: GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
9213: GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
9214: GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
9215: GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
9216: GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
9217: GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
9218: GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9219: GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9220: GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9221: GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
9222: GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
9223: GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
9224: GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
9225: GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9226: GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9227: GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9228: GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9229: GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9230: GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
9231: GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
9232: GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9233: GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9234: GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
9235: GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
9236: GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),
9237:
9238: GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9239: GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
9240: GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
9241: GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9242: GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9243: GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9244: GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9245: GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9246: GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9247: GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9248: GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9249: GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9250: GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9251: GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9252:
9253: GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9254: GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
9255: GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
9256: GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9257: GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9258: GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE),
9259: GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9260: GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9261: GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9262: GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9263: GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9264: GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9265: GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9266: GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9267:
9268: GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
9269: GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9270: GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
9271: GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9272: GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
9273: GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9274: GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
9275: GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
9276: GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9277: GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9278: GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9279: GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9280: GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9281: GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9282: GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
9283: GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
1.1.1.7 root 9284:
9285: #undef GEN_SPEOP_LDST
9286: #define GEN_SPEOP_LDST(name, opc2, sh) \
9287: GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
9288: GEN_SPEOP_LDST(evldd, 0x00, 3),
9289: GEN_SPEOP_LDST(evldw, 0x01, 3),
9290: GEN_SPEOP_LDST(evldh, 0x02, 3),
9291: GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
9292: GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
9293: GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
9294: GEN_SPEOP_LDST(evlwhe, 0x08, 2),
9295: GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
9296: GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
9297: GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
9298: GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
9299:
9300: GEN_SPEOP_LDST(evstdd, 0x10, 3),
9301: GEN_SPEOP_LDST(evstdw, 0x11, 3),
9302: GEN_SPEOP_LDST(evstdh, 0x12, 3),
9303: GEN_SPEOP_LDST(evstwhe, 0x18, 2),
9304: GEN_SPEOP_LDST(evstwho, 0x1A, 2),
9305: GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
9306: GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
9307: };
1.1 root 9308:
1.1.1.5 root 9309: #include "helper_regs.h"
1.1.1.13! root 9310: #include "translate_init.c"
1.1 root 9311:
9312: /*****************************************************************************/
9313: /* Misc PowerPC helpers */
1.1.1.13! root 9314: void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
1.1.1.5 root 9315: int flags)
9316: {
1.1 root 9317: #define RGPL 4
9318: #define RFPL 4
9319:
9320: int i;
9321:
1.1.1.13! root 9322: cpu_synchronize_state(env);
! 9323:
1.1.1.8 root 9324: cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR "
1.1.1.10 root 9325: TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
9326: env->nip, env->lr, env->ctr, env->xer);
1.1.1.8 root 9327: cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF "
9328: TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0],
9329: env->hflags, env->mmu_idx);
1.1.1.5 root 9330: #if !defined(NO_TIMER_DUMP)
1.1.1.10 root 9331: cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
1.1.1.5 root 9332: #if !defined(CONFIG_USER_ONLY)
1.1.1.10 root 9333: " DECR %08" PRIu32
1.1.1.5 root 9334: #endif
9335: "\n",
9336: cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9337: #if !defined(CONFIG_USER_ONLY)
9338: , cpu_ppc_load_decr(env)
9339: #endif
9340: );
9341: #endif
9342: for (i = 0; i < 32; i++) {
1.1 root 9343: if ((i & (RGPL - 1)) == 0)
9344: cpu_fprintf(f, "GPR%02d", i);
1.1.1.8 root 9345: cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
1.1 root 9346: if ((i & (RGPL - 1)) == (RGPL - 1))
9347: cpu_fprintf(f, "\n");
1.1.1.5 root 9348: }
1.1 root 9349: cpu_fprintf(f, "CR ");
1.1.1.5 root 9350: for (i = 0; i < 8; i++)
1.1 root 9351: cpu_fprintf(f, "%01x", env->crf[i]);
9352: cpu_fprintf(f, " [");
1.1.1.5 root 9353: for (i = 0; i < 8; i++) {
9354: char a = '-';
9355: if (env->crf[i] & 0x08)
9356: a = 'L';
9357: else if (env->crf[i] & 0x04)
9358: a = 'G';
9359: else if (env->crf[i] & 0x02)
9360: a = 'E';
1.1 root 9361: cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
1.1.1.5 root 9362: }
1.1.1.8 root 9363: cpu_fprintf(f, " ] RES " TARGET_FMT_lx "\n",
9364: env->reserve_addr);
1.1 root 9365: for (i = 0; i < 32; i++) {
9366: if ((i & (RFPL - 1)) == 0)
9367: cpu_fprintf(f, "FPR%02d", i);
1.1.1.3 root 9368: cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
1.1 root 9369: if ((i & (RFPL - 1)) == (RFPL - 1))
9370: cpu_fprintf(f, "\n");
9371: }
1.1.1.6 root 9372: cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
1.1.1.5 root 9373: #if !defined(CONFIG_USER_ONLY)
1.1.1.11 root 9374: cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
9375: " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
9376: env->spr[SPR_SRR0], env->spr[SPR_SRR1],
9377: env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
9378:
9379: cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
9380: " SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n",
9381: env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
9382: env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
9383:
9384: cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
9385: " SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n",
9386: env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
9387: env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
9388:
9389: if (env->excp_model == POWERPC_EXCP_BOOKE) {
9390: cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
9391: " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
9392: env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
9393: env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
9394:
9395: cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
9396: " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
9397: env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
9398: env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
9399:
9400: cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
9401: " IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n",
9402: env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
9403: env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
9404:
9405: cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
9406: " EPR " TARGET_FMT_lx "\n",
9407: env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
9408: env->spr[SPR_BOOKE_EPR]);
9409:
9410: /* FSL-specific */
9411: cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx
9412: " PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n",
9413: env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
9414: env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
9415:
9416: /*
9417: * IVORs are left out as they are large and do not change often --
9418: * they can be read with "p $ivor0", "p $ivor1", etc.
9419: */
9420: }
9421:
1.1.1.12 root 9422: #if defined(TARGET_PPC64)
9423: if (env->flags & POWERPC_FLAG_CFAR) {
9424: cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
9425: }
9426: #endif
9427:
1.1.1.11 root 9428: switch (env->mmu_model) {
9429: case POWERPC_MMU_32B:
9430: case POWERPC_MMU_601:
9431: case POWERPC_MMU_SOFT_6xx:
9432: case POWERPC_MMU_SOFT_74xx:
9433: #if defined(TARGET_PPC64)
9434: case POWERPC_MMU_620:
9435: case POWERPC_MMU_64B:
9436: #endif
9437: cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
9438: break;
9439: case POWERPC_MMU_BOOKE206:
9440: cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
9441: " MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
9442: env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
9443: env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
9444:
9445: cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx
9446: " MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
9447: env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
9448: env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
9449:
9450: cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
9451: " TLB1CFG " TARGET_FMT_lx "\n",
9452: env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
9453: env->spr[SPR_BOOKE_TLB1CFG]);
9454: break;
9455: default:
9456: break;
9457: }
1.1.1.5 root 9458: #endif
1.1 root 9459:
9460: #undef RGPL
9461: #undef RFPL
1.1.1.5 root 9462: }
9463:
1.1.1.13! root 9464: void cpu_dump_statistics (CPUPPCState *env, FILE*f, fprintf_function cpu_fprintf,
1.1.1.5 root 9465: int flags)
9466: {
9467: #if defined(DO_PPC_STATISTICS)
9468: opc_handler_t **t1, **t2, **t3, *handler;
9469: int op1, op2, op3;
9470:
9471: t1 = env->opcodes;
9472: for (op1 = 0; op1 < 64; op1++) {
9473: handler = t1[op1];
9474: if (is_indirect_opcode(handler)) {
9475: t2 = ind_table(handler);
9476: for (op2 = 0; op2 < 32; op2++) {
9477: handler = t2[op2];
9478: if (is_indirect_opcode(handler)) {
9479: t3 = ind_table(handler);
9480: for (op3 = 0; op3 < 32; op3++) {
9481: handler = t3[op3];
9482: if (handler->count == 0)
9483: continue;
9484: cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
1.1.1.9 root 9485: "%016" PRIx64 " %" PRId64 "\n",
1.1.1.5 root 9486: op1, op2, op3, op1, (op3 << 5) | op2,
9487: handler->oname,
9488: handler->count, handler->count);
9489: }
9490: } else {
9491: if (handler->count == 0)
9492: continue;
9493: cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
1.1.1.9 root 9494: "%016" PRIx64 " %" PRId64 "\n",
1.1.1.5 root 9495: op1, op2, op1, op2, handler->oname,
9496: handler->count, handler->count);
9497: }
9498: }
9499: } else {
9500: if (handler->count == 0)
9501: continue;
1.1.1.9 root 9502: cpu_fprintf(f, "%02x (%02x ) %16s: %016" PRIx64
9503: " %" PRId64 "\n",
1.1.1.5 root 9504: op1, op1, handler->oname,
9505: handler->count, handler->count);
9506: }
9507: }
9508: #endif
1.1 root 9509: }
9510:
9511: /*****************************************************************************/
1.1.1.13! root 9512: static inline void gen_intermediate_code_internal(CPUPPCState *env,
1.1.1.8 root 9513: TranslationBlock *tb,
9514: int search_pc)
1.1 root 9515: {
9516: DisasContext ctx, *ctxp = &ctx;
9517: opc_handler_t **table, *handler;
9518: target_ulong pc_start;
9519: uint16_t *gen_opc_end;
1.1.1.6 root 9520: CPUBreakpoint *bp;
1.1 root 9521: int j, lj = -1;
1.1.1.6 root 9522: int num_insns;
9523: int max_insns;
1.1 root 9524:
9525: pc_start = tb->pc;
9526: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9527: ctx.nip = pc_start;
9528: ctx.tb = tb;
1.1.1.5 root 9529: ctx.exception = POWERPC_EXCP_NONE;
1.1 root 9530: ctx.spr_cb = env->spr_cb;
1.1.1.6 root 9531: ctx.mem_idx = env->mmu_idx;
9532: ctx.access_type = -1;
9533: ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
1.1.1.5 root 9534: #if defined(TARGET_PPC64)
9535: ctx.sf_mode = msr_sf;
1.1.1.12 root 9536: ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
1.1 root 9537: #endif
9538: ctx.fpu_enabled = msr_fp;
1.1.1.5 root 9539: if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9540: ctx.spe_enabled = msr_spe;
9541: else
9542: ctx.spe_enabled = 0;
9543: if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
9544: ctx.altivec_enabled = msr_vr;
9545: else
9546: ctx.altivec_enabled = 0;
9547: if ((env->flags & POWERPC_FLAG_SE) && msr_se)
1.1.1.6 root 9548: ctx.singlestep_enabled = CPU_SINGLE_STEP;
1.1.1.5 root 9549: else
1.1.1.6 root 9550: ctx.singlestep_enabled = 0;
1.1.1.5 root 9551: if ((env->flags & POWERPC_FLAG_BE) && msr_be)
1.1.1.6 root 9552: ctx.singlestep_enabled |= CPU_BRANCH_STEP;
9553: if (unlikely(env->singlestep_enabled))
9554: ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
1.1 root 9555: #if defined (DO_SINGLE_STEP) && 0
9556: /* Single step trace mode */
9557: msr_se = 1;
9558: #endif
1.1.1.6 root 9559: num_insns = 0;
9560: max_insns = tb->cflags & CF_COUNT_MASK;
9561: if (max_insns == 0)
9562: max_insns = CF_COUNT_MASK;
9563:
9564: gen_icount_start();
1.1 root 9565: /* Set env in case of segfault during code fetch */
1.1.1.5 root 9566: while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
1.1.1.8 root 9567: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9568: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.6 root 9569: if (bp->pc == ctx.nip) {
9570: gen_debug_exception(ctxp);
1.1.1.3 root 9571: break;
9572: }
9573: }
9574: }
1.1.1.5 root 9575: if (unlikely(search_pc)) {
1.1 root 9576: j = gen_opc_ptr - gen_opc_buf;
9577: if (lj < j) {
9578: lj++;
9579: while (lj < j)
9580: gen_opc_instr_start[lj++] = 0;
9581: }
1.1.1.7 root 9582: gen_opc_pc[lj] = ctx.nip;
9583: gen_opc_instr_start[lj] = 1;
9584: gen_opc_icount[lj] = num_insns;
1.1 root 9585: }
1.1.1.6 root 9586: LOG_DISAS("----------------\n");
1.1.1.8 root 9587: LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
1.1.1.6 root 9588: ctx.nip, ctx.mem_idx, (int)msr_ir);
9589: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9590: gen_io_start();
9591: if (unlikely(ctx.le_mode)) {
1.1.1.5 root 9592: ctx.opcode = bswap32(ldl_code(ctx.nip));
9593: } else {
9594: ctx.opcode = ldl_code(ctx.nip);
1.1 root 9595: }
1.1.1.6 root 9596: LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
1.1 root 9597: ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
1.1.1.5 root 9598: opc3(ctx.opcode), little_endian ? "little" : "big");
1.1.1.8 root 9599: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
9600: tcg_gen_debug_insn_start(ctx.nip);
1.1 root 9601: ctx.nip += 4;
9602: table = env->opcodes;
1.1.1.6 root 9603: num_insns++;
1.1 root 9604: handler = table[opc1(ctx.opcode)];
9605: if (is_indirect_opcode(handler)) {
9606: table = ind_table(handler);
9607: handler = table[opc2(ctx.opcode)];
9608: if (is_indirect_opcode(handler)) {
9609: table = ind_table(handler);
9610: handler = table[opc3(ctx.opcode)];
9611: }
9612: }
9613: /* Is opcode *REALLY* valid ? */
1.1.1.5 root 9614: if (unlikely(handler->handler == &gen_invalid)) {
1.1.1.6 root 9615: if (qemu_log_enabled()) {
9616: qemu_log("invalid/unsupported opcode: "
1.1.1.8 root 9617: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
9618: opc1(ctx.opcode), opc2(ctx.opcode),
9619: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
1.1 root 9620: }
1.1.1.5 root 9621: } else {
1.1.1.12 root 9622: uint32_t inval;
9623:
9624: if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
9625: inval = handler->inval2;
9626: } else {
9627: inval = handler->inval1;
9628: }
9629:
9630: if (unlikely((ctx.opcode & inval) != 0)) {
1.1.1.6 root 9631: if (qemu_log_enabled()) {
9632: qemu_log("invalid bits: %08x for opcode: "
1.1.1.8 root 9633: "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
1.1.1.12 root 9634: ctx.opcode & inval, opc1(ctx.opcode),
1.1.1.8 root 9635: opc2(ctx.opcode), opc3(ctx.opcode),
9636: ctx.opcode, ctx.nip - 4);
1.1.1.5 root 9637: }
1.1.1.6 root 9638: gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
1.1 root 9639: break;
9640: }
9641: }
9642: (*(handler->handler))(&ctx);
1.1.1.5 root 9643: #if defined(DO_PPC_STATISTICS)
9644: handler->count++;
9645: #endif
1.1 root 9646: /* Check trace mode exceptions */
1.1.1.6 root 9647: if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
9648: (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
9649: ctx.exception != POWERPC_SYSCALL &&
9650: ctx.exception != POWERPC_EXCP_TRAP &&
9651: ctx.exception != POWERPC_EXCP_BRANCH)) {
9652: gen_exception(ctxp, POWERPC_EXCP_TRACE);
1.1.1.5 root 9653: } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
1.1.1.6 root 9654: (env->singlestep_enabled) ||
1.1.1.7 root 9655: singlestep ||
1.1.1.6 root 9656: num_insns >= max_insns)) {
1.1.1.5 root 9657: /* if we reach a page boundary or are single stepping, stop
9658: * generation
1.1 root 9659: */
9660: break;
1.1.1.5 root 9661: }
1.1 root 9662: }
1.1.1.6 root 9663: if (tb->cflags & CF_LAST_IO)
9664: gen_io_end();
1.1.1.5 root 9665: if (ctx.exception == POWERPC_EXCP_NONE) {
1.1.1.2 root 9666: gen_goto_tb(&ctx, 0, ctx.nip);
1.1.1.5 root 9667: } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
1.1.1.6 root 9668: if (unlikely(env->singlestep_enabled)) {
9669: gen_debug_exception(ctxp);
9670: }
1.1.1.5 root 9671: /* Generate the return instruction */
1.1.1.6 root 9672: tcg_gen_exit_tb(0);
1.1 root 9673: }
1.1.1.6 root 9674: gen_icount_end(tb, num_insns);
1.1 root 9675: *gen_opc_ptr = INDEX_op_end;
1.1.1.5 root 9676: if (unlikely(search_pc)) {
1.1 root 9677: j = gen_opc_ptr - gen_opc_buf;
9678: lj++;
9679: while (lj <= j)
9680: gen_opc_instr_start[lj++] = 0;
9681: } else {
9682: tb->size = ctx.nip - pc_start;
1.1.1.6 root 9683: tb->icount = num_insns;
1.1 root 9684: }
1.1.1.5 root 9685: #if defined(DEBUG_DISAS)
1.1.1.6 root 9686: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1.1.1.5 root 9687: int flags;
9688: flags = env->bfd_mach;
1.1.1.6 root 9689: flags |= ctx.le_mode << 16;
9690: qemu_log("IN: %s\n", lookup_symbol(pc_start));
9691: log_target_disas(pc_start, ctx.nip - pc_start, flags);
9692: qemu_log("\n");
1.1 root 9693: }
9694: #endif
9695: }
9696:
1.1.1.13! root 9697: void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
1.1.1.6 root 9698: {
9699: gen_intermediate_code_internal(env, tb, 0);
9700: }
9701:
1.1.1.13! root 9702: void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
1.1 root 9703: {
1.1.1.6 root 9704: gen_intermediate_code_internal(env, tb, 1);
1.1 root 9705: }
9706:
1.1.1.13! root 9707: void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
1.1 root 9708: {
1.1.1.6 root 9709: env->nip = gen_opc_pc[pc_pos];
1.1 root 9710: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.