|
|
1.1 root 1: /*
2: * PowerPC emulation for qemu: main translation routines.
1.1.1.5 ! root 3: *
! 4: * Copyright (c) 2003-2007 Jocelyn Mayer
1.1 root 5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20: #include <stdarg.h>
21: #include <stdlib.h>
22: #include <stdio.h>
23: #include <string.h>
24: #include <inttypes.h>
25:
26: #include "cpu.h"
27: #include "exec-all.h"
28: #include "disas.h"
29:
1.1.1.5 ! root 30: /* Include definitions for instructions classes and implementations flags */
1.1 root 31: //#define DO_SINGLE_STEP
32: //#define PPC_DEBUG_DISAS
1.1.1.5 ! root 33: //#define DEBUG_MEMORY_ACCESSES
! 34: //#define DO_PPC_STATISTICS
! 35: //#define OPTIMIZE_FPRF_UPDATE
1.1 root 36:
1.1.1.5 ! root 37: /*****************************************************************************/
! 38: /* Code translation helpers */
! 39: #if defined(USE_DIRECT_JUMP)
1.1.1.2 root 40: #define TBPARAM(x)
41: #else
42: #define TBPARAM(x) (long)(x)
43: #endif
44:
1.1 root 45: enum {
46: #define DEF(s, n, copy_size) INDEX_op_ ## s,
47: #include "opc.h"
48: #undef DEF
49: NB_OPS,
50: };
51:
52: static uint16_t *gen_opc_ptr;
53: static uint32_t *gen_opparam_ptr;
1.1.1.5 ! root 54: #if defined(OPTIMIZE_FPRF_UPDATE)
! 55: static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
! 56: static uint16_t **gen_fprf_ptr;
! 57: #endif
1.1 root 58:
59: #include "gen-op.h"
60:
1.1.1.5 ! root 61: static always_inline void gen_set_T0 (target_ulong val)
! 62: {
! 63: #if defined(TARGET_PPC64)
! 64: if (val >> 32)
! 65: gen_op_set_T0_64(val >> 32, val);
! 66: else
! 67: #endif
! 68: gen_op_set_T0(val);
! 69: }
! 70:
! 71: static always_inline void gen_set_T1 (target_ulong val)
! 72: {
! 73: #if defined(TARGET_PPC64)
! 74: if (val >> 32)
! 75: gen_op_set_T1_64(val >> 32, val);
! 76: else
! 77: #endif
! 78: gen_op_set_T1(val);
! 79: }
! 80:
! 81: #define GEN8(func, NAME) \
1.1 root 82: static GenOpFunc *NAME ## _table [8] = { \
83: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
84: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
85: }; \
1.1.1.5 ! root 86: static always_inline void func (int n) \
1.1 root 87: { \
88: NAME ## _table[n](); \
89: }
90:
91: #define GEN16(func, NAME) \
92: static GenOpFunc *NAME ## _table [16] = { \
93: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
94: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
95: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
96: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
97: }; \
1.1.1.5 ! root 98: static always_inline void func (int n) \
1.1 root 99: { \
100: NAME ## _table[n](); \
101: }
102:
1.1.1.5 ! root 103: #define GEN32(func, NAME) \
1.1 root 104: static GenOpFunc *NAME ## _table [32] = { \
105: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
106: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
107: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
108: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
109: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
110: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
111: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
112: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
113: }; \
1.1.1.5 ! root 114: static always_inline void func (int n) \
1.1 root 115: { \
116: NAME ## _table[n](); \
117: }
118:
119: /* Condition register moves */
120: GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
121: GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
122: GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
1.1.1.5 ! root 123: #if 0 // Unused
1.1 root 124: GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
1.1.1.5 ! root 125: #endif
1.1 root 126:
127: /* General purpose registers moves */
128: GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
129: GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
130: GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
131:
132: GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
133: GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
1.1.1.5 ! root 134: #if 0 // unused
1.1 root 135: GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
1.1.1.5 ! root 136: #endif
1.1 root 137:
138: /* floating point registers moves */
139: GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
140: GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
141: GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
142: GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
143: GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
1.1.1.5 ! root 144: #if 0 // unused
1.1 root 145: GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
1.1.1.5 ! root 146: #endif
1.1 root 147:
148: /* internal defines */
149: typedef struct DisasContext {
150: struct TranslationBlock *tb;
151: target_ulong nip;
152: uint32_t opcode;
153: uint32_t exception;
154: /* Routine used to access memory */
155: int mem_idx;
156: /* Translation flags */
157: #if !defined(CONFIG_USER_ONLY)
158: int supervisor;
159: #endif
1.1.1.5 ! root 160: #if defined(TARGET_PPC64)
! 161: int sf_mode;
! 162: #endif
1.1 root 163: int fpu_enabled;
1.1.1.5 ! root 164: int altivec_enabled;
! 165: int spe_enabled;
1.1 root 166: ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
1.1.1.3 root 167: int singlestep_enabled;
1.1.1.5 ! root 168: int dcache_line_size;
1.1 root 169: } DisasContext;
170:
171: struct opc_handler_t {
172: /* invalid bits */
173: uint32_t inval;
174: /* instruction type */
1.1.1.5 ! root 175: uint64_t type;
1.1 root 176: /* handler */
177: void (*handler)(DisasContext *ctx);
1.1.1.5 ! root 178: #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
! 179: const unsigned char *oname;
! 180: #endif
! 181: #if defined(DO_PPC_STATISTICS)
! 182: uint64_t count;
! 183: #endif
1.1 root 184: };
185:
1.1.1.5 ! root 186: static always_inline void gen_set_Rc0 (DisasContext *ctx)
! 187: {
! 188: #if defined(TARGET_PPC64)
! 189: if (ctx->sf_mode)
! 190: gen_op_cmpi_64(0);
! 191: else
! 192: #endif
! 193: gen_op_cmpi(0);
! 194: gen_op_set_Rc0();
! 195: }
! 196:
! 197: static always_inline void gen_reset_fpstatus (void)
! 198: {
! 199: #ifdef CONFIG_SOFTFLOAT
! 200: gen_op_reset_fpstatus();
! 201: #endif
! 202: }
! 203:
! 204: static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
! 205: {
! 206: if (set_fprf != 0) {
! 207: /* This case might be optimized later */
! 208: #if defined(OPTIMIZE_FPRF_UPDATE)
! 209: *gen_fprf_ptr++ = gen_opc_ptr;
! 210: #endif
! 211: gen_op_compute_fprf(1);
! 212: if (unlikely(set_rc))
! 213: gen_op_store_T0_crf(1);
! 214: gen_op_float_check_status();
! 215: } else if (unlikely(set_rc)) {
! 216: /* We always need to compute fpcc */
! 217: gen_op_compute_fprf(0);
! 218: gen_op_store_T0_crf(1);
! 219: if (set_fprf)
! 220: gen_op_float_check_status();
! 221: }
! 222: }
! 223:
! 224: static always_inline void gen_optimize_fprf (void)
! 225: {
! 226: #if defined(OPTIMIZE_FPRF_UPDATE)
! 227: uint16_t **ptr;
! 228:
! 229: for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
! 230: *ptr = INDEX_op_nop1;
! 231: gen_fprf_ptr = gen_fprf_buf;
! 232: #endif
! 233: }
! 234:
! 235: static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
! 236: {
! 237: #if defined(TARGET_PPC64)
! 238: if (ctx->sf_mode)
! 239: gen_op_update_nip_64(nip >> 32, nip);
! 240: else
! 241: #endif
! 242: gen_op_update_nip(nip);
! 243: }
! 244:
! 245: #define GEN_EXCP(ctx, excp, error) \
1.1 root 246: do { \
1.1.1.5 ! root 247: if ((ctx)->exception == POWERPC_EXCP_NONE) { \
! 248: gen_update_nip(ctx, (ctx)->nip); \
1.1 root 249: } \
250: gen_op_raise_exception_err((excp), (error)); \
251: ctx->exception = (excp); \
252: } while (0)
253:
1.1.1.5 ! root 254: #define GEN_EXCP_INVAL(ctx) \
! 255: GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
! 256: POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
! 257:
! 258: #define GEN_EXCP_PRIVOPC(ctx) \
! 259: GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
! 260: POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
! 261:
! 262: #define GEN_EXCP_PRIVREG(ctx) \
! 263: GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
! 264: POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
! 265:
! 266: #define GEN_EXCP_NO_FP(ctx) \
! 267: GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
1.1 root 268:
1.1.1.5 ! root 269: #define GEN_EXCP_NO_AP(ctx) \
! 270: GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
1.1 root 271:
1.1.1.5 ! root 272: #define GEN_EXCP_NO_VR(ctx) \
! 273: GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
1.1 root 274:
1.1.1.2 root 275: /* Stop translation */
1.1.1.5 ! root 276: static always_inline void GEN_STOP (DisasContext *ctx)
1.1 root 277: {
1.1.1.5 ! root 278: gen_update_nip(ctx, ctx->nip);
! 279: ctx->exception = POWERPC_EXCP_STOP;
1.1 root 280: }
281:
1.1.1.2 root 282: /* No need to update nip here, as execution flow will change */
1.1.1.5 ! root 283: static always_inline void GEN_SYNC (DisasContext *ctx)
1.1 root 284: {
1.1.1.5 ! root 285: ctx->exception = POWERPC_EXCP_SYNC;
1.1 root 286: }
287:
288: #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
289: static void gen_##name (DisasContext *ctx); \
290: GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
291: static void gen_##name (DisasContext *ctx)
292:
1.1.1.5 ! root 293: #define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
! 294: static void gen_##name (DisasContext *ctx); \
! 295: GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type); \
! 296: static void gen_##name (DisasContext *ctx)
! 297:
1.1 root 298: typedef struct opcode_t {
299: unsigned char opc1, opc2, opc3;
300: #if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */
301: unsigned char pad[5];
302: #else
303: unsigned char pad[1];
304: #endif
305: opc_handler_t handler;
306: const unsigned char *oname;
307: } opcode_t;
308:
1.1.1.5 ! root 309: /*****************************************************************************/
1.1 root 310: /*** Instruction decoding ***/
311: #define EXTRACT_HELPER(name, shift, nb) \
1.1.1.5 ! root 312: static always_inline uint32_t name (uint32_t opcode) \
1.1 root 313: { \
314: return (opcode >> (shift)) & ((1 << (nb)) - 1); \
315: }
316:
317: #define EXTRACT_SHELPER(name, shift, nb) \
1.1.1.5 ! root 318: static always_inline int32_t name (uint32_t opcode) \
1.1 root 319: { \
320: return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
321: }
322:
323: /* Opcode part 1 */
324: EXTRACT_HELPER(opc1, 26, 6);
325: /* Opcode part 2 */
326: EXTRACT_HELPER(opc2, 1, 5);
327: /* Opcode part 3 */
328: EXTRACT_HELPER(opc3, 6, 5);
329: /* Update Cr0 flags */
330: EXTRACT_HELPER(Rc, 0, 1);
331: /* Destination */
332: EXTRACT_HELPER(rD, 21, 5);
333: /* Source */
334: EXTRACT_HELPER(rS, 21, 5);
335: /* First operand */
336: EXTRACT_HELPER(rA, 16, 5);
337: /* Second operand */
338: EXTRACT_HELPER(rB, 11, 5);
339: /* Third operand */
340: EXTRACT_HELPER(rC, 6, 5);
341: /*** Get CRn ***/
342: EXTRACT_HELPER(crfD, 23, 3);
343: EXTRACT_HELPER(crfS, 18, 3);
344: EXTRACT_HELPER(crbD, 21, 5);
345: EXTRACT_HELPER(crbA, 16, 5);
346: EXTRACT_HELPER(crbB, 11, 5);
347: /* SPR / TBL */
348: EXTRACT_HELPER(_SPR, 11, 10);
1.1.1.5 ! root 349: static always_inline uint32_t SPR (uint32_t opcode)
1.1 root 350: {
351: uint32_t sprn = _SPR(opcode);
352:
353: return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
354: }
355: /*** Get constants ***/
356: EXTRACT_HELPER(IMM, 12, 8);
357: /* 16 bits signed immediate value */
358: EXTRACT_SHELPER(SIMM, 0, 16);
359: /* 16 bits unsigned immediate value */
360: EXTRACT_HELPER(UIMM, 0, 16);
361: /* Bit count */
362: EXTRACT_HELPER(NB, 11, 5);
363: /* Shift count */
364: EXTRACT_HELPER(SH, 11, 5);
365: /* Mask start */
366: EXTRACT_HELPER(MB, 6, 5);
367: /* Mask end */
368: EXTRACT_HELPER(ME, 1, 5);
369: /* Trap operand */
370: EXTRACT_HELPER(TO, 21, 5);
371:
372: EXTRACT_HELPER(CRM, 12, 8);
373: EXTRACT_HELPER(FM, 17, 8);
374: EXTRACT_HELPER(SR, 16, 4);
375: EXTRACT_HELPER(FPIMM, 20, 4);
376:
377: /*** Jump target decoding ***/
378: /* Displacement */
379: EXTRACT_SHELPER(d, 0, 16);
380: /* Immediate address */
1.1.1.5 ! root 381: static always_inline target_ulong LI (uint32_t opcode)
1.1 root 382: {
383: return (opcode >> 0) & 0x03FFFFFC;
384: }
385:
1.1.1.5 ! root 386: static always_inline uint32_t BD (uint32_t opcode)
1.1 root 387: {
388: return (opcode >> 0) & 0xFFFC;
389: }
390:
391: EXTRACT_HELPER(BO, 21, 5);
392: EXTRACT_HELPER(BI, 16, 5);
393: /* Absolute/relative address */
394: EXTRACT_HELPER(AA, 1, 1);
395: /* Link */
396: EXTRACT_HELPER(LK, 0, 1);
397:
398: /* Create a mask between <start> and <end> bits */
1.1.1.5 ! root 399: static always_inline target_ulong MASK (uint32_t start, uint32_t end)
1.1 root 400: {
1.1.1.5 ! root 401: target_ulong ret;
1.1 root 402:
1.1.1.5 ! root 403: #if defined(TARGET_PPC64)
! 404: if (likely(start == 0)) {
! 405: ret = UINT64_MAX << (63 - end);
! 406: } else if (likely(end == 63)) {
! 407: ret = UINT64_MAX >> start;
! 408: }
! 409: #else
! 410: if (likely(start == 0)) {
! 411: ret = UINT32_MAX << (31 - end);
! 412: } else if (likely(end == 31)) {
! 413: ret = UINT32_MAX >> start;
! 414: }
! 415: #endif
! 416: else {
! 417: ret = (((target_ulong)(-1ULL)) >> (start)) ^
! 418: (((target_ulong)(-1ULL) >> (end)) >> 1);
! 419: if (unlikely(start > end))
! 420: return ~ret;
! 421: }
1.1 root 422:
423: return ret;
424: }
425:
1.1.1.5 ! root 426: /*****************************************************************************/
! 427: /* PowerPC Instructions types definitions */
! 428: enum {
! 429: PPC_NONE = 0x0000000000000000ULL,
! 430: /* PowerPC base instructions set */
! 431: PPC_INSNS_BASE = 0x0000000000000001ULL,
! 432: /* integer operations instructions */
! 433: #define PPC_INTEGER PPC_INSNS_BASE
! 434: /* flow control instructions */
! 435: #define PPC_FLOW PPC_INSNS_BASE
! 436: /* virtual memory instructions */
! 437: #define PPC_MEM PPC_INSNS_BASE
! 438: /* ld/st with reservation instructions */
! 439: #define PPC_RES PPC_INSNS_BASE
! 440: /* spr/msr access instructions */
! 441: #define PPC_MISC PPC_INSNS_BASE
! 442: /* Deprecated instruction sets */
! 443: /* Original POWER instruction set */
! 444: PPC_POWER = 0x0000000000000002ULL,
! 445: /* POWER2 instruction set extension */
! 446: PPC_POWER2 = 0x0000000000000004ULL,
! 447: /* Power RTC support */
! 448: PPC_POWER_RTC = 0x0000000000000008ULL,
! 449: /* Power-to-PowerPC bridge (601) */
! 450: PPC_POWER_BR = 0x0000000000000010ULL,
! 451: /* 64 bits PowerPC instruction set */
! 452: PPC_64B = 0x0000000000000020ULL,
! 453: /* New 64 bits extensions (PowerPC 2.0x) */
! 454: PPC_64BX = 0x0000000000000040ULL,
! 455: /* 64 bits hypervisor extensions */
! 456: PPC_64H = 0x0000000000000080ULL,
! 457: /* New wait instruction (PowerPC 2.0x) */
! 458: PPC_WAIT = 0x0000000000000100ULL,
! 459: /* Time base mftb instruction */
! 460: PPC_MFTB = 0x0000000000000200ULL,
! 461:
! 462: /* Fixed-point unit extensions */
! 463: /* PowerPC 602 specific */
! 464: PPC_602_SPEC = 0x0000000000000400ULL,
! 465: /* isel instruction */
! 466: PPC_ISEL = 0x0000000000000800ULL,
! 467: /* popcntb instruction */
! 468: PPC_POPCNTB = 0x0000000000001000ULL,
! 469: /* string load / store */
! 470: PPC_STRING = 0x0000000000002000ULL,
! 471:
! 472: /* Floating-point unit extensions */
! 473: /* Optional floating point instructions */
! 474: PPC_FLOAT = 0x0000000000010000ULL,
! 475: /* New floating-point extensions (PowerPC 2.0x) */
! 476: PPC_FLOAT_EXT = 0x0000000000020000ULL,
! 477: PPC_FLOAT_FSQRT = 0x0000000000040000ULL,
! 478: PPC_FLOAT_FRES = 0x0000000000080000ULL,
! 479: PPC_FLOAT_FRSQRTE = 0x0000000000100000ULL,
! 480: PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
! 481: PPC_FLOAT_FSEL = 0x0000000000400000ULL,
! 482: PPC_FLOAT_STFIWX = 0x0000000000800000ULL,
! 483:
! 484: /* Vector/SIMD extensions */
! 485: /* Altivec support */
! 486: PPC_ALTIVEC = 0x0000000001000000ULL,
! 487: /* PowerPC 2.03 SPE extension */
! 488: PPC_SPE = 0x0000000002000000ULL,
! 489: /* PowerPC 2.03 SPE floating-point extension */
! 490: PPC_SPEFPU = 0x0000000004000000ULL,
! 491:
! 492: /* Optional memory control instructions */
! 493: PPC_MEM_TLBIA = 0x0000000010000000ULL,
! 494: PPC_MEM_TLBIE = 0x0000000020000000ULL,
! 495: PPC_MEM_TLBSYNC = 0x0000000040000000ULL,
! 496: /* sync instruction */
! 497: PPC_MEM_SYNC = 0x0000000080000000ULL,
! 498: /* eieio instruction */
! 499: PPC_MEM_EIEIO = 0x0000000100000000ULL,
! 500:
! 501: /* Cache control instructions */
! 502: PPC_CACHE = 0x0000000200000000ULL,
! 503: /* icbi instruction */
! 504: PPC_CACHE_ICBI = 0x0000000400000000ULL,
! 505: /* dcbz instruction with fixed cache line size */
! 506: PPC_CACHE_DCBZ = 0x0000000800000000ULL,
! 507: /* dcbz instruction with tunable cache line size */
! 508: PPC_CACHE_DCBZT = 0x0000001000000000ULL,
! 509: /* dcba instruction */
! 510: PPC_CACHE_DCBA = 0x0000002000000000ULL,
! 511: /* Freescale cache locking instructions */
! 512: PPC_CACHE_LOCK = 0x0000004000000000ULL,
! 513:
! 514: /* MMU related extensions */
! 515: /* external control instructions */
! 516: PPC_EXTERN = 0x0000010000000000ULL,
! 517: /* segment register access instructions */
! 518: PPC_SEGMENT = 0x0000020000000000ULL,
! 519: /* PowerPC 6xx TLB management instructions */
! 520: PPC_6xx_TLB = 0x0000040000000000ULL,
! 521: /* PowerPC 74xx TLB management instructions */
! 522: PPC_74xx_TLB = 0x0000080000000000ULL,
! 523: /* PowerPC 40x TLB management instructions */
! 524: PPC_40x_TLB = 0x0000100000000000ULL,
! 525: /* segment register access instructions for PowerPC 64 "bridge" */
! 526: PPC_SEGMENT_64B = 0x0000200000000000ULL,
! 527: /* SLB management */
! 528: PPC_SLBI = 0x0000400000000000ULL,
! 529:
! 530: /* Embedded PowerPC dedicated instructions */
! 531: PPC_WRTEE = 0x0001000000000000ULL,
! 532: /* PowerPC 40x exception model */
! 533: PPC_40x_EXCP = 0x0002000000000000ULL,
! 534: /* PowerPC 405 Mac instructions */
! 535: PPC_405_MAC = 0x0004000000000000ULL,
! 536: /* PowerPC 440 specific instructions */
! 537: PPC_440_SPEC = 0x0008000000000000ULL,
! 538: /* BookE (embedded) PowerPC specification */
! 539: PPC_BOOKE = 0x0010000000000000ULL,
! 540: /* mfapidi instruction */
! 541: PPC_MFAPIDI = 0x0020000000000000ULL,
! 542: /* tlbiva instruction */
! 543: PPC_TLBIVA = 0x0040000000000000ULL,
! 544: /* tlbivax instruction */
! 545: PPC_TLBIVAX = 0x0080000000000000ULL,
! 546: /* PowerPC 4xx dedicated instructions */
! 547: PPC_4xx_COMMON = 0x0100000000000000ULL,
! 548: /* PowerPC 40x ibct instructions */
! 549: PPC_40x_ICBT = 0x0200000000000000ULL,
! 550: /* rfmci is not implemented in all BookE PowerPC */
! 551: PPC_RFMCI = 0x0400000000000000ULL,
! 552: /* rfdi instruction */
! 553: PPC_RFDI = 0x0800000000000000ULL,
! 554: /* DCR accesses */
! 555: PPC_DCR = 0x1000000000000000ULL,
! 556: /* DCR extended accesse */
! 557: PPC_DCRX = 0x2000000000000000ULL,
! 558: /* user-mode DCR access, implemented in PowerPC 460 */
! 559: PPC_DCRUX = 0x4000000000000000ULL,
! 560: };
! 561:
! 562: /*****************************************************************************/
! 563: /* PowerPC instructions table */
1.1 root 564: #if HOST_LONG_BITS == 64
565: #define OPC_ALIGN 8
566: #else
567: #define OPC_ALIGN 4
568: #endif
569: #if defined(__APPLE__)
1.1.1.5 ! root 570: #define OPCODES_SECTION \
1.1 root 571: __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
572: #else
1.1.1.5 ! root 573: #define OPCODES_SECTION \
1.1 root 574: __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
575: #endif
576:
1.1.1.5 ! root 577: #if defined(DO_PPC_STATISTICS)
! 578: #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
! 579: OPCODES_SECTION opcode_t opc_##name = { \
! 580: .opc1 = op1, \
! 581: .opc2 = op2, \
! 582: .opc3 = op3, \
! 583: .pad = { 0, }, \
! 584: .handler = { \
! 585: .inval = invl, \
! 586: .type = _typ, \
! 587: .handler = &gen_##name, \
! 588: .oname = stringify(name), \
! 589: }, \
! 590: .oname = stringify(name), \
! 591: }
! 592: #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
! 593: OPCODES_SECTION opcode_t opc_##name = { \
! 594: .opc1 = op1, \
! 595: .opc2 = op2, \
! 596: .opc3 = op3, \
! 597: .pad = { 0, }, \
! 598: .handler = { \
! 599: .inval = invl, \
! 600: .type = _typ, \
! 601: .handler = &gen_##name, \
! 602: .oname = onam, \
! 603: }, \
! 604: .oname = onam, \
! 605: }
! 606: #else
1.1 root 607: #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
608: OPCODES_SECTION opcode_t opc_##name = { \
609: .opc1 = op1, \
610: .opc2 = op2, \
611: .opc3 = op3, \
612: .pad = { 0, }, \
613: .handler = { \
614: .inval = invl, \
615: .type = _typ, \
616: .handler = &gen_##name, \
617: }, \
618: .oname = stringify(name), \
619: }
1.1.1.5 ! root 620: #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
! 621: OPCODES_SECTION opcode_t opc_##name = { \
! 622: .opc1 = op1, \
! 623: .opc2 = op2, \
! 624: .opc3 = op3, \
! 625: .pad = { 0, }, \
! 626: .handler = { \
! 627: .inval = invl, \
! 628: .type = _typ, \
! 629: .handler = &gen_##name, \
! 630: }, \
! 631: .oname = onam, \
! 632: }
! 633: #endif
1.1 root 634:
635: #define GEN_OPCODE_MARK(name) \
636: OPCODES_SECTION opcode_t opc_##name = { \
637: .opc1 = 0xFF, \
638: .opc2 = 0xFF, \
639: .opc3 = 0xFF, \
640: .pad = { 0, }, \
641: .handler = { \
642: .inval = 0x00000000, \
643: .type = 0x00, \
644: .handler = NULL, \
645: }, \
646: .oname = stringify(name), \
647: }
648:
649: /* Start opcode list */
650: GEN_OPCODE_MARK(start);
651:
652: /* Invalid instruction */
653: GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
654: {
1.1.1.5 ! root 655: GEN_EXCP_INVAL(ctx);
1.1 root 656: }
657:
658: static opc_handler_t invalid_handler = {
659: .inval = 0xFFFFFFFF,
660: .type = PPC_NONE,
661: .handler = gen_invalid,
662: };
663:
664: /*** Integer arithmetic ***/
1.1.1.5 ! root 665: #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type) \
! 666: GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
1.1 root 667: { \
668: gen_op_load_gpr_T0(rA(ctx->opcode)); \
669: gen_op_load_gpr_T1(rB(ctx->opcode)); \
670: gen_op_##name(); \
671: gen_op_store_T0_gpr(rD(ctx->opcode)); \
1.1.1.5 ! root 672: if (unlikely(Rc(ctx->opcode) != 0)) \
! 673: gen_set_Rc0(ctx); \
1.1 root 674: }
675:
1.1.1.5 ! root 676: #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type) \
! 677: GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
1.1 root 678: { \
679: gen_op_load_gpr_T0(rA(ctx->opcode)); \
680: gen_op_load_gpr_T1(rB(ctx->opcode)); \
681: gen_op_##name(); \
682: gen_op_store_T0_gpr(rD(ctx->opcode)); \
1.1.1.5 ! root 683: if (unlikely(Rc(ctx->opcode) != 0)) \
! 684: gen_set_Rc0(ctx); \
1.1 root 685: }
686:
1.1.1.5 ! root 687: #define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
! 688: GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
1.1 root 689: { \
690: gen_op_load_gpr_T0(rA(ctx->opcode)); \
691: gen_op_##name(); \
692: gen_op_store_T0_gpr(rD(ctx->opcode)); \
1.1.1.5 ! root 693: if (unlikely(Rc(ctx->opcode) != 0)) \
! 694: gen_set_Rc0(ctx); \
1.1 root 695: }
1.1.1.5 ! root 696: #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type) \
! 697: GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
1.1 root 698: { \
699: gen_op_load_gpr_T0(rA(ctx->opcode)); \
700: gen_op_##name(); \
701: gen_op_store_T0_gpr(rD(ctx->opcode)); \
1.1.1.5 ! root 702: if (unlikely(Rc(ctx->opcode) != 0)) \
! 703: gen_set_Rc0(ctx); \
! 704: }
! 705:
! 706: /* Two operands arithmetic functions */
! 707: #define GEN_INT_ARITH2(name, opc1, opc2, opc3, type) \
! 708: __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type) \
! 709: __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
! 710:
! 711: /* Two operands arithmetic functions with no overflow allowed */
! 712: #define GEN_INT_ARITHN(name, opc1, opc2, opc3, type) \
! 713: __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)
! 714:
! 715: /* One operand arithmetic functions */
! 716: #define GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
! 717: __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
! 718: __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)
! 719:
! 720: #if defined(TARGET_PPC64)
! 721: #define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type) \
! 722: GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
! 723: { \
! 724: gen_op_load_gpr_T0(rA(ctx->opcode)); \
! 725: gen_op_load_gpr_T1(rB(ctx->opcode)); \
! 726: if (ctx->sf_mode) \
! 727: gen_op_##name##_64(); \
! 728: else \
! 729: gen_op_##name(); \
! 730: gen_op_store_T0_gpr(rD(ctx->opcode)); \
! 731: if (unlikely(Rc(ctx->opcode) != 0)) \
! 732: gen_set_Rc0(ctx); \
! 733: }
! 734:
! 735: #define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type) \
! 736: GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
! 737: { \
! 738: gen_op_load_gpr_T0(rA(ctx->opcode)); \
! 739: gen_op_load_gpr_T1(rB(ctx->opcode)); \
! 740: if (ctx->sf_mode) \
! 741: gen_op_##name##_64(); \
! 742: else \
! 743: gen_op_##name(); \
! 744: gen_op_store_T0_gpr(rD(ctx->opcode)); \
! 745: if (unlikely(Rc(ctx->opcode) != 0)) \
! 746: gen_set_Rc0(ctx); \
! 747: }
! 748:
! 749: #define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
! 750: GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
! 751: { \
! 752: gen_op_load_gpr_T0(rA(ctx->opcode)); \
! 753: if (ctx->sf_mode) \
! 754: gen_op_##name##_64(); \
! 755: else \
! 756: gen_op_##name(); \
! 757: gen_op_store_T0_gpr(rD(ctx->opcode)); \
! 758: if (unlikely(Rc(ctx->opcode) != 0)) \
! 759: gen_set_Rc0(ctx); \
! 760: }
! 761: #define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type) \
! 762: GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
! 763: { \
! 764: gen_op_load_gpr_T0(rA(ctx->opcode)); \
! 765: if (ctx->sf_mode) \
! 766: gen_op_##name##_64(); \
! 767: else \
! 768: gen_op_##name(); \
! 769: gen_op_store_T0_gpr(rD(ctx->opcode)); \
! 770: if (unlikely(Rc(ctx->opcode) != 0)) \
! 771: gen_set_Rc0(ctx); \
1.1 root 772: }
773:
774: /* Two operands arithmetic functions */
1.1.1.5 ! root 775: #define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type) \
! 776: __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type) \
! 777: __GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
1.1 root 778:
779: /* Two operands arithmetic functions with no overflow allowed */
1.1.1.5 ! root 780: #define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type) \
! 781: __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
1.1 root 782:
783: /* One operand arithmetic functions */
1.1.1.5 ! root 784: #define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
! 785: __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
! 786: __GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
! 787: #else
! 788: #define GEN_INT_ARITH2_64 GEN_INT_ARITH2
! 789: #define GEN_INT_ARITHN_64 GEN_INT_ARITHN
! 790: #define GEN_INT_ARITH1_64 GEN_INT_ARITH1
! 791: #endif
1.1 root 792:
793: /* add add. addo addo. */
1.1.1.5 ! root 794: static always_inline void gen_op_addo (void)
! 795: {
! 796: gen_op_move_T2_T0();
! 797: gen_op_add();
! 798: gen_op_check_addo();
! 799: }
! 800: #if defined(TARGET_PPC64)
! 801: #define gen_op_add_64 gen_op_add
! 802: static always_inline void gen_op_addo_64 (void)
! 803: {
! 804: gen_op_move_T2_T0();
! 805: gen_op_add();
! 806: gen_op_check_addo_64();
! 807: }
! 808: #endif
! 809: GEN_INT_ARITH2_64 (add, 0x1F, 0x0A, 0x08, PPC_INTEGER);
1.1 root 810: /* addc addc. addco addco. */
1.1.1.5 ! root 811: static always_inline void gen_op_addc (void)
! 812: {
! 813: gen_op_move_T2_T0();
! 814: gen_op_add();
! 815: gen_op_check_addc();
! 816: }
! 817: static always_inline void gen_op_addco (void)
! 818: {
! 819: gen_op_move_T2_T0();
! 820: gen_op_add();
! 821: gen_op_check_addc();
! 822: gen_op_check_addo();
! 823: }
! 824: #if defined(TARGET_PPC64)
! 825: static always_inline void gen_op_addc_64 (void)
! 826: {
! 827: gen_op_move_T2_T0();
! 828: gen_op_add();
! 829: gen_op_check_addc_64();
! 830: }
! 831: static always_inline void gen_op_addco_64 (void)
! 832: {
! 833: gen_op_move_T2_T0();
! 834: gen_op_add();
! 835: gen_op_check_addc_64();
! 836: gen_op_check_addo_64();
! 837: }
! 838: #endif
! 839: GEN_INT_ARITH2_64 (addc, 0x1F, 0x0A, 0x00, PPC_INTEGER);
1.1 root 840: /* adde adde. addeo addeo. */
1.1.1.5 ! root 841: static always_inline void gen_op_addeo (void)
! 842: {
! 843: gen_op_move_T2_T0();
! 844: gen_op_adde();
! 845: gen_op_check_addo();
! 846: }
! 847: #if defined(TARGET_PPC64)
! 848: static always_inline void gen_op_addeo_64 (void)
! 849: {
! 850: gen_op_move_T2_T0();
! 851: gen_op_adde_64();
! 852: gen_op_check_addo_64();
! 853: }
! 854: #endif
! 855: GEN_INT_ARITH2_64 (adde, 0x1F, 0x0A, 0x04, PPC_INTEGER);
1.1 root 856: /* addme addme. addmeo addmeo. */
1.1.1.5 ! root 857: static always_inline void gen_op_addme (void)
! 858: {
! 859: gen_op_move_T1_T0();
! 860: gen_op_add_me();
! 861: }
! 862: #if defined(TARGET_PPC64)
! 863: static always_inline void gen_op_addme_64 (void)
! 864: {
! 865: gen_op_move_T1_T0();
! 866: gen_op_add_me_64();
! 867: }
! 868: #endif
! 869: GEN_INT_ARITH1_64 (addme, 0x1F, 0x0A, 0x07, PPC_INTEGER);
1.1 root 870: /* addze addze. addzeo addzeo. */
1.1.1.5 ! root 871: static always_inline void gen_op_addze (void)
! 872: {
! 873: gen_op_move_T2_T0();
! 874: gen_op_add_ze();
! 875: gen_op_check_addc();
! 876: }
! 877: static always_inline void gen_op_addzeo (void)
! 878: {
! 879: gen_op_move_T2_T0();
! 880: gen_op_add_ze();
! 881: gen_op_check_addc();
! 882: gen_op_check_addo();
! 883: }
! 884: #if defined(TARGET_PPC64)
! 885: static always_inline void gen_op_addze_64 (void)
! 886: {
! 887: gen_op_move_T2_T0();
! 888: gen_op_add_ze();
! 889: gen_op_check_addc_64();
! 890: }
! 891: static always_inline void gen_op_addzeo_64 (void)
! 892: {
! 893: gen_op_move_T2_T0();
! 894: gen_op_add_ze();
! 895: gen_op_check_addc_64();
! 896: gen_op_check_addo_64();
! 897: }
! 898: #endif
! 899: GEN_INT_ARITH1_64 (addze, 0x1F, 0x0A, 0x06, PPC_INTEGER);
1.1 root 900: /* divw divw. divwo divwo. */
1.1.1.5 ! root 901: GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F, PPC_INTEGER);
1.1 root 902: /* divwu divwu. divwuo divwuo. */
1.1.1.5 ! root 903: GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E, PPC_INTEGER);
1.1 root 904: /* mulhw mulhw. */
1.1.1.5 ! root 905: GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02, PPC_INTEGER);
1.1 root 906: /* mulhwu mulhwu. */
1.1.1.5 ! root 907: GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
1.1 root 908: /* mullw mullw. mullwo mullwo. */
1.1.1.5 ! root 909: GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07, PPC_INTEGER);
1.1 root 910: /* neg neg. nego nego. */
1.1.1.5 ! root 911: GEN_INT_ARITH1_64 (neg, 0x1F, 0x08, 0x03, PPC_INTEGER);
1.1 root 912: /* subf subf. subfo subfo. */
1.1.1.5 ! root 913: static always_inline void gen_op_subfo (void)
! 914: {
! 915: gen_op_moven_T2_T0();
! 916: gen_op_subf();
! 917: gen_op_check_addo();
! 918: }
! 919: #if defined(TARGET_PPC64)
! 920: #define gen_op_subf_64 gen_op_subf
! 921: static always_inline void gen_op_subfo_64 (void)
! 922: {
! 923: gen_op_moven_T2_T0();
! 924: gen_op_subf();
! 925: gen_op_check_addo_64();
! 926: }
! 927: #endif
! 928: GEN_INT_ARITH2_64 (subf, 0x1F, 0x08, 0x01, PPC_INTEGER);
1.1 root 929: /* subfc subfc. subfco subfco. */
1.1.1.5 ! root 930: static always_inline void gen_op_subfc (void)
! 931: {
! 932: gen_op_subf();
! 933: gen_op_check_subfc();
! 934: }
! 935: static always_inline void gen_op_subfco (void)
! 936: {
! 937: gen_op_moven_T2_T0();
! 938: gen_op_subf();
! 939: gen_op_check_subfc();
! 940: gen_op_check_addo();
! 941: }
! 942: #if defined(TARGET_PPC64)
! 943: static always_inline void gen_op_subfc_64 (void)
! 944: {
! 945: gen_op_subf();
! 946: gen_op_check_subfc_64();
! 947: }
! 948: static always_inline void gen_op_subfco_64 (void)
! 949: {
! 950: gen_op_moven_T2_T0();
! 951: gen_op_subf();
! 952: gen_op_check_subfc_64();
! 953: gen_op_check_addo_64();
! 954: }
! 955: #endif
! 956: GEN_INT_ARITH2_64 (subfc, 0x1F, 0x08, 0x00, PPC_INTEGER);
1.1 root 957: /* subfe subfe. subfeo subfeo. */
1.1.1.5 ! root 958: static always_inline void gen_op_subfeo (void)
! 959: {
! 960: gen_op_moven_T2_T0();
! 961: gen_op_subfe();
! 962: gen_op_check_addo();
! 963: }
! 964: #if defined(TARGET_PPC64)
! 965: #define gen_op_subfe_64 gen_op_subfe
! 966: static always_inline void gen_op_subfeo_64 (void)
! 967: {
! 968: gen_op_moven_T2_T0();
! 969: gen_op_subfe_64();
! 970: gen_op_check_addo_64();
! 971: }
! 972: #endif
! 973: GEN_INT_ARITH2_64 (subfe, 0x1F, 0x08, 0x04, PPC_INTEGER);
1.1 root 974: /* subfme subfme. subfmeo subfmeo. */
1.1.1.5 ! root 975: GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
1.1 root 976: /* subfze subfze. subfzeo subfzeo. */
1.1.1.5 ! root 977: GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
1.1 root 978: /* addi */
979: GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
980: {
1.1.1.5 ! root 981: target_long simm = SIMM(ctx->opcode);
1.1 root 982:
983: if (rA(ctx->opcode) == 0) {
1.1.1.5 ! root 984: /* li case */
! 985: gen_set_T0(simm);
1.1 root 986: } else {
987: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 988: if (likely(simm != 0))
! 989: gen_op_addi(simm);
1.1 root 990: }
991: gen_op_store_T0_gpr(rD(ctx->opcode));
992: }
993: /* addic */
994: GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
995: {
1.1.1.5 ! root 996: target_long simm = SIMM(ctx->opcode);
! 997:
1.1 root 998: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 999: if (likely(simm != 0)) {
! 1000: gen_op_move_T2_T0();
! 1001: gen_op_addi(simm);
! 1002: #if defined(TARGET_PPC64)
! 1003: if (ctx->sf_mode)
! 1004: gen_op_check_addc_64();
! 1005: else
! 1006: #endif
! 1007: gen_op_check_addc();
! 1008: } else {
! 1009: gen_op_clear_xer_ca();
! 1010: }
1.1 root 1011: gen_op_store_T0_gpr(rD(ctx->opcode));
1012: }
1013: /* addic. */
1.1.1.5 ! root 1014: GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1.1 root 1015: {
1.1.1.5 ! root 1016: target_long simm = SIMM(ctx->opcode);
! 1017:
1.1 root 1018: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 1019: if (likely(simm != 0)) {
! 1020: gen_op_move_T2_T0();
! 1021: gen_op_addi(simm);
! 1022: #if defined(TARGET_PPC64)
! 1023: if (ctx->sf_mode)
! 1024: gen_op_check_addc_64();
! 1025: else
! 1026: #endif
! 1027: gen_op_check_addc();
! 1028: } else {
! 1029: gen_op_clear_xer_ca();
! 1030: }
1.1 root 1031: gen_op_store_T0_gpr(rD(ctx->opcode));
1.1.1.5 ! root 1032: gen_set_Rc0(ctx);
1.1 root 1033: }
1034: /* addis */
1035: GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1036: {
1.1.1.5 ! root 1037: target_long simm = SIMM(ctx->opcode);
1.1 root 1038:
1039: if (rA(ctx->opcode) == 0) {
1.1.1.5 ! root 1040: /* lis case */
! 1041: gen_set_T0(simm << 16);
1.1 root 1042: } else {
1043: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 1044: if (likely(simm != 0))
! 1045: gen_op_addi(simm << 16);
1.1 root 1046: }
1047: gen_op_store_T0_gpr(rD(ctx->opcode));
1048: }
1049: /* mulli */
1050: GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1051: {
1052: gen_op_load_gpr_T0(rA(ctx->opcode));
1053: gen_op_mulli(SIMM(ctx->opcode));
1054: gen_op_store_T0_gpr(rD(ctx->opcode));
1055: }
1056: /* subfic */
1057: GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1058: {
1059: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 1060: #if defined(TARGET_PPC64)
! 1061: if (ctx->sf_mode)
! 1062: gen_op_subfic_64(SIMM(ctx->opcode));
! 1063: else
! 1064: #endif
! 1065: gen_op_subfic(SIMM(ctx->opcode));
1.1 root 1066: gen_op_store_T0_gpr(rD(ctx->opcode));
1067: }
1068:
1.1.1.5 ! root 1069: #if defined(TARGET_PPC64)
! 1070: /* mulhd mulhd. */
! 1071: GEN_INT_ARITHN (mulhd, 0x1F, 0x09, 0x02, PPC_64B);
! 1072: /* mulhdu mulhdu. */
! 1073: GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
! 1074: /* mulld mulld. mulldo mulldo. */
! 1075: GEN_INT_ARITH2 (mulld, 0x1F, 0x09, 0x07, PPC_64B);
! 1076: /* divd divd. divdo divdo. */
! 1077: GEN_INT_ARITH2 (divd, 0x1F, 0x09, 0x0F, PPC_64B);
! 1078: /* divdu divdu. divduo divduo. */
! 1079: GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_64B);
! 1080: #endif
! 1081:
1.1 root 1082: /*** Integer comparison ***/
1.1.1.5 ! root 1083: #if defined(TARGET_PPC64)
! 1084: #define GEN_CMP(name, opc, type) \
! 1085: GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
! 1086: { \
! 1087: gen_op_load_gpr_T0(rA(ctx->opcode)); \
! 1088: gen_op_load_gpr_T1(rB(ctx->opcode)); \
! 1089: if (ctx->sf_mode && (ctx->opcode & 0x00200000)) \
! 1090: gen_op_##name##_64(); \
! 1091: else \
! 1092: gen_op_##name(); \
! 1093: gen_op_store_T0_crf(crfD(ctx->opcode)); \
! 1094: }
! 1095: #else
! 1096: #define GEN_CMP(name, opc, type) \
! 1097: GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
1.1 root 1098: { \
1099: gen_op_load_gpr_T0(rA(ctx->opcode)); \
1100: gen_op_load_gpr_T1(rB(ctx->opcode)); \
1101: gen_op_##name(); \
1102: gen_op_store_T0_crf(crfD(ctx->opcode)); \
1103: }
1.1.1.5 ! root 1104: #endif
1.1 root 1105:
1106: /* cmp */
1.1.1.5 ! root 1107: GEN_CMP(cmp, 0x00, PPC_INTEGER);
1.1 root 1108: /* cmpi */
1109: GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1110: {
1111: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 1112: #if defined(TARGET_PPC64)
! 1113: if (ctx->sf_mode && (ctx->opcode & 0x00200000))
! 1114: gen_op_cmpi_64(SIMM(ctx->opcode));
! 1115: else
! 1116: #endif
! 1117: gen_op_cmpi(SIMM(ctx->opcode));
1.1 root 1118: gen_op_store_T0_crf(crfD(ctx->opcode));
1119: }
1120: /* cmpl */
1.1.1.5 ! root 1121: GEN_CMP(cmpl, 0x01, PPC_INTEGER);
1.1 root 1122: /* cmpli */
1123: GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1124: {
1125: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 1126: #if defined(TARGET_PPC64)
! 1127: if (ctx->sf_mode && (ctx->opcode & 0x00200000))
! 1128: gen_op_cmpli_64(UIMM(ctx->opcode));
! 1129: else
! 1130: #endif
! 1131: gen_op_cmpli(UIMM(ctx->opcode));
1.1 root 1132: gen_op_store_T0_crf(crfD(ctx->opcode));
1133: }
1134:
1.1.1.5 ! root 1135: /* isel (PowerPC 2.03 specification) */
! 1136: GEN_HANDLER(isel, 0x1F, 0x0F, 0x00, 0x00000001, PPC_ISEL)
! 1137: {
! 1138: uint32_t bi = rC(ctx->opcode);
! 1139: uint32_t mask;
! 1140:
! 1141: if (rA(ctx->opcode) == 0) {
! 1142: gen_set_T0(0);
! 1143: } else {
! 1144: gen_op_load_gpr_T1(rA(ctx->opcode));
! 1145: }
! 1146: gen_op_load_gpr_T2(rB(ctx->opcode));
! 1147: mask = 1 << (3 - (bi & 0x03));
! 1148: gen_op_load_crf_T0(bi >> 2);
! 1149: gen_op_test_true(mask);
! 1150: gen_op_isel();
! 1151: gen_op_store_T0_gpr(rD(ctx->opcode));
! 1152: }
! 1153:
1.1 root 1154: /*** Integer logical ***/
1.1.1.5 ! root 1155: #define __GEN_LOGICAL2(name, opc2, opc3, type) \
! 1156: GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type) \
1.1 root 1157: { \
1158: gen_op_load_gpr_T0(rS(ctx->opcode)); \
1159: gen_op_load_gpr_T1(rB(ctx->opcode)); \
1160: gen_op_##name(); \
1161: gen_op_store_T0_gpr(rA(ctx->opcode)); \
1.1.1.5 ! root 1162: if (unlikely(Rc(ctx->opcode) != 0)) \
! 1163: gen_set_Rc0(ctx); \
1.1 root 1164: }
1.1.1.5 ! root 1165: #define GEN_LOGICAL2(name, opc, type) \
! 1166: __GEN_LOGICAL2(name, 0x1C, opc, type)
1.1 root 1167:
1.1.1.5 ! root 1168: #define GEN_LOGICAL1(name, opc, type) \
! 1169: GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \
1.1 root 1170: { \
1171: gen_op_load_gpr_T0(rS(ctx->opcode)); \
1172: gen_op_##name(); \
1173: gen_op_store_T0_gpr(rA(ctx->opcode)); \
1.1.1.5 ! root 1174: if (unlikely(Rc(ctx->opcode) != 0)) \
! 1175: gen_set_Rc0(ctx); \
1.1 root 1176: }
1177:
1178: /* and & and. */
1.1.1.5 ! root 1179: GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
1.1 root 1180: /* andc & andc. */
1.1.1.5 ! root 1181: GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
1.1 root 1182: /* andi. */
1.1.1.5 ! root 1183: GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1.1 root 1184: {
1185: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 1186: gen_op_andi_T0(UIMM(ctx->opcode));
1.1 root 1187: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1.1.5 ! root 1188: gen_set_Rc0(ctx);
1.1 root 1189: }
1190: /* andis. */
1.1.1.5 ! root 1191: GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1.1 root 1192: {
1193: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 1194: gen_op_andi_T0(UIMM(ctx->opcode) << 16);
1.1 root 1195: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1.1.5 ! root 1196: gen_set_Rc0(ctx);
1.1 root 1197: }
1198:
1199: /* cntlzw */
1.1.1.5 ! root 1200: GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
1.1 root 1201: /* eqv & eqv. */
1.1.1.5 ! root 1202: GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
1.1 root 1203: /* extsb & extsb. */
1.1.1.5 ! root 1204: GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
1.1 root 1205: /* extsh & extsh. */
1.1.1.5 ! root 1206: GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
1.1 root 1207: /* nand & nand. */
1.1.1.5 ! root 1208: GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
1.1 root 1209: /* nor & nor. */
1.1.1.5 ! root 1210: GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
1.1 root 1211:
1212: /* or & or. */
1213: GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1214: {
1.1.1.5 ! root 1215: int rs, ra, rb;
! 1216:
! 1217: rs = rS(ctx->opcode);
! 1218: ra = rA(ctx->opcode);
! 1219: rb = rB(ctx->opcode);
! 1220: /* Optimisation for mr. ri case */
! 1221: if (rs != ra || rs != rb) {
! 1222: gen_op_load_gpr_T0(rs);
! 1223: if (rs != rb) {
! 1224: gen_op_load_gpr_T1(rb);
! 1225: gen_op_or();
! 1226: }
! 1227: gen_op_store_T0_gpr(ra);
! 1228: if (unlikely(Rc(ctx->opcode) != 0))
! 1229: gen_set_Rc0(ctx);
! 1230: } else if (unlikely(Rc(ctx->opcode) != 0)) {
! 1231: gen_op_load_gpr_T0(rs);
! 1232: gen_set_Rc0(ctx);
! 1233: #if defined(TARGET_PPC64)
! 1234: } else {
! 1235: switch (rs) {
! 1236: case 1:
! 1237: /* Set process priority to low */
! 1238: gen_op_store_pri(2);
! 1239: break;
! 1240: case 6:
! 1241: /* Set process priority to medium-low */
! 1242: gen_op_store_pri(3);
! 1243: break;
! 1244: case 2:
! 1245: /* Set process priority to normal */
! 1246: gen_op_store_pri(4);
! 1247: break;
! 1248: #if !defined(CONFIG_USER_ONLY)
! 1249: case 31:
! 1250: if (ctx->supervisor > 0) {
! 1251: /* Set process priority to very low */
! 1252: gen_op_store_pri(1);
! 1253: }
! 1254: break;
! 1255: case 5:
! 1256: if (ctx->supervisor > 0) {
! 1257: /* Set process priority to medium-hight */
! 1258: gen_op_store_pri(5);
! 1259: }
! 1260: break;
! 1261: case 3:
! 1262: if (ctx->supervisor > 0) {
! 1263: /* Set process priority to high */
! 1264: gen_op_store_pri(6);
! 1265: }
! 1266: break;
! 1267: case 7:
! 1268: if (ctx->supervisor > 1) {
! 1269: /* Set process priority to very high */
! 1270: gen_op_store_pri(7);
! 1271: }
! 1272: break;
! 1273: #endif
! 1274: default:
! 1275: /* nop */
! 1276: break;
! 1277: }
! 1278: #endif
1.1 root 1279: }
1280: }
1281:
1282: /* orc & orc. */
1.1.1.5 ! root 1283: GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
1.1 root 1284: /* xor & xor. */
1285: GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
1286: {
1287: gen_op_load_gpr_T0(rS(ctx->opcode));
1288: /* Optimisation for "set to zero" case */
1289: if (rS(ctx->opcode) != rB(ctx->opcode)) {
1290: gen_op_load_gpr_T1(rB(ctx->opcode));
1291: gen_op_xor();
1292: } else {
1.1.1.5 ! root 1293: gen_op_reset_T0();
1.1 root 1294: }
1295: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1.1.5 ! root 1296: if (unlikely(Rc(ctx->opcode) != 0))
! 1297: gen_set_Rc0(ctx);
1.1 root 1298: }
1299: /* ori */
1300: GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1301: {
1.1.1.5 ! root 1302: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1303:
1304: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1305: /* NOP */
1.1.1.5 ! root 1306: /* XXX: should handle special NOPs for POWER series */
1.1 root 1307: return;
1.1.1.5 ! root 1308: }
! 1309: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1310: if (likely(uimm != 0))
1.1 root 1311: gen_op_ori(uimm);
1.1.1.5 ! root 1312: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1 root 1313: }
1314: /* oris */
1315: GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1316: {
1.1.1.5 ! root 1317: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1318:
1319: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1320: /* NOP */
1321: return;
1.1.1.5 ! root 1322: }
! 1323: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1324: if (likely(uimm != 0))
1.1 root 1325: gen_op_ori(uimm << 16);
1.1.1.5 ! root 1326: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1 root 1327: }
1328: /* xori */
1329: GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1330: {
1.1.1.5 ! root 1331: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1332:
1333: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1334: /* NOP */
1335: return;
1336: }
1337: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 1338: if (likely(uimm != 0))
! 1339: gen_op_xori(uimm);
1.1 root 1340: gen_op_store_T0_gpr(rA(ctx->opcode));
1341: }
1342:
1343: /* xoris */
1344: GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1345: {
1.1.1.5 ! root 1346: target_ulong uimm = UIMM(ctx->opcode);
1.1 root 1347:
1348: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1349: /* NOP */
1350: return;
1351: }
1352: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 1353: if (likely(uimm != 0))
! 1354: gen_op_xori(uimm << 16);
! 1355: gen_op_store_T0_gpr(rA(ctx->opcode));
! 1356: }
! 1357:
! 1358: /* popcntb : PowerPC 2.03 specification */
! 1359: GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
! 1360: {
! 1361: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1362: #if defined(TARGET_PPC64)
! 1363: if (ctx->sf_mode)
! 1364: gen_op_popcntb_64();
! 1365: else
! 1366: #endif
! 1367: gen_op_popcntb();
1.1 root 1368: gen_op_store_T0_gpr(rA(ctx->opcode));
1369: }
1370:
1.1.1.5 ! root 1371: #if defined(TARGET_PPC64)
! 1372: /* extsw & extsw. */
! 1373: GEN_LOGICAL1(extsw, 0x1E, PPC_64B);
! 1374: /* cntlzd */
! 1375: GEN_LOGICAL1(cntlzd, 0x01, PPC_64B);
! 1376: #endif
! 1377:
1.1 root 1378: /*** Integer rotate ***/
1379: /* rlwimi & rlwimi. */
1380: GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1381: {
1.1.1.5 ! root 1382: target_ulong mask;
! 1383: uint32_t mb, me, sh;
1.1 root 1384:
1385: mb = MB(ctx->opcode);
1386: me = ME(ctx->opcode);
1.1.1.5 ! root 1387: sh = SH(ctx->opcode);
! 1388: if (likely(sh == 0)) {
! 1389: if (likely(mb == 0 && me == 31)) {
! 1390: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1391: goto do_store;
! 1392: } else if (likely(mb == 31 && me == 0)) {
! 1393: gen_op_load_gpr_T0(rA(ctx->opcode));
! 1394: goto do_store;
! 1395: }
! 1396: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1397: gen_op_load_gpr_T1(rA(ctx->opcode));
! 1398: goto do_mask;
! 1399: }
1.1 root 1400: gen_op_load_gpr_T0(rS(ctx->opcode));
1401: gen_op_load_gpr_T1(rA(ctx->opcode));
1.1.1.5 ! root 1402: gen_op_rotli32_T0(SH(ctx->opcode));
! 1403: do_mask:
! 1404: #if defined(TARGET_PPC64)
! 1405: mb += 32;
! 1406: me += 32;
! 1407: #endif
! 1408: mask = MASK(mb, me);
! 1409: gen_op_andi_T0(mask);
! 1410: gen_op_andi_T1(~mask);
! 1411: gen_op_or();
! 1412: do_store:
1.1 root 1413: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1.1.5 ! root 1414: if (unlikely(Rc(ctx->opcode) != 0))
! 1415: gen_set_Rc0(ctx);
1.1 root 1416: }
1417: /* rlwinm & rlwinm. */
1418: GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1419: {
1420: uint32_t mb, me, sh;
1.1.1.5 ! root 1421:
1.1 root 1422: sh = SH(ctx->opcode);
1423: mb = MB(ctx->opcode);
1424: me = ME(ctx->opcode);
1425: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 1426: if (likely(sh == 0)) {
! 1427: goto do_mask;
1.1 root 1428: }
1.1.1.5 ! root 1429: if (likely(mb == 0)) {
! 1430: if (likely(me == 31)) {
! 1431: gen_op_rotli32_T0(sh);
! 1432: goto do_store;
! 1433: } else if (likely(me == (31 - sh))) {
! 1434: gen_op_sli_T0(sh);
! 1435: goto do_store;
1.1 root 1436: }
1.1.1.5 ! root 1437: } else if (likely(me == 31)) {
! 1438: if (likely(sh == (32 - mb))) {
! 1439: gen_op_srli_T0(mb);
! 1440: goto do_store;
1.1 root 1441: }
1442: }
1.1.1.5 ! root 1443: gen_op_rotli32_T0(sh);
! 1444: do_mask:
! 1445: #if defined(TARGET_PPC64)
! 1446: mb += 32;
! 1447: me += 32;
! 1448: #endif
! 1449: gen_op_andi_T0(MASK(mb, me));
! 1450: do_store:
1.1 root 1451: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1.1.5 ! root 1452: if (unlikely(Rc(ctx->opcode) != 0))
! 1453: gen_set_Rc0(ctx);
1.1 root 1454: }
1455: /* rlwnm & rlwnm. */
1456: GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1457: {
1458: uint32_t mb, me;
1459:
1460: mb = MB(ctx->opcode);
1461: me = ME(ctx->opcode);
1462: gen_op_load_gpr_T0(rS(ctx->opcode));
1463: gen_op_load_gpr_T1(rB(ctx->opcode));
1.1.1.5 ! root 1464: gen_op_rotl32_T0_T1();
! 1465: if (unlikely(mb != 0 || me != 31)) {
! 1466: #if defined(TARGET_PPC64)
! 1467: mb += 32;
! 1468: me += 32;
! 1469: #endif
! 1470: gen_op_andi_T0(MASK(mb, me));
1.1 root 1471: }
1472: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1.1.5 ! root 1473: if (unlikely(Rc(ctx->opcode) != 0))
! 1474: gen_set_Rc0(ctx);
! 1475: }
! 1476:
! 1477: #if defined(TARGET_PPC64)
! 1478: #define GEN_PPC64_R2(name, opc1, opc2) \
! 1479: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
! 1480: { \
! 1481: gen_##name(ctx, 0); \
! 1482: } \
! 1483: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
! 1484: PPC_64B) \
! 1485: { \
! 1486: gen_##name(ctx, 1); \
! 1487: }
! 1488: #define GEN_PPC64_R4(name, opc1, opc2) \
! 1489: GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
! 1490: { \
! 1491: gen_##name(ctx, 0, 0); \
! 1492: } \
! 1493: GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
! 1494: PPC_64B) \
! 1495: { \
! 1496: gen_##name(ctx, 0, 1); \
! 1497: } \
! 1498: GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
! 1499: PPC_64B) \
! 1500: { \
! 1501: gen_##name(ctx, 1, 0); \
! 1502: } \
! 1503: GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
! 1504: PPC_64B) \
! 1505: { \
! 1506: gen_##name(ctx, 1, 1); \
! 1507: }
! 1508:
! 1509: static always_inline void gen_andi_T0_64 (DisasContext *ctx, uint64_t mask)
! 1510: {
! 1511: if (mask >> 32)
! 1512: gen_op_andi_T0_64(mask >> 32, mask & 0xFFFFFFFF);
! 1513: else
! 1514: gen_op_andi_T0(mask);
! 1515: }
! 1516:
! 1517: static always_inline void gen_andi_T1_64 (DisasContext *ctx, uint64_t mask)
! 1518: {
! 1519: if (mask >> 32)
! 1520: gen_op_andi_T1_64(mask >> 32, mask & 0xFFFFFFFF);
! 1521: else
! 1522: gen_op_andi_T1(mask);
! 1523: }
! 1524:
! 1525: static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
! 1526: uint32_t me, uint32_t sh)
! 1527: {
! 1528: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1529: if (likely(sh == 0)) {
! 1530: goto do_mask;
! 1531: }
! 1532: if (likely(mb == 0)) {
! 1533: if (likely(me == 63)) {
! 1534: gen_op_rotli64_T0(sh);
! 1535: goto do_store;
! 1536: } else if (likely(me == (63 - sh))) {
! 1537: gen_op_sli_T0(sh);
! 1538: goto do_store;
! 1539: }
! 1540: } else if (likely(me == 63)) {
! 1541: if (likely(sh == (64 - mb))) {
! 1542: gen_op_srli_T0_64(mb);
! 1543: goto do_store;
! 1544: }
! 1545: }
! 1546: gen_op_rotli64_T0(sh);
! 1547: do_mask:
! 1548: gen_andi_T0_64(ctx, MASK(mb, me));
! 1549: do_store:
! 1550: gen_op_store_T0_gpr(rA(ctx->opcode));
! 1551: if (unlikely(Rc(ctx->opcode) != 0))
! 1552: gen_set_Rc0(ctx);
! 1553: }
! 1554: /* rldicl - rldicl. */
! 1555: static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
! 1556: {
! 1557: uint32_t sh, mb;
! 1558:
! 1559: sh = SH(ctx->opcode) | (shn << 5);
! 1560: mb = MB(ctx->opcode) | (mbn << 5);
! 1561: gen_rldinm(ctx, mb, 63, sh);
! 1562: }
! 1563: GEN_PPC64_R4(rldicl, 0x1E, 0x00);
! 1564: /* rldicr - rldicr. */
! 1565: static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
! 1566: {
! 1567: uint32_t sh, me;
! 1568:
! 1569: sh = SH(ctx->opcode) | (shn << 5);
! 1570: me = MB(ctx->opcode) | (men << 5);
! 1571: gen_rldinm(ctx, 0, me, sh);
! 1572: }
! 1573: GEN_PPC64_R4(rldicr, 0x1E, 0x02);
! 1574: /* rldic - rldic. */
! 1575: static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
! 1576: {
! 1577: uint32_t sh, mb;
! 1578:
! 1579: sh = SH(ctx->opcode) | (shn << 5);
! 1580: mb = MB(ctx->opcode) | (mbn << 5);
! 1581: gen_rldinm(ctx, mb, 63 - sh, sh);
! 1582: }
! 1583: GEN_PPC64_R4(rldic, 0x1E, 0x04);
! 1584:
! 1585: static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
! 1586: uint32_t me)
! 1587: {
! 1588: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1589: gen_op_load_gpr_T1(rB(ctx->opcode));
! 1590: gen_op_rotl64_T0_T1();
! 1591: if (unlikely(mb != 0 || me != 63)) {
! 1592: gen_andi_T0_64(ctx, MASK(mb, me));
! 1593: }
! 1594: gen_op_store_T0_gpr(rA(ctx->opcode));
! 1595: if (unlikely(Rc(ctx->opcode) != 0))
! 1596: gen_set_Rc0(ctx);
! 1597: }
! 1598:
! 1599: /* rldcl - rldcl. */
! 1600: static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
! 1601: {
! 1602: uint32_t mb;
! 1603:
! 1604: mb = MB(ctx->opcode) | (mbn << 5);
! 1605: gen_rldnm(ctx, mb, 63);
! 1606: }
! 1607: GEN_PPC64_R2(rldcl, 0x1E, 0x08);
! 1608: /* rldcr - rldcr. */
! 1609: static always_inline void gen_rldcr (DisasContext *ctx, int men)
! 1610: {
! 1611: uint32_t me;
! 1612:
! 1613: me = MB(ctx->opcode) | (men << 5);
! 1614: gen_rldnm(ctx, 0, me);
! 1615: }
! 1616: GEN_PPC64_R2(rldcr, 0x1E, 0x09);
! 1617: /* rldimi - rldimi. */
! 1618: static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
! 1619: {
! 1620: uint64_t mask;
! 1621: uint32_t sh, mb, me;
! 1622:
! 1623: sh = SH(ctx->opcode) | (shn << 5);
! 1624: mb = MB(ctx->opcode) | (mbn << 5);
! 1625: me = 63 - sh;
! 1626: if (likely(sh == 0)) {
! 1627: if (likely(mb == 0)) {
! 1628: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1629: goto do_store;
! 1630: }
! 1631: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1632: gen_op_load_gpr_T1(rA(ctx->opcode));
! 1633: goto do_mask;
! 1634: }
! 1635: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1636: gen_op_load_gpr_T1(rA(ctx->opcode));
! 1637: gen_op_rotli64_T0(sh);
! 1638: do_mask:
! 1639: mask = MASK(mb, me);
! 1640: gen_andi_T0_64(ctx, mask);
! 1641: gen_andi_T1_64(ctx, ~mask);
! 1642: gen_op_or();
! 1643: do_store:
! 1644: gen_op_store_T0_gpr(rA(ctx->opcode));
! 1645: if (unlikely(Rc(ctx->opcode) != 0))
! 1646: gen_set_Rc0(ctx);
1.1 root 1647: }
1.1.1.5 ! root 1648: GEN_PPC64_R4(rldimi, 0x1E, 0x06);
! 1649: #endif
1.1 root 1650:
1651: /*** Integer shift ***/
1652: /* slw & slw. */
1.1.1.5 ! root 1653: __GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
1.1 root 1654: /* sraw & sraw. */
1.1.1.5 ! root 1655: __GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
1.1 root 1656: /* srawi & srawi. */
1657: GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
1658: {
1.1.1.5 ! root 1659: int mb, me;
1.1 root 1660: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 1661: if (SH(ctx->opcode) != 0) {
! 1662: gen_op_move_T1_T0();
! 1663: mb = 32 - SH(ctx->opcode);
! 1664: me = 31;
! 1665: #if defined(TARGET_PPC64)
! 1666: mb += 32;
! 1667: me += 32;
! 1668: #endif
! 1669: gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
! 1670: }
1.1 root 1671: gen_op_store_T0_gpr(rA(ctx->opcode));
1.1.1.5 ! root 1672: if (unlikely(Rc(ctx->opcode) != 0))
! 1673: gen_set_Rc0(ctx);
1.1 root 1674: }
1675: /* srw & srw. */
1.1.1.5 ! root 1676: __GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);
! 1677:
! 1678: #if defined(TARGET_PPC64)
! 1679: /* sld & sld. */
! 1680: __GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
! 1681: /* srad & srad. */
! 1682: __GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
! 1683: /* sradi & sradi. */
! 1684: static always_inline void gen_sradi (DisasContext *ctx, int n)
! 1685: {
! 1686: uint64_t mask;
! 1687: int sh, mb, me;
! 1688:
! 1689: gen_op_load_gpr_T0(rS(ctx->opcode));
! 1690: sh = SH(ctx->opcode) + (n << 5);
! 1691: if (sh != 0) {
! 1692: gen_op_move_T1_T0();
! 1693: mb = 64 - SH(ctx->opcode);
! 1694: me = 63;
! 1695: mask = MASK(mb, me);
! 1696: gen_op_sradi(sh, mask >> 32, mask);
! 1697: }
! 1698: gen_op_store_T0_gpr(rA(ctx->opcode));
! 1699: if (unlikely(Rc(ctx->opcode) != 0))
! 1700: gen_set_Rc0(ctx);
! 1701: }
! 1702: GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
! 1703: {
! 1704: gen_sradi(ctx, 0);
! 1705: }
! 1706: GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
! 1707: {
! 1708: gen_sradi(ctx, 1);
! 1709: }
! 1710: /* srd & srd. */
! 1711: __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
! 1712: #endif
1.1 root 1713:
1714: /*** Floating-Point arithmetic ***/
1.1.1.5 ! root 1715: #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
! 1716: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
1.1 root 1717: { \
1.1.1.5 ! root 1718: if (unlikely(!ctx->fpu_enabled)) { \
! 1719: GEN_EXCP_NO_FP(ctx); \
1.1 root 1720: return; \
1721: } \
1722: gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1723: gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1724: gen_op_load_fpr_FT2(rB(ctx->opcode)); \
1.1.1.5 ! root 1725: gen_reset_fpstatus(); \
1.1 root 1726: gen_op_f##op(); \
1727: if (isfloat) { \
1728: gen_op_frsp(); \
1729: } \
1730: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1.1.5 ! root 1731: gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 1732: }
1733:
1.1.1.5 ! root 1734: #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
! 1735: _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
! 1736: _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1.1 root 1737:
1.1.1.5 ! root 1738: #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
! 1739: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1.1 root 1740: { \
1.1.1.5 ! root 1741: if (unlikely(!ctx->fpu_enabled)) { \
! 1742: GEN_EXCP_NO_FP(ctx); \
1.1 root 1743: return; \
1744: } \
1745: gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1746: gen_op_load_fpr_FT1(rB(ctx->opcode)); \
1.1.1.5 ! root 1747: gen_reset_fpstatus(); \
1.1 root 1748: gen_op_f##op(); \
1749: if (isfloat) { \
1750: gen_op_frsp(); \
1751: } \
1752: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1.1.5 ! root 1753: gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 1754: }
1.1.1.5 ! root 1755: #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
! 1756: _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
! 1757: _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1.1 root 1758:
1.1.1.5 ! root 1759: #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
! 1760: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1.1 root 1761: { \
1.1.1.5 ! root 1762: if (unlikely(!ctx->fpu_enabled)) { \
! 1763: GEN_EXCP_NO_FP(ctx); \
1.1 root 1764: return; \
1765: } \
1766: gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1767: gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1.1.1.5 ! root 1768: gen_reset_fpstatus(); \
1.1 root 1769: gen_op_f##op(); \
1770: if (isfloat) { \
1771: gen_op_frsp(); \
1772: } \
1773: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1.1.5 ! root 1774: gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 1775: }
1.1.1.5 ! root 1776: #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
! 1777: _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
! 1778: _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1.1 root 1779:
1.1.1.5 ! root 1780: #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
! 1781: GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
1.1 root 1782: { \
1.1.1.5 ! root 1783: if (unlikely(!ctx->fpu_enabled)) { \
! 1784: GEN_EXCP_NO_FP(ctx); \
1.1 root 1785: return; \
1786: } \
1787: gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1.1.1.5 ! root 1788: gen_reset_fpstatus(); \
1.1 root 1789: gen_op_f##name(); \
1790: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1.1.5 ! root 1791: gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 1792: }
1793:
1.1.1.5 ! root 1794: #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
! 1795: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
1.1 root 1796: { \
1.1.1.5 ! root 1797: if (unlikely(!ctx->fpu_enabled)) { \
! 1798: GEN_EXCP_NO_FP(ctx); \
1.1 root 1799: return; \
1800: } \
1801: gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1.1.1.5 ! root 1802: gen_reset_fpstatus(); \
1.1 root 1803: gen_op_f##name(); \
1804: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1.1.5 ! root 1805: gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1.1 root 1806: }
1807:
1808: /* fadd - fadds */
1.1.1.5 ! root 1809: GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1.1 root 1810: /* fdiv - fdivs */
1.1.1.5 ! root 1811: GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1.1 root 1812: /* fmul - fmuls */
1.1.1.5 ! root 1813: GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
! 1814:
! 1815: /* fre */
! 1816: GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1.1 root 1817:
1818: /* fres */
1.1.1.5 ! root 1819: GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
1.1 root 1820:
1821: /* frsqrte */
1.1.1.5 ! root 1822: GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
! 1823:
! 1824: /* frsqrtes */
! 1825: static always_inline void gen_op_frsqrtes (void)
! 1826: {
! 1827: gen_op_frsqrte();
! 1828: gen_op_frsp();
! 1829: }
! 1830: GEN_FLOAT_BS(rsqrtes, 0x3B, 0x1A, 1, PPC_FLOAT_FRSQRTES);
1.1 root 1831:
1832: /* fsel */
1.1.1.5 ! root 1833: _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1.1 root 1834: /* fsub - fsubs */
1.1.1.5 ! root 1835: GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
1.1 root 1836: /* Optional: */
1837: /* fsqrt */
1.1.1.5 ! root 1838: GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1.1 root 1839: {
1.1.1.5 ! root 1840: if (unlikely(!ctx->fpu_enabled)) {
! 1841: GEN_EXCP_NO_FP(ctx);
1.1 root 1842: return;
1843: }
1844: gen_op_load_fpr_FT0(rB(ctx->opcode));
1.1.1.5 ! root 1845: gen_reset_fpstatus();
1.1 root 1846: gen_op_fsqrt();
1847: gen_op_store_FT0_fpr(rD(ctx->opcode));
1.1.1.5 ! root 1848: gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1.1 root 1849: }
1850:
1.1.1.5 ! root 1851: GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1.1 root 1852: {
1.1.1.5 ! root 1853: if (unlikely(!ctx->fpu_enabled)) {
! 1854: GEN_EXCP_NO_FP(ctx);
1.1 root 1855: return;
1856: }
1857: gen_op_load_fpr_FT0(rB(ctx->opcode));
1.1.1.5 ! root 1858: gen_reset_fpstatus();
1.1 root 1859: gen_op_fsqrt();
1860: gen_op_frsp();
1861: gen_op_store_FT0_fpr(rD(ctx->opcode));
1.1.1.5 ! root 1862: gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1.1 root 1863: }
1864:
1865: /*** Floating-Point multiply-and-add ***/
1866: /* fmadd - fmadds */
1.1.1.5 ! root 1867: GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1.1 root 1868: /* fmsub - fmsubs */
1.1.1.5 ! root 1869: GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1.1 root 1870: /* fnmadd - fnmadds */
1.1.1.5 ! root 1871: GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1.1 root 1872: /* fnmsub - fnmsubs */
1.1.1.5 ! root 1873: GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
1.1 root 1874:
1875: /*** Floating-Point round & convert ***/
1876: /* fctiw */
1.1.1.5 ! root 1877: GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
1.1 root 1878: /* fctiwz */
1.1.1.5 ! root 1879: GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
1.1 root 1880: /* frsp */
1.1.1.5 ! root 1881: GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
! 1882: #if defined(TARGET_PPC64)
! 1883: /* fcfid */
! 1884: GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
! 1885: /* fctid */
! 1886: GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
! 1887: /* fctidz */
! 1888: GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
! 1889: #endif
! 1890:
! 1891: /* frin */
! 1892: GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
! 1893: /* friz */
! 1894: GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
! 1895: /* frip */
! 1896: GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
! 1897: /* frim */
! 1898: GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1.1 root 1899:
1900: /*** Floating-Point compare ***/
1901: /* fcmpo */
1.1.1.5 ! root 1902: GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
1.1 root 1903: {
1.1.1.5 ! root 1904: if (unlikely(!ctx->fpu_enabled)) {
! 1905: GEN_EXCP_NO_FP(ctx);
1.1 root 1906: return;
1907: }
1908: gen_op_load_fpr_FT0(rA(ctx->opcode));
1909: gen_op_load_fpr_FT1(rB(ctx->opcode));
1.1.1.5 ! root 1910: gen_reset_fpstatus();
1.1 root 1911: gen_op_fcmpo();
1912: gen_op_store_T0_crf(crfD(ctx->opcode));
1.1.1.5 ! root 1913: gen_op_float_check_status();
1.1 root 1914: }
1915:
1916: /* fcmpu */
1.1.1.5 ! root 1917: GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
1.1 root 1918: {
1.1.1.5 ! root 1919: if (unlikely(!ctx->fpu_enabled)) {
! 1920: GEN_EXCP_NO_FP(ctx);
1.1 root 1921: return;
1922: }
1923: gen_op_load_fpr_FT0(rA(ctx->opcode));
1924: gen_op_load_fpr_FT1(rB(ctx->opcode));
1.1.1.5 ! root 1925: gen_reset_fpstatus();
1.1 root 1926: gen_op_fcmpu();
1927: gen_op_store_T0_crf(crfD(ctx->opcode));
1.1.1.5 ! root 1928: gen_op_float_check_status();
1.1 root 1929: }
1930:
1931: /*** Floating-point move ***/
1932: /* fabs */
1.1.1.5 ! root 1933: /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
! 1934: GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1.1 root 1935:
1936: /* fmr - fmr. */
1.1.1.5 ! root 1937: /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1.1 root 1938: GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1939: {
1.1.1.5 ! root 1940: if (unlikely(!ctx->fpu_enabled)) {
! 1941: GEN_EXCP_NO_FP(ctx);
1.1 root 1942: return;
1943: }
1944: gen_op_load_fpr_FT0(rB(ctx->opcode));
1945: gen_op_store_FT0_fpr(rD(ctx->opcode));
1.1.1.5 ! root 1946: gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1.1 root 1947: }
1948:
1949: /* fnabs */
1.1.1.5 ! root 1950: /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
! 1951: GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1.1 root 1952: /* fneg */
1.1.1.5 ! root 1953: /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
! 1954: GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1.1 root 1955:
1956: /*** Floating-Point status & ctrl register ***/
1957: /* mcrfs */
1958: GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
1959: {
1.1.1.5 ! root 1960: int bfa;
! 1961:
! 1962: if (unlikely(!ctx->fpu_enabled)) {
! 1963: GEN_EXCP_NO_FP(ctx);
1.1 root 1964: return;
1965: }
1.1.1.5 ! root 1966: gen_optimize_fprf();
! 1967: bfa = 4 * (7 - crfS(ctx->opcode));
! 1968: gen_op_load_fpscr_T0(bfa);
1.1 root 1969: gen_op_store_T0_crf(crfD(ctx->opcode));
1.1.1.5 ! root 1970: gen_op_fpscr_resetbit(~(0xF << bfa));
1.1 root 1971: }
1972:
1973: /* mffs */
1974: GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
1975: {
1.1.1.5 ! root 1976: if (unlikely(!ctx->fpu_enabled)) {
! 1977: GEN_EXCP_NO_FP(ctx);
1.1 root 1978: return;
1979: }
1.1.1.5 ! root 1980: gen_optimize_fprf();
! 1981: gen_reset_fpstatus();
! 1982: gen_op_load_fpscr_FT0();
1.1 root 1983: gen_op_store_FT0_fpr(rD(ctx->opcode));
1.1.1.5 ! root 1984: gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1.1 root 1985: }
1986:
1987: /* mtfsb0 */
1988: GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
1989: {
1990: uint8_t crb;
1.1.1.5 ! root 1991:
! 1992: if (unlikely(!ctx->fpu_enabled)) {
! 1993: GEN_EXCP_NO_FP(ctx);
1.1 root 1994: return;
1995: }
1.1.1.5 ! root 1996: crb = 32 - (crbD(ctx->opcode) >> 2);
! 1997: gen_optimize_fprf();
! 1998: gen_reset_fpstatus();
! 1999: if (likely(crb != 30 && crb != 29))
! 2000: gen_op_fpscr_resetbit(~(1 << crb));
! 2001: if (unlikely(Rc(ctx->opcode) != 0)) {
! 2002: gen_op_load_fpcc();
! 2003: gen_op_set_Rc0();
! 2004: }
1.1 root 2005: }
2006:
2007: /* mtfsb1 */
2008: GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
2009: {
2010: uint8_t crb;
1.1.1.5 ! root 2011:
! 2012: if (unlikely(!ctx->fpu_enabled)) {
! 2013: GEN_EXCP_NO_FP(ctx);
1.1 root 2014: return;
2015: }
1.1.1.5 ! root 2016: crb = 32 - (crbD(ctx->opcode) >> 2);
! 2017: gen_optimize_fprf();
! 2018: gen_reset_fpstatus();
! 2019: /* XXX: we pretend we can only do IEEE floating-point computations */
! 2020: if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
! 2021: gen_op_fpscr_setbit(crb);
! 2022: if (unlikely(Rc(ctx->opcode) != 0)) {
! 2023: gen_op_load_fpcc();
! 2024: gen_op_set_Rc0();
! 2025: }
! 2026: /* We can raise a differed exception */
! 2027: gen_op_float_check_status();
1.1 root 2028: }
2029:
2030: /* mtfsf */
2031: GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
2032: {
1.1.1.5 ! root 2033: if (unlikely(!ctx->fpu_enabled)) {
! 2034: GEN_EXCP_NO_FP(ctx);
1.1 root 2035: return;
2036: }
1.1.1.5 ! root 2037: gen_optimize_fprf();
1.1 root 2038: gen_op_load_fpr_FT0(rB(ctx->opcode));
1.1.1.5 ! root 2039: gen_reset_fpstatus();
1.1 root 2040: gen_op_store_fpscr(FM(ctx->opcode));
1.1.1.5 ! root 2041: if (unlikely(Rc(ctx->opcode) != 0)) {
! 2042: gen_op_load_fpcc();
! 2043: gen_op_set_Rc0();
! 2044: }
! 2045: /* We can raise a differed exception */
! 2046: gen_op_float_check_status();
1.1 root 2047: }
2048:
2049: /* mtfsfi */
2050: GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
2051: {
1.1.1.5 ! root 2052: int bf, sh;
! 2053:
! 2054: if (unlikely(!ctx->fpu_enabled)) {
! 2055: GEN_EXCP_NO_FP(ctx);
1.1 root 2056: return;
2057: }
1.1.1.5 ! root 2058: bf = crbD(ctx->opcode) >> 2;
! 2059: sh = 7 - bf;
! 2060: gen_optimize_fprf();
! 2061: gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh));
! 2062: gen_reset_fpstatus();
! 2063: gen_op_store_fpscr(1 << sh);
! 2064: if (unlikely(Rc(ctx->opcode) != 0)) {
! 2065: gen_op_load_fpcc();
! 2066: gen_op_set_Rc0();
! 2067: }
! 2068: /* We can raise a differed exception */
! 2069: gen_op_float_check_status();
1.1 root 2070: }
2071:
1.1.1.5 ! root 2072: /*** Addressing modes ***/
! 2073: /* Register indirect with immediate index : EA = (rA|0) + SIMM */
! 2074: static always_inline void gen_addr_imm_index (DisasContext *ctx,
! 2075: target_long maskl)
! 2076: {
! 2077: target_long simm = SIMM(ctx->opcode);
! 2078:
! 2079: simm &= ~maskl;
! 2080: if (rA(ctx->opcode) == 0) {
! 2081: gen_set_T0(simm);
! 2082: } else {
! 2083: gen_op_load_gpr_T0(rA(ctx->opcode));
! 2084: if (likely(simm != 0))
! 2085: gen_op_addi(simm);
! 2086: }
! 2087: #ifdef DEBUG_MEMORY_ACCESSES
! 2088: gen_op_print_mem_EA();
! 2089: #endif
! 2090: }
! 2091:
! 2092: static always_inline void gen_addr_reg_index (DisasContext *ctx)
! 2093: {
! 2094: if (rA(ctx->opcode) == 0) {
! 2095: gen_op_load_gpr_T0(rB(ctx->opcode));
! 2096: } else {
! 2097: gen_op_load_gpr_T0(rA(ctx->opcode));
! 2098: gen_op_load_gpr_T1(rB(ctx->opcode));
! 2099: gen_op_add();
! 2100: }
! 2101: #ifdef DEBUG_MEMORY_ACCESSES
! 2102: gen_op_print_mem_EA();
! 2103: #endif
! 2104: }
! 2105:
! 2106: static always_inline void gen_addr_register (DisasContext *ctx)
! 2107: {
! 2108: if (rA(ctx->opcode) == 0) {
! 2109: gen_op_reset_T0();
! 2110: } else {
! 2111: gen_op_load_gpr_T0(rA(ctx->opcode));
! 2112: }
! 2113: #ifdef DEBUG_MEMORY_ACCESSES
! 2114: gen_op_print_mem_EA();
! 2115: #endif
! 2116: }
! 2117:
! 2118: #if defined(TARGET_PPC64)
! 2119: #define _GEN_MEM_FUNCS(name, mode) \
! 2120: &gen_op_##name##_##mode, \
! 2121: &gen_op_##name##_le_##mode, \
! 2122: &gen_op_##name##_64_##mode, \
! 2123: &gen_op_##name##_le_64_##mode
! 2124: #else
! 2125: #define _GEN_MEM_FUNCS(name, mode) \
! 2126: &gen_op_##name##_##mode, \
! 2127: &gen_op_##name##_le_##mode
! 2128: #endif
! 2129: #if defined(CONFIG_USER_ONLY)
! 2130: #if defined(TARGET_PPC64)
! 2131: #define NB_MEM_FUNCS 4
! 2132: #else
! 2133: #define NB_MEM_FUNCS 2
! 2134: #endif
! 2135: #define GEN_MEM_FUNCS(name) \
! 2136: _GEN_MEM_FUNCS(name, raw)
! 2137: #else
! 2138: #if defined(TARGET_PPC64)
! 2139: #define NB_MEM_FUNCS 12
! 2140: #else
! 2141: #define NB_MEM_FUNCS 6
! 2142: #endif
! 2143: #define GEN_MEM_FUNCS(name) \
! 2144: _GEN_MEM_FUNCS(name, user), \
! 2145: _GEN_MEM_FUNCS(name, kernel), \
! 2146: _GEN_MEM_FUNCS(name, hypv)
! 2147: #endif
! 2148:
1.1 root 2149: /*** Integer load ***/
2150: #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
2151: /* Byte access routine are endian safe */
1.1.1.5 ! root 2152: #define gen_op_lbz_le_raw gen_op_lbz_raw
! 2153: #define gen_op_lbz_le_user gen_op_lbz_user
! 2154: #define gen_op_lbz_le_kernel gen_op_lbz_kernel
! 2155: #define gen_op_lbz_le_hypv gen_op_lbz_hypv
! 2156: #define gen_op_lbz_le_64_raw gen_op_lbz_64_raw
! 2157: #define gen_op_lbz_le_64_user gen_op_lbz_64_user
! 2158: #define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
! 2159: #define gen_op_lbz_le_64_hypv gen_op_lbz_64_hypv
! 2160: #define gen_op_stb_le_raw gen_op_stb_raw
! 2161: #define gen_op_stb_le_user gen_op_stb_user
! 2162: #define gen_op_stb_le_kernel gen_op_stb_kernel
! 2163: #define gen_op_stb_le_hypv gen_op_stb_hypv
! 2164: #define gen_op_stb_le_64_raw gen_op_stb_64_raw
! 2165: #define gen_op_stb_le_64_user gen_op_stb_64_user
! 2166: #define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
! 2167: #define gen_op_stb_le_64_hypv gen_op_stb_64_hypv
1.1 root 2168: #define OP_LD_TABLE(width) \
1.1.1.5 ! root 2169: static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = { \
! 2170: GEN_MEM_FUNCS(l##width), \
1.1 root 2171: };
2172: #define OP_ST_TABLE(width) \
1.1.1.5 ! root 2173: static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = { \
! 2174: GEN_MEM_FUNCS(st##width), \
1.1 root 2175: };
1.1.1.5 ! root 2176:
! 2177: #define GEN_LD(width, opc, type) \
! 2178: GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
! 2179: { \
! 2180: gen_addr_imm_index(ctx, 0); \
1.1 root 2181: op_ldst(l##width); \
2182: gen_op_store_T1_gpr(rD(ctx->opcode)); \
2183: }
2184:
1.1.1.5 ! root 2185: #define GEN_LDU(width, opc, type) \
! 2186: GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
1.1 root 2187: { \
1.1.1.5 ! root 2188: if (unlikely(rA(ctx->opcode) == 0 || \
! 2189: rA(ctx->opcode) == rD(ctx->opcode))) { \
! 2190: GEN_EXCP_INVAL(ctx); \
1.1 root 2191: return; \
2192: } \
1.1.1.5 ! root 2193: if (type == PPC_64B) \
! 2194: gen_addr_imm_index(ctx, 0x03); \
! 2195: else \
! 2196: gen_addr_imm_index(ctx, 0); \
1.1 root 2197: op_ldst(l##width); \
2198: gen_op_store_T1_gpr(rD(ctx->opcode)); \
2199: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2200: }
2201:
1.1.1.5 ! root 2202: #define GEN_LDUX(width, opc2, opc3, type) \
! 2203: GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
1.1 root 2204: { \
1.1.1.5 ! root 2205: if (unlikely(rA(ctx->opcode) == 0 || \
! 2206: rA(ctx->opcode) == rD(ctx->opcode))) { \
! 2207: GEN_EXCP_INVAL(ctx); \
1.1 root 2208: return; \
2209: } \
1.1.1.5 ! root 2210: gen_addr_reg_index(ctx); \
1.1 root 2211: op_ldst(l##width); \
2212: gen_op_store_T1_gpr(rD(ctx->opcode)); \
2213: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2214: }
2215:
1.1.1.5 ! root 2216: #define GEN_LDX(width, opc2, opc3, type) \
! 2217: GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
1.1 root 2218: { \
1.1.1.5 ! root 2219: gen_addr_reg_index(ctx); \
1.1 root 2220: op_ldst(l##width); \
2221: gen_op_store_T1_gpr(rD(ctx->opcode)); \
2222: }
2223:
1.1.1.5 ! root 2224: #define GEN_LDS(width, op, type) \
1.1 root 2225: OP_LD_TABLE(width); \
1.1.1.5 ! root 2226: GEN_LD(width, op | 0x20, type); \
! 2227: GEN_LDU(width, op | 0x21, type); \
! 2228: GEN_LDUX(width, 0x17, op | 0x01, type); \
! 2229: GEN_LDX(width, 0x17, op | 0x00, type)
1.1 root 2230:
2231: /* lbz lbzu lbzux lbzx */
1.1.1.5 ! root 2232: GEN_LDS(bz, 0x02, PPC_INTEGER);
1.1 root 2233: /* lha lhau lhaux lhax */
1.1.1.5 ! root 2234: GEN_LDS(ha, 0x0A, PPC_INTEGER);
1.1 root 2235: /* lhz lhzu lhzux lhzx */
1.1.1.5 ! root 2236: GEN_LDS(hz, 0x08, PPC_INTEGER);
1.1 root 2237: /* lwz lwzu lwzux lwzx */
1.1.1.5 ! root 2238: GEN_LDS(wz, 0x00, PPC_INTEGER);
! 2239: #if defined(TARGET_PPC64)
! 2240: OP_LD_TABLE(wa);
! 2241: OP_LD_TABLE(d);
! 2242: /* lwaux */
! 2243: GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
! 2244: /* lwax */
! 2245: GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
! 2246: /* ldux */
! 2247: GEN_LDUX(d, 0x15, 0x01, PPC_64B);
! 2248: /* ldx */
! 2249: GEN_LDX(d, 0x15, 0x00, PPC_64B);
! 2250: GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
! 2251: {
! 2252: if (Rc(ctx->opcode)) {
! 2253: if (unlikely(rA(ctx->opcode) == 0 ||
! 2254: rA(ctx->opcode) == rD(ctx->opcode))) {
! 2255: GEN_EXCP_INVAL(ctx);
! 2256: return;
! 2257: }
! 2258: }
! 2259: gen_addr_imm_index(ctx, 0x03);
! 2260: if (ctx->opcode & 0x02) {
! 2261: /* lwa (lwau is undefined) */
! 2262: op_ldst(lwa);
! 2263: } else {
! 2264: /* ld - ldu */
! 2265: op_ldst(ld);
! 2266: }
! 2267: gen_op_store_T1_gpr(rD(ctx->opcode));
! 2268: if (Rc(ctx->opcode))
! 2269: gen_op_store_T0_gpr(rA(ctx->opcode));
! 2270: }
! 2271: /* lq */
! 2272: GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
! 2273: {
! 2274: #if defined(CONFIG_USER_ONLY)
! 2275: GEN_EXCP_PRIVOPC(ctx);
! 2276: #else
! 2277: int ra, rd;
! 2278:
! 2279: /* Restore CPU state */
! 2280: if (unlikely(ctx->supervisor == 0)) {
! 2281: GEN_EXCP_PRIVOPC(ctx);
! 2282: return;
! 2283: }
! 2284: ra = rA(ctx->opcode);
! 2285: rd = rD(ctx->opcode);
! 2286: if (unlikely((rd & 1) || rd == ra)) {
! 2287: GEN_EXCP_INVAL(ctx);
! 2288: return;
! 2289: }
! 2290: if (unlikely(ctx->mem_idx & 1)) {
! 2291: /* Little-endian mode is not handled */
! 2292: GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
! 2293: return;
! 2294: }
! 2295: gen_addr_imm_index(ctx, 0x0F);
! 2296: op_ldst(ld);
! 2297: gen_op_store_T1_gpr(rd);
! 2298: gen_op_addi(8);
! 2299: op_ldst(ld);
! 2300: gen_op_store_T1_gpr(rd + 1);
! 2301: #endif
! 2302: }
! 2303: #endif
1.1 root 2304:
2305: /*** Integer store ***/
1.1.1.5 ! root 2306: #define GEN_ST(width, opc, type) \
! 2307: GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
1.1 root 2308: { \
1.1.1.5 ! root 2309: gen_addr_imm_index(ctx, 0); \
1.1 root 2310: gen_op_load_gpr_T1(rS(ctx->opcode)); \
2311: op_ldst(st##width); \
2312: }
2313:
1.1.1.5 ! root 2314: #define GEN_STU(width, opc, type) \
! 2315: GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
1.1 root 2316: { \
1.1.1.5 ! root 2317: if (unlikely(rA(ctx->opcode) == 0)) { \
! 2318: GEN_EXCP_INVAL(ctx); \
1.1 root 2319: return; \
2320: } \
1.1.1.5 ! root 2321: if (type == PPC_64B) \
! 2322: gen_addr_imm_index(ctx, 0x03); \
! 2323: else \
! 2324: gen_addr_imm_index(ctx, 0); \
1.1 root 2325: gen_op_load_gpr_T1(rS(ctx->opcode)); \
2326: op_ldst(st##width); \
2327: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2328: }
2329:
1.1.1.5 ! root 2330: #define GEN_STUX(width, opc2, opc3, type) \
! 2331: GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
1.1 root 2332: { \
1.1.1.5 ! root 2333: if (unlikely(rA(ctx->opcode) == 0)) { \
! 2334: GEN_EXCP_INVAL(ctx); \
1.1 root 2335: return; \
2336: } \
1.1.1.5 ! root 2337: gen_addr_reg_index(ctx); \
1.1 root 2338: gen_op_load_gpr_T1(rS(ctx->opcode)); \
2339: op_ldst(st##width); \
2340: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2341: }
2342:
1.1.1.5 ! root 2343: #define GEN_STX(width, opc2, opc3, type) \
! 2344: GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
1.1 root 2345: { \
1.1.1.5 ! root 2346: gen_addr_reg_index(ctx); \
1.1 root 2347: gen_op_load_gpr_T1(rS(ctx->opcode)); \
2348: op_ldst(st##width); \
2349: }
2350:
1.1.1.5 ! root 2351: #define GEN_STS(width, op, type) \
1.1 root 2352: OP_ST_TABLE(width); \
1.1.1.5 ! root 2353: GEN_ST(width, op | 0x20, type); \
! 2354: GEN_STU(width, op | 0x21, type); \
! 2355: GEN_STUX(width, 0x17, op | 0x01, type); \
! 2356: GEN_STX(width, 0x17, op | 0x00, type)
1.1 root 2357:
2358: /* stb stbu stbux stbx */
1.1.1.5 ! root 2359: GEN_STS(b, 0x06, PPC_INTEGER);
1.1 root 2360: /* sth sthu sthux sthx */
1.1.1.5 ! root 2361: GEN_STS(h, 0x0C, PPC_INTEGER);
1.1 root 2362: /* stw stwu stwux stwx */
1.1.1.5 ! root 2363: GEN_STS(w, 0x04, PPC_INTEGER);
! 2364: #if defined(TARGET_PPC64)
! 2365: OP_ST_TABLE(d);
! 2366: GEN_STUX(d, 0x15, 0x05, PPC_64B);
! 2367: GEN_STX(d, 0x15, 0x04, PPC_64B);
! 2368: GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
! 2369: {
! 2370: int rs;
1.1 root 2371:
1.1.1.5 ! root 2372: rs = rS(ctx->opcode);
! 2373: if ((ctx->opcode & 0x3) == 0x2) {
! 2374: #if defined(CONFIG_USER_ONLY)
! 2375: GEN_EXCP_PRIVOPC(ctx);
! 2376: #else
! 2377: /* stq */
! 2378: if (unlikely(ctx->supervisor == 0)) {
! 2379: GEN_EXCP_PRIVOPC(ctx);
! 2380: return;
! 2381: }
! 2382: if (unlikely(rs & 1)) {
! 2383: GEN_EXCP_INVAL(ctx);
! 2384: return;
! 2385: }
! 2386: if (unlikely(ctx->mem_idx & 1)) {
! 2387: /* Little-endian mode is not handled */
! 2388: GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
! 2389: return;
! 2390: }
! 2391: gen_addr_imm_index(ctx, 0x03);
! 2392: gen_op_load_gpr_T1(rs);
! 2393: op_ldst(std);
! 2394: gen_op_addi(8);
! 2395: gen_op_load_gpr_T1(rs + 1);
! 2396: op_ldst(std);
! 2397: #endif
! 2398: } else {
! 2399: /* std / stdu */
! 2400: if (Rc(ctx->opcode)) {
! 2401: if (unlikely(rA(ctx->opcode) == 0)) {
! 2402: GEN_EXCP_INVAL(ctx);
! 2403: return;
! 2404: }
! 2405: }
! 2406: gen_addr_imm_index(ctx, 0x03);
! 2407: gen_op_load_gpr_T1(rs);
! 2408: op_ldst(std);
! 2409: if (Rc(ctx->opcode))
! 2410: gen_op_store_T0_gpr(rA(ctx->opcode));
! 2411: }
! 2412: }
! 2413: #endif
1.1 root 2414: /*** Integer load and store with byte reverse ***/
2415: /* lhbrx */
2416: OP_LD_TABLE(hbr);
1.1.1.5 ! root 2417: GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
1.1 root 2418: /* lwbrx */
2419: OP_LD_TABLE(wbr);
1.1.1.5 ! root 2420: GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
1.1 root 2421: /* sthbrx */
2422: OP_ST_TABLE(hbr);
1.1.1.5 ! root 2423: GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
1.1 root 2424: /* stwbrx */
2425: OP_ST_TABLE(wbr);
1.1.1.5 ! root 2426: GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
1.1 root 2427:
2428: /*** Integer load and store multiple ***/
2429: #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
1.1.1.5 ! root 2430: static GenOpFunc1 *gen_op_lmw[NB_MEM_FUNCS] = {
! 2431: GEN_MEM_FUNCS(lmw),
! 2432: };
! 2433: static GenOpFunc1 *gen_op_stmw[NB_MEM_FUNCS] = {
! 2434: GEN_MEM_FUNCS(stmw),
1.1 root 2435: };
2436:
2437: /* lmw */
2438: GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2439: {
1.1.1.5 ! root 2440: /* NIP cannot be restored if the memory exception comes from an helper */
! 2441: gen_update_nip(ctx, ctx->nip - 4);
! 2442: gen_addr_imm_index(ctx, 0);
1.1 root 2443: op_ldstm(lmw, rD(ctx->opcode));
2444: }
2445:
2446: /* stmw */
2447: GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2448: {
1.1.1.5 ! root 2449: /* NIP cannot be restored if the memory exception comes from an helper */
! 2450: gen_update_nip(ctx, ctx->nip - 4);
! 2451: gen_addr_imm_index(ctx, 0);
1.1 root 2452: op_ldstm(stmw, rS(ctx->opcode));
2453: }
2454:
2455: /*** Integer load and store strings ***/
2456: #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
2457: #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
1.1.1.5 ! root 2458: /* string load & stores are by definition endian-safe */
! 2459: #define gen_op_lswi_le_raw gen_op_lswi_raw
! 2460: #define gen_op_lswi_le_user gen_op_lswi_user
! 2461: #define gen_op_lswi_le_kernel gen_op_lswi_kernel
! 2462: #define gen_op_lswi_le_hypv gen_op_lswi_hypv
! 2463: #define gen_op_lswi_le_64_raw gen_op_lswi_raw
! 2464: #define gen_op_lswi_le_64_user gen_op_lswi_user
! 2465: #define gen_op_lswi_le_64_kernel gen_op_lswi_kernel
! 2466: #define gen_op_lswi_le_64_hypv gen_op_lswi_hypv
! 2467: static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = {
! 2468: GEN_MEM_FUNCS(lswi),
! 2469: };
! 2470: #define gen_op_lswx_le_raw gen_op_lswx_raw
! 2471: #define gen_op_lswx_le_user gen_op_lswx_user
! 2472: #define gen_op_lswx_le_kernel gen_op_lswx_kernel
! 2473: #define gen_op_lswx_le_hypv gen_op_lswx_hypv
! 2474: #define gen_op_lswx_le_64_raw gen_op_lswx_raw
! 2475: #define gen_op_lswx_le_64_user gen_op_lswx_user
! 2476: #define gen_op_lswx_le_64_kernel gen_op_lswx_kernel
! 2477: #define gen_op_lswx_le_64_hypv gen_op_lswx_hypv
! 2478: static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = {
! 2479: GEN_MEM_FUNCS(lswx),
! 2480: };
! 2481: #define gen_op_stsw_le_raw gen_op_stsw_raw
! 2482: #define gen_op_stsw_le_user gen_op_stsw_user
! 2483: #define gen_op_stsw_le_kernel gen_op_stsw_kernel
! 2484: #define gen_op_stsw_le_hypv gen_op_stsw_hypv
! 2485: #define gen_op_stsw_le_64_raw gen_op_stsw_raw
! 2486: #define gen_op_stsw_le_64_user gen_op_stsw_user
! 2487: #define gen_op_stsw_le_64_kernel gen_op_stsw_kernel
! 2488: #define gen_op_stsw_le_64_hypv gen_op_stsw_hypv
! 2489: static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = {
! 2490: GEN_MEM_FUNCS(stsw),
1.1 root 2491: };
2492:
2493: /* lswi */
2494: /* PowerPC32 specification says we must generate an exception if
2495: * rA is in the range of registers to be loaded.
2496: * In an other hand, IBM says this is valid, but rA won't be loaded.
2497: * For now, I'll follow the spec...
2498: */
1.1.1.5 ! root 2499: GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
1.1 root 2500: {
2501: int nb = NB(ctx->opcode);
2502: int start = rD(ctx->opcode);
2503: int ra = rA(ctx->opcode);
2504: int nr;
2505:
2506: if (nb == 0)
2507: nb = 32;
2508: nr = nb / 4;
1.1.1.5 ! root 2509: if (unlikely(((start + nr) > 32 &&
! 2510: start <= ra && (start + nr - 32) > ra) ||
! 2511: ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
! 2512: GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
! 2513: POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
1.1 root 2514: return;
2515: }
2516: /* NIP cannot be restored if the memory exception comes from an helper */
1.1.1.5 ! root 2517: gen_update_nip(ctx, ctx->nip - 4);
! 2518: gen_addr_register(ctx);
! 2519: gen_op_set_T1(nb);
1.1 root 2520: op_ldsts(lswi, start);
2521: }
2522:
2523: /* lswx */
1.1.1.5 ! root 2524: GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
1.1 root 2525: {
2526: int ra = rA(ctx->opcode);
2527: int rb = rB(ctx->opcode);
2528:
1.1.1.5 ! root 2529: /* NIP cannot be restored if the memory exception comes from an helper */
! 2530: gen_update_nip(ctx, ctx->nip - 4);
! 2531: gen_addr_reg_index(ctx);
1.1 root 2532: if (ra == 0) {
2533: ra = rb;
2534: }
2535: gen_op_load_xer_bc();
2536: op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
2537: }
2538:
2539: /* stswi */
1.1.1.5 ! root 2540: GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
1.1 root 2541: {
2542: int nb = NB(ctx->opcode);
2543:
1.1.1.5 ! root 2544: /* NIP cannot be restored if the memory exception comes from an helper */
! 2545: gen_update_nip(ctx, ctx->nip - 4);
! 2546: gen_addr_register(ctx);
1.1 root 2547: if (nb == 0)
2548: nb = 32;
2549: gen_op_set_T1(nb);
2550: op_ldsts(stsw, rS(ctx->opcode));
2551: }
2552:
2553: /* stswx */
1.1.1.5 ! root 2554: GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
1.1 root 2555: {
2556: /* NIP cannot be restored if the memory exception comes from an helper */
1.1.1.5 ! root 2557: gen_update_nip(ctx, ctx->nip - 4);
! 2558: gen_addr_reg_index(ctx);
! 2559: gen_op_load_xer_bc();
1.1 root 2560: op_ldsts(stsw, rS(ctx->opcode));
2561: }
2562:
2563: /*** Memory synchronisation ***/
2564: /* eieio */
1.1.1.5 ! root 2565: GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
1.1 root 2566: {
2567: }
2568:
2569: /* isync */
1.1.1.5 ! root 2570: GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
1.1 root 2571: {
1.1.1.5 ! root 2572: GEN_STOP(ctx);
1.1 root 2573: }
2574:
2575: #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
2576: #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
1.1.1.5 ! root 2577: static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = {
! 2578: GEN_MEM_FUNCS(lwarx),
! 2579: };
! 2580: static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = {
! 2581: GEN_MEM_FUNCS(stwcx),
1.1 root 2582: };
2583:
2584: /* lwarx */
1.1.1.5 ! root 2585: GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
1.1 root 2586: {
1.1.1.5 ! root 2587: /* NIP cannot be restored if the memory exception comes from an helper */
! 2588: gen_update_nip(ctx, ctx->nip - 4);
! 2589: gen_addr_reg_index(ctx);
1.1 root 2590: op_lwarx();
2591: gen_op_store_T1_gpr(rD(ctx->opcode));
2592: }
2593:
2594: /* stwcx. */
1.1.1.5 ! root 2595: GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
1.1 root 2596: {
1.1.1.5 ! root 2597: /* NIP cannot be restored if the memory exception comes from an helper */
! 2598: gen_update_nip(ctx, ctx->nip - 4);
! 2599: gen_addr_reg_index(ctx);
1.1 root 2600: gen_op_load_gpr_T1(rS(ctx->opcode));
2601: op_stwcx();
2602: }
2603:
1.1.1.5 ! root 2604: #if defined(TARGET_PPC64)
! 2605: #define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
! 2606: #define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
! 2607: static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = {
! 2608: GEN_MEM_FUNCS(ldarx),
! 2609: };
! 2610: static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = {
! 2611: GEN_MEM_FUNCS(stdcx),
! 2612: };
! 2613:
! 2614: /* ldarx */
! 2615: GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
! 2616: {
! 2617: /* NIP cannot be restored if the memory exception comes from an helper */
! 2618: gen_update_nip(ctx, ctx->nip - 4);
! 2619: gen_addr_reg_index(ctx);
! 2620: op_ldarx();
! 2621: gen_op_store_T1_gpr(rD(ctx->opcode));
! 2622: }
! 2623:
! 2624: /* stdcx. */
! 2625: GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
! 2626: {
! 2627: /* NIP cannot be restored if the memory exception comes from an helper */
! 2628: gen_update_nip(ctx, ctx->nip - 4);
! 2629: gen_addr_reg_index(ctx);
! 2630: gen_op_load_gpr_T1(rS(ctx->opcode));
! 2631: op_stdcx();
! 2632: }
! 2633: #endif /* defined(TARGET_PPC64) */
! 2634:
1.1 root 2635: /* sync */
1.1.1.5 ! root 2636: GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
1.1 root 2637: {
2638: }
2639:
1.1.1.5 ! root 2640: /* wait */
! 2641: GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
! 2642: {
! 2643: /* Stop translation, as the CPU is supposed to sleep from now */
! 2644: gen_op_wait();
! 2645: GEN_EXCP(ctx, EXCP_HLT, 1);
! 2646: }
! 2647:
1.1 root 2648: /*** Floating-point load ***/
1.1.1.5 ! root 2649: #define GEN_LDF(width, opc, type) \
! 2650: GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
1.1 root 2651: { \
1.1.1.5 ! root 2652: if (unlikely(!ctx->fpu_enabled)) { \
! 2653: GEN_EXCP_NO_FP(ctx); \
1.1 root 2654: return; \
2655: } \
1.1.1.5 ! root 2656: gen_addr_imm_index(ctx, 0); \
1.1 root 2657: op_ldst(l##width); \
1.1.1.5 ! root 2658: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1 root 2659: }
2660:
1.1.1.5 ! root 2661: #define GEN_LDUF(width, opc, type) \
! 2662: GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
1.1 root 2663: { \
1.1.1.5 ! root 2664: if (unlikely(!ctx->fpu_enabled)) { \
! 2665: GEN_EXCP_NO_FP(ctx); \
1.1 root 2666: return; \
2667: } \
1.1.1.5 ! root 2668: if (unlikely(rA(ctx->opcode) == 0)) { \
! 2669: GEN_EXCP_INVAL(ctx); \
1.1 root 2670: return; \
2671: } \
1.1.1.5 ! root 2672: gen_addr_imm_index(ctx, 0); \
1.1 root 2673: op_ldst(l##width); \
1.1.1.5 ! root 2674: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1 root 2675: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2676: }
2677:
1.1.1.5 ! root 2678: #define GEN_LDUXF(width, opc, type) \
! 2679: GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
1.1 root 2680: { \
1.1.1.5 ! root 2681: if (unlikely(!ctx->fpu_enabled)) { \
! 2682: GEN_EXCP_NO_FP(ctx); \
1.1 root 2683: return; \
2684: } \
1.1.1.5 ! root 2685: if (unlikely(rA(ctx->opcode) == 0)) { \
! 2686: GEN_EXCP_INVAL(ctx); \
1.1 root 2687: return; \
2688: } \
1.1.1.5 ! root 2689: gen_addr_reg_index(ctx); \
1.1 root 2690: op_ldst(l##width); \
1.1.1.5 ! root 2691: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1 root 2692: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2693: }
2694:
1.1.1.5 ! root 2695: #define GEN_LDXF(width, opc2, opc3, type) \
! 2696: GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
1.1 root 2697: { \
1.1.1.5 ! root 2698: if (unlikely(!ctx->fpu_enabled)) { \
! 2699: GEN_EXCP_NO_FP(ctx); \
1.1 root 2700: return; \
2701: } \
1.1.1.5 ! root 2702: gen_addr_reg_index(ctx); \
1.1 root 2703: op_ldst(l##width); \
1.1.1.5 ! root 2704: gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1.1 root 2705: }
2706:
1.1.1.5 ! root 2707: #define GEN_LDFS(width, op, type) \
1.1 root 2708: OP_LD_TABLE(width); \
1.1.1.5 ! root 2709: GEN_LDF(width, op | 0x20, type); \
! 2710: GEN_LDUF(width, op | 0x21, type); \
! 2711: GEN_LDUXF(width, op | 0x01, type); \
! 2712: GEN_LDXF(width, 0x17, op | 0x00, type)
1.1 root 2713:
2714: /* lfd lfdu lfdux lfdx */
1.1.1.5 ! root 2715: GEN_LDFS(fd, 0x12, PPC_FLOAT);
1.1 root 2716: /* lfs lfsu lfsux lfsx */
1.1.1.5 ! root 2717: GEN_LDFS(fs, 0x10, PPC_FLOAT);
1.1 root 2718:
2719: /*** Floating-point store ***/
1.1.1.5 ! root 2720: #define GEN_STF(width, opc, type) \
! 2721: GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
1.1 root 2722: { \
1.1.1.5 ! root 2723: if (unlikely(!ctx->fpu_enabled)) { \
! 2724: GEN_EXCP_NO_FP(ctx); \
! 2725: return; \
1.1 root 2726: } \
1.1.1.5 ! root 2727: gen_addr_imm_index(ctx, 0); \
! 2728: gen_op_load_fpr_FT0(rS(ctx->opcode)); \
1.1 root 2729: op_ldst(st##width); \
2730: }
2731:
1.1.1.5 ! root 2732: #define GEN_STUF(width, opc, type) \
! 2733: GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
1.1 root 2734: { \
1.1.1.5 ! root 2735: if (unlikely(!ctx->fpu_enabled)) { \
! 2736: GEN_EXCP_NO_FP(ctx); \
1.1 root 2737: return; \
2738: } \
1.1.1.5 ! root 2739: if (unlikely(rA(ctx->opcode) == 0)) { \
! 2740: GEN_EXCP_INVAL(ctx); \
1.1 root 2741: return; \
2742: } \
1.1.1.5 ! root 2743: gen_addr_imm_index(ctx, 0); \
! 2744: gen_op_load_fpr_FT0(rS(ctx->opcode)); \
1.1 root 2745: op_ldst(st##width); \
2746: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2747: }
2748:
1.1.1.5 ! root 2749: #define GEN_STUXF(width, opc, type) \
! 2750: GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
1.1 root 2751: { \
1.1.1.5 ! root 2752: if (unlikely(!ctx->fpu_enabled)) { \
! 2753: GEN_EXCP_NO_FP(ctx); \
1.1 root 2754: return; \
2755: } \
1.1.1.5 ! root 2756: if (unlikely(rA(ctx->opcode) == 0)) { \
! 2757: GEN_EXCP_INVAL(ctx); \
1.1 root 2758: return; \
2759: } \
1.1.1.5 ! root 2760: gen_addr_reg_index(ctx); \
! 2761: gen_op_load_fpr_FT0(rS(ctx->opcode)); \
1.1 root 2762: op_ldst(st##width); \
2763: gen_op_store_T0_gpr(rA(ctx->opcode)); \
2764: }
2765:
1.1.1.5 ! root 2766: #define GEN_STXF(width, opc2, opc3, type) \
! 2767: GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
1.1 root 2768: { \
1.1.1.5 ! root 2769: if (unlikely(!ctx->fpu_enabled)) { \
! 2770: GEN_EXCP_NO_FP(ctx); \
1.1 root 2771: return; \
2772: } \
1.1.1.5 ! root 2773: gen_addr_reg_index(ctx); \
! 2774: gen_op_load_fpr_FT0(rS(ctx->opcode)); \
1.1 root 2775: op_ldst(st##width); \
2776: }
2777:
1.1.1.5 ! root 2778: #define GEN_STFS(width, op, type) \
1.1 root 2779: OP_ST_TABLE(width); \
1.1.1.5 ! root 2780: GEN_STF(width, op | 0x20, type); \
! 2781: GEN_STUF(width, op | 0x21, type); \
! 2782: GEN_STUXF(width, op | 0x01, type); \
! 2783: GEN_STXF(width, 0x17, op | 0x00, type)
1.1 root 2784:
2785: /* stfd stfdu stfdux stfdx */
1.1.1.5 ! root 2786: GEN_STFS(fd, 0x16, PPC_FLOAT);
1.1 root 2787: /* stfs stfsu stfsux stfsx */
1.1.1.5 ! root 2788: GEN_STFS(fs, 0x14, PPC_FLOAT);
1.1 root 2789:
2790: /* Optional: */
2791: /* stfiwx */
1.1.1.5 ! root 2792: OP_ST_TABLE(fiw);
! 2793: GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
1.1 root 2794:
2795: /*** Branch ***/
1.1.1.5 ! root 2796: static always_inline void gen_goto_tb (DisasContext *ctx, int n,
! 2797: target_ulong dest)
1.1.1.2 root 2798: {
2799: TranslationBlock *tb;
2800: tb = ctx->tb;
2801: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2802: if (n == 0)
2803: gen_op_goto_tb0(TBPARAM(tb));
2804: else
2805: gen_op_goto_tb1(TBPARAM(tb));
1.1.1.5 ! root 2806: gen_set_T1(dest);
! 2807: #if defined(TARGET_PPC64)
! 2808: if (ctx->sf_mode)
! 2809: gen_op_b_T1_64();
! 2810: else
! 2811: #endif
! 2812: gen_op_b_T1();
1.1.1.2 root 2813: gen_op_set_T0((long)tb + n);
1.1.1.3 root 2814: if (ctx->singlestep_enabled)
2815: gen_op_debug();
1.1.1.2 root 2816: gen_op_exit_tb();
2817: } else {
1.1.1.5 ! root 2818: gen_set_T1(dest);
! 2819: #if defined(TARGET_PPC64)
! 2820: if (ctx->sf_mode)
! 2821: gen_op_b_T1_64();
! 2822: else
! 2823: #endif
! 2824: gen_op_b_T1();
! 2825: gen_op_reset_T0();
1.1.1.3 root 2826: if (ctx->singlestep_enabled)
2827: gen_op_debug();
1.1.1.2 root 2828: gen_op_exit_tb();
2829: }
2830: }
2831:
1.1.1.5 ! root 2832: static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
! 2833: {
! 2834: #if defined(TARGET_PPC64)
! 2835: if (ctx->sf_mode != 0 && (nip >> 32))
! 2836: gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
! 2837: else
! 2838: #endif
! 2839: gen_op_setlr(ctx->nip);
! 2840: }
! 2841:
1.1 root 2842: /* b ba bl bla */
2843: GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
2844: {
1.1.1.5 ! root 2845: target_ulong li, target;
1.1 root 2846:
2847: /* sign extend LI */
1.1.1.5 ! root 2848: #if defined(TARGET_PPC64)
! 2849: if (ctx->sf_mode)
! 2850: li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
! 2851: else
! 2852: #endif
! 2853: li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
! 2854: if (likely(AA(ctx->opcode) == 0))
1.1 root 2855: target = ctx->nip + li - 4;
2856: else
2857: target = li;
1.1.1.5 ! root 2858: #if defined(TARGET_PPC64)
! 2859: if (!ctx->sf_mode)
! 2860: target = (uint32_t)target;
! 2861: #endif
! 2862: if (LK(ctx->opcode))
! 2863: gen_setlr(ctx, ctx->nip);
1.1.1.2 root 2864: gen_goto_tb(ctx, 0, target);
1.1.1.5 ! root 2865: ctx->exception = POWERPC_EXCP_BRANCH;
1.1 root 2866: }
2867:
2868: #define BCOND_IM 0
2869: #define BCOND_LR 1
2870: #define BCOND_CTR 2
2871:
1.1.1.5 ! root 2872: static always_inline void gen_bcond (DisasContext *ctx, int type)
! 2873: {
! 2874: target_ulong target = 0;
! 2875: target_ulong li;
! 2876: uint32_t bo = BO(ctx->opcode);
! 2877: uint32_t bi = BI(ctx->opcode);
! 2878: uint32_t mask;
1.1 root 2879:
2880: if ((bo & 0x4) == 0)
1.1.1.5 ! root 2881: gen_op_dec_ctr();
1.1 root 2882: switch(type) {
2883: case BCOND_IM:
1.1.1.5 ! root 2884: li = (target_long)((int16_t)(BD(ctx->opcode)));
! 2885: if (likely(AA(ctx->opcode) == 0)) {
1.1 root 2886: target = ctx->nip + li - 4;
2887: } else {
2888: target = li;
2889: }
1.1.1.5 ! root 2890: #if defined(TARGET_PPC64)
! 2891: if (!ctx->sf_mode)
! 2892: target = (uint32_t)target;
! 2893: #endif
1.1 root 2894: break;
2895: case BCOND_CTR:
2896: gen_op_movl_T1_ctr();
2897: break;
2898: default:
2899: case BCOND_LR:
2900: gen_op_movl_T1_lr();
2901: break;
2902: }
1.1.1.5 ! root 2903: if (LK(ctx->opcode))
! 2904: gen_setlr(ctx, ctx->nip);
1.1 root 2905: if (bo & 0x10) {
1.1.1.5 ! root 2906: /* No CR condition */
! 2907: switch (bo & 0x6) {
! 2908: case 0:
! 2909: #if defined(TARGET_PPC64)
! 2910: if (ctx->sf_mode)
! 2911: gen_op_test_ctr_64();
! 2912: else
! 2913: #endif
! 2914: gen_op_test_ctr();
! 2915: break;
! 2916: case 2:
! 2917: #if defined(TARGET_PPC64)
! 2918: if (ctx->sf_mode)
! 2919: gen_op_test_ctrz_64();
! 2920: else
! 2921: #endif
! 2922: gen_op_test_ctrz();
1.1 root 2923: break;
2924: default:
1.1.1.5 ! root 2925: case 4:
! 2926: case 6:
1.1 root 2927: if (type == BCOND_IM) {
1.1.1.2 root 2928: gen_goto_tb(ctx, 0, target);
1.1.1.5 ! root 2929: goto out;
1.1 root 2930: } else {
1.1.1.5 ! root 2931: #if defined(TARGET_PPC64)
! 2932: if (ctx->sf_mode)
! 2933: gen_op_b_T1_64();
! 2934: else
! 2935: #endif
! 2936: gen_op_b_T1();
! 2937: gen_op_reset_T0();
! 2938: goto no_test;
1.1 root 2939: }
1.1.1.5 ! root 2940: break;
1.1 root 2941: }
1.1.1.5 ! root 2942: } else {
! 2943: mask = 1 << (3 - (bi & 0x03));
! 2944: gen_op_load_crf_T0(bi >> 2);
! 2945: if (bo & 0x8) {
! 2946: switch (bo & 0x6) {
! 2947: case 0:
! 2948: #if defined(TARGET_PPC64)
! 2949: if (ctx->sf_mode)
! 2950: gen_op_test_ctr_true_64(mask);
! 2951: else
! 2952: #endif
! 2953: gen_op_test_ctr_true(mask);
! 2954: break;
! 2955: case 2:
! 2956: #if defined(TARGET_PPC64)
! 2957: if (ctx->sf_mode)
! 2958: gen_op_test_ctrz_true_64(mask);
! 2959: else
! 2960: #endif
! 2961: gen_op_test_ctrz_true(mask);
! 2962: break;
! 2963: default:
! 2964: case 4:
! 2965: case 6:
1.1 root 2966: gen_op_test_true(mask);
1.1.1.5 ! root 2967: break;
! 2968: }
! 2969: } else {
! 2970: switch (bo & 0x6) {
! 2971: case 0:
! 2972: #if defined(TARGET_PPC64)
! 2973: if (ctx->sf_mode)
! 2974: gen_op_test_ctr_false_64(mask);
! 2975: else
! 2976: #endif
! 2977: gen_op_test_ctr_false(mask);
! 2978: break;
! 2979: case 2:
! 2980: #if defined(TARGET_PPC64)
! 2981: if (ctx->sf_mode)
! 2982: gen_op_test_ctrz_false_64(mask);
! 2983: else
! 2984: #endif
! 2985: gen_op_test_ctrz_false(mask);
! 2986: break;
1.1 root 2987: default:
1.1.1.5 ! root 2988: case 4:
! 2989: case 6:
1.1 root 2990: gen_op_test_false(mask);
1.1.1.5 ! root 2991: break;
! 2992: }
! 2993: }
! 2994: }
1.1 root 2995: if (type == BCOND_IM) {
1.1.1.2 root 2996: int l1 = gen_new_label();
2997: gen_op_jz_T0(l1);
2998: gen_goto_tb(ctx, 0, target);
2999: gen_set_label(l1);
3000: gen_goto_tb(ctx, 1, ctx->nip);
1.1 root 3001: } else {
1.1.1.5 ! root 3002: #if defined(TARGET_PPC64)
! 3003: if (ctx->sf_mode)
! 3004: gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
! 3005: else
! 3006: #endif
! 3007: gen_op_btest_T1(ctx->nip);
! 3008: gen_op_reset_T0();
! 3009: no_test:
! 3010: if (ctx->singlestep_enabled)
! 3011: gen_op_debug();
! 3012: gen_op_exit_tb();
1.1 root 3013: }
1.1.1.5 ! root 3014: out:
! 3015: ctx->exception = POWERPC_EXCP_BRANCH;
1.1 root 3016: }
3017:
3018: GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1.1.1.5 ! root 3019: {
1.1 root 3020: gen_bcond(ctx, BCOND_IM);
3021: }
3022:
3023: GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
1.1.1.5 ! root 3024: {
1.1 root 3025: gen_bcond(ctx, BCOND_CTR);
3026: }
3027:
3028: GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
1.1.1.5 ! root 3029: {
1.1 root 3030: gen_bcond(ctx, BCOND_LR);
3031: }
3032:
3033: /*** Condition register logical ***/
3034: #define GEN_CRLOGIC(op, opc) \
3035: GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
3036: { \
1.1.1.5 ! root 3037: uint8_t bitmask; \
! 3038: int sh; \
1.1 root 3039: gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
1.1.1.5 ! root 3040: sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
! 3041: if (sh > 0) \
! 3042: gen_op_srli_T0(sh); \
! 3043: else if (sh < 0) \
! 3044: gen_op_sli_T0(-sh); \
1.1 root 3045: gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
1.1.1.5 ! root 3046: sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
! 3047: if (sh > 0) \
! 3048: gen_op_srli_T1(sh); \
! 3049: else if (sh < 0) \
! 3050: gen_op_sli_T1(-sh); \
1.1 root 3051: gen_op_##op(); \
1.1.1.5 ! root 3052: bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
! 3053: gen_op_andi_T0(bitmask); \
1.1 root 3054: gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
1.1.1.5 ! root 3055: gen_op_andi_T1(~bitmask); \
! 3056: gen_op_or(); \
! 3057: gen_op_store_T0_crf(crbD(ctx->opcode) >> 2); \
1.1 root 3058: }
3059:
3060: /* crand */
1.1.1.5 ! root 3061: GEN_CRLOGIC(and, 0x08);
1.1 root 3062: /* crandc */
1.1.1.5 ! root 3063: GEN_CRLOGIC(andc, 0x04);
1.1 root 3064: /* creqv */
1.1.1.5 ! root 3065: GEN_CRLOGIC(eqv, 0x09);
1.1 root 3066: /* crnand */
1.1.1.5 ! root 3067: GEN_CRLOGIC(nand, 0x07);
1.1 root 3068: /* crnor */
1.1.1.5 ! root 3069: GEN_CRLOGIC(nor, 0x01);
1.1 root 3070: /* cror */
1.1.1.5 ! root 3071: GEN_CRLOGIC(or, 0x0E);
1.1 root 3072: /* crorc */
1.1.1.5 ! root 3073: GEN_CRLOGIC(orc, 0x0D);
1.1 root 3074: /* crxor */
1.1.1.5 ! root 3075: GEN_CRLOGIC(xor, 0x06);
1.1 root 3076: /* mcrf */
3077: GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3078: {
3079: gen_op_load_crf_T0(crfS(ctx->opcode));
3080: gen_op_store_T0_crf(crfD(ctx->opcode));
3081: }
3082:
3083: /*** System linkage ***/
3084: /* rfi (supervisor only) */
1.1.1.5 ! root 3085: GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
1.1 root 3086: {
3087: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3088: GEN_EXCP_PRIVOPC(ctx);
1.1 root 3089: #else
3090: /* Restore CPU state */
1.1.1.5 ! root 3091: if (unlikely(!ctx->supervisor)) {
! 3092: GEN_EXCP_PRIVOPC(ctx);
1.1 root 3093: return;
3094: }
3095: gen_op_rfi();
1.1.1.5 ! root 3096: GEN_SYNC(ctx);
1.1 root 3097: #endif
3098: }
3099:
1.1.1.5 ! root 3100: #if defined(TARGET_PPC64)
! 3101: GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
! 3102: {
! 3103: #if defined(CONFIG_USER_ONLY)
! 3104: GEN_EXCP_PRIVOPC(ctx);
! 3105: #else
! 3106: /* Restore CPU state */
! 3107: if (unlikely(!ctx->supervisor)) {
! 3108: GEN_EXCP_PRIVOPC(ctx);
! 3109: return;
! 3110: }
! 3111: gen_op_rfid();
! 3112: GEN_SYNC(ctx);
! 3113: #endif
! 3114: }
! 3115:
! 3116: GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
1.1 root 3117: {
3118: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3119: GEN_EXCP_PRIVOPC(ctx);
! 3120: #else
! 3121: /* Restore CPU state */
! 3122: if (unlikely(ctx->supervisor <= 1)) {
! 3123: GEN_EXCP_PRIVOPC(ctx);
! 3124: return;
! 3125: }
! 3126: gen_op_hrfid();
! 3127: GEN_SYNC(ctx);
! 3128: #endif
! 3129: }
! 3130: #endif
! 3131:
! 3132: /* sc */
! 3133: #if defined(CONFIG_USER_ONLY)
! 3134: #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
1.1 root 3135: #else
1.1.1.5 ! root 3136: #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
1.1 root 3137: #endif
1.1.1.5 ! root 3138: GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
! 3139: {
! 3140: uint32_t lev;
! 3141:
! 3142: lev = (ctx->opcode >> 5) & 0x7F;
! 3143: GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
1.1 root 3144: }
3145:
3146: /*** Trap ***/
3147: /* tw */
1.1.1.5 ! root 3148: GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
1.1 root 3149: {
3150: gen_op_load_gpr_T0(rA(ctx->opcode));
3151: gen_op_load_gpr_T1(rB(ctx->opcode));
1.1.1.4 root 3152: /* Update the nip since this might generate a trap exception */
1.1.1.5 ! root 3153: gen_update_nip(ctx, ctx->nip);
1.1 root 3154: gen_op_tw(TO(ctx->opcode));
3155: }
3156:
3157: /* twi */
3158: GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3159: {
3160: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 3161: gen_set_T1(SIMM(ctx->opcode));
! 3162: /* Update the nip since this might generate a trap exception */
! 3163: gen_update_nip(ctx, ctx->nip);
! 3164: gen_op_tw(TO(ctx->opcode));
1.1 root 3165: }
3166:
1.1.1.5 ! root 3167: #if defined(TARGET_PPC64)
! 3168: /* td */
! 3169: GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
1.1 root 3170: {
1.1.1.5 ! root 3171: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3172: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3173: /* Update the nip since this might generate a trap exception */
! 3174: gen_update_nip(ctx, ctx->nip);
! 3175: gen_op_td(TO(ctx->opcode));
! 3176: }
1.1 root 3177:
1.1.1.5 ! root 3178: /* tdi */
! 3179: GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
! 3180: {
! 3181: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3182: gen_set_T1(SIMM(ctx->opcode));
! 3183: /* Update the nip since this might generate a trap exception */
! 3184: gen_update_nip(ctx, ctx->nip);
! 3185: gen_op_td(TO(ctx->opcode));
1.1 root 3186: }
1.1.1.5 ! root 3187: #endif
1.1 root 3188:
1.1.1.5 ! root 3189: /*** Processor control ***/
1.1 root 3190: /* mcrxr */
3191: GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3192: {
3193: gen_op_load_xer_cr();
3194: gen_op_store_T0_crf(crfD(ctx->opcode));
1.1.1.5 ! root 3195: gen_op_clear_xer_ov();
! 3196: gen_op_clear_xer_ca();
1.1 root 3197: }
3198:
3199: /* mfcr */
1.1.1.5 ! root 3200: GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
1.1 root 3201: {
1.1.1.5 ! root 3202: uint32_t crm, crn;
! 3203:
! 3204: if (likely(ctx->opcode & 0x00100000)) {
! 3205: crm = CRM(ctx->opcode);
! 3206: if (likely((crm ^ (crm - 1)) == 0)) {
! 3207: crn = ffs(crm);
! 3208: gen_op_load_cro(7 - crn);
! 3209: }
! 3210: } else {
! 3211: gen_op_load_cr();
! 3212: }
1.1 root 3213: gen_op_store_T0_gpr(rD(ctx->opcode));
3214: }
3215:
3216: /* mfmsr */
3217: GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3218: {
3219: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3220: GEN_EXCP_PRIVREG(ctx);
1.1 root 3221: #else
1.1.1.5 ! root 3222: if (unlikely(!ctx->supervisor)) {
! 3223: GEN_EXCP_PRIVREG(ctx);
1.1 root 3224: return;
3225: }
3226: gen_op_load_msr();
3227: gen_op_store_T0_gpr(rD(ctx->opcode));
3228: #endif
3229: }
3230:
1.1.1.5 ! root 3231: #if 1
! 3232: #define SPR_NOACCESS ((void *)(-1UL))
1.1 root 3233: #else
3234: static void spr_noaccess (void *opaque, int sprn)
3235: {
3236: sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3237: printf("ERROR: try to access SPR %d !\n", sprn);
3238: }
3239: #define SPR_NOACCESS (&spr_noaccess)
3240: #endif
3241:
3242: /* mfspr */
1.1.1.5 ! root 3243: static always_inline void gen_op_mfspr (DisasContext *ctx)
1.1 root 3244: {
3245: void (*read_cb)(void *opaque, int sprn);
3246: uint32_t sprn = SPR(ctx->opcode);
3247:
3248: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3249: if (ctx->supervisor == 2)
! 3250: read_cb = ctx->spr_cb[sprn].hea_read;
! 3251: else if (ctx->supervisor)
1.1 root 3252: read_cb = ctx->spr_cb[sprn].oea_read;
3253: else
3254: #endif
3255: read_cb = ctx->spr_cb[sprn].uea_read;
1.1.1.5 ! root 3256: if (likely(read_cb != NULL)) {
! 3257: if (likely(read_cb != SPR_NOACCESS)) {
1.1 root 3258: (*read_cb)(ctx, sprn);
3259: gen_op_store_T0_gpr(rD(ctx->opcode));
3260: } else {
3261: /* Privilege exception */
1.1.1.5 ! root 3262: /* This is a hack to avoid warnings when running Linux:
! 3263: * this OS breaks the PowerPC virtualisation model,
! 3264: * allowing userland application to read the PVR
! 3265: */
! 3266: if (sprn != SPR_PVR) {
! 3267: if (loglevel != 0) {
! 3268: fprintf(logfile, "Trying to read privileged spr %d %03x at "
! 3269: ADDRX "\n", sprn, sprn, ctx->nip);
! 3270: }
! 3271: printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
! 3272: sprn, sprn, ctx->nip);
1.1.1.2 root 3273: }
1.1.1.5 ! root 3274: GEN_EXCP_PRIVREG(ctx);
1.1 root 3275: }
3276: } else {
3277: /* Not defined */
1.1.1.5 ! root 3278: if (loglevel != 0) {
! 3279: fprintf(logfile, "Trying to read invalid spr %d %03x at "
! 3280: ADDRX "\n", sprn, sprn, ctx->nip);
1.1.1.2 root 3281: }
1.1.1.5 ! root 3282: printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
! 3283: sprn, sprn, ctx->nip);
! 3284: GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
! 3285: POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
1.1 root 3286: }
3287: }
3288:
3289: GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
3290: {
3291: gen_op_mfspr(ctx);
1.1.1.5 ! root 3292: }
1.1 root 3293:
3294: /* mftb */
1.1.1.5 ! root 3295: GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
1.1 root 3296: {
3297: gen_op_mfspr(ctx);
3298: }
3299:
3300: /* mtcrf */
3301: GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3302: {
1.1.1.5 ! root 3303: uint32_t crm, crn;
! 3304:
1.1 root 3305: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 3306: crm = CRM(ctx->opcode);
! 3307: if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
! 3308: crn = ffs(crm);
! 3309: gen_op_srli_T0(crn * 4);
! 3310: gen_op_andi_T0(0xF);
! 3311: gen_op_store_cro(7 - crn);
! 3312: } else {
! 3313: gen_op_store_cr(crm);
! 3314: }
1.1 root 3315: }
3316:
3317: /* mtmsr */
1.1.1.5 ! root 3318: #if defined(TARGET_PPC64)
! 3319: GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
! 3320: {
! 3321: #if defined(CONFIG_USER_ONLY)
! 3322: GEN_EXCP_PRIVREG(ctx);
! 3323: #else
! 3324: if (unlikely(!ctx->supervisor)) {
! 3325: GEN_EXCP_PRIVREG(ctx);
! 3326: return;
! 3327: }
! 3328: gen_op_load_gpr_T0(rS(ctx->opcode));
! 3329: if (ctx->opcode & 0x00010000) {
! 3330: /* Special form that does not need any synchronisation */
! 3331: gen_op_update_riee();
! 3332: } else {
! 3333: /* XXX: we need to update nip before the store
! 3334: * if we enter power saving mode, we will exit the loop
! 3335: * directly from ppc_store_msr
! 3336: */
! 3337: gen_update_nip(ctx, ctx->nip);
! 3338: gen_op_store_msr();
! 3339: /* Must stop the translation as machine state (may have) changed */
! 3340: /* Note that mtmsr is not always defined as context-synchronizing */
! 3341: ctx->exception = POWERPC_EXCP_STOP;
! 3342: }
! 3343: #endif
! 3344: }
! 3345: #endif
! 3346:
1.1 root 3347: GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3348: {
3349: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3350: GEN_EXCP_PRIVREG(ctx);
1.1 root 3351: #else
1.1.1.5 ! root 3352: if (unlikely(!ctx->supervisor)) {
! 3353: GEN_EXCP_PRIVREG(ctx);
1.1 root 3354: return;
3355: }
3356: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 3357: if (ctx->opcode & 0x00010000) {
! 3358: /* Special form that does not need any synchronisation */
! 3359: gen_op_update_riee();
! 3360: } else {
! 3361: /* XXX: we need to update nip before the store
! 3362: * if we enter power saving mode, we will exit the loop
! 3363: * directly from ppc_store_msr
! 3364: */
! 3365: gen_update_nip(ctx, ctx->nip);
! 3366: #if defined(TARGET_PPC64)
! 3367: if (!ctx->sf_mode)
! 3368: gen_op_store_msr_32();
! 3369: else
! 3370: #endif
! 3371: gen_op_store_msr();
! 3372: /* Must stop the translation as machine state (may have) changed */
! 3373: /* Note that mtmsrd is not always defined as context-synchronizing */
! 3374: ctx->exception = POWERPC_EXCP_STOP;
! 3375: }
1.1 root 3376: #endif
3377: }
3378:
3379: /* mtspr */
3380: GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3381: {
3382: void (*write_cb)(void *opaque, int sprn);
3383: uint32_t sprn = SPR(ctx->opcode);
3384:
3385: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3386: if (ctx->supervisor == 2)
! 3387: write_cb = ctx->spr_cb[sprn].hea_write;
! 3388: else if (ctx->supervisor)
1.1 root 3389: write_cb = ctx->spr_cb[sprn].oea_write;
3390: else
3391: #endif
3392: write_cb = ctx->spr_cb[sprn].uea_write;
1.1.1.5 ! root 3393: if (likely(write_cb != NULL)) {
! 3394: if (likely(write_cb != SPR_NOACCESS)) {
1.1 root 3395: gen_op_load_gpr_T0(rS(ctx->opcode));
3396: (*write_cb)(ctx, sprn);
3397: } else {
3398: /* Privilege exception */
1.1.1.5 ! root 3399: if (loglevel != 0) {
! 3400: fprintf(logfile, "Trying to write privileged spr %d %03x at "
! 3401: ADDRX "\n", sprn, sprn, ctx->nip);
1.1.1.2 root 3402: }
1.1.1.5 ! root 3403: printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
! 3404: sprn, sprn, ctx->nip);
! 3405: GEN_EXCP_PRIVREG(ctx);
! 3406: }
1.1 root 3407: } else {
3408: /* Not defined */
1.1.1.5 ! root 3409: if (loglevel != 0) {
! 3410: fprintf(logfile, "Trying to write invalid spr %d %03x at "
! 3411: ADDRX "\n", sprn, sprn, ctx->nip);
1.1.1.2 root 3412: }
1.1.1.5 ! root 3413: printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
! 3414: sprn, sprn, ctx->nip);
! 3415: GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
! 3416: POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
1.1 root 3417: }
3418: }
3419:
3420: /*** Cache management ***/
3421: /* dcbf */
1.1.1.5 ! root 3422: GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
1.1 root 3423: {
1.1.1.5 ! root 3424: /* XXX: specification says this is treated as a load by the MMU */
! 3425: gen_addr_reg_index(ctx);
1.1 root 3426: op_ldst(lbz);
3427: }
3428:
3429: /* dcbi (Supervisor only) */
3430: GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
3431: {
3432: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3433: GEN_EXCP_PRIVOPC(ctx);
1.1 root 3434: #else
1.1.1.5 ! root 3435: if (unlikely(!ctx->supervisor)) {
! 3436: GEN_EXCP_PRIVOPC(ctx);
1.1 root 3437: return;
3438: }
1.1.1.5 ! root 3439: gen_addr_reg_index(ctx);
! 3440: /* XXX: specification says this should be treated as a store by the MMU */
1.1 root 3441: op_ldst(lbz);
3442: op_ldst(stb);
3443: #endif
3444: }
3445:
3446: /* dcdst */
3447: GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
3448: {
1.1.1.5 ! root 3449: /* XXX: specification say this is treated as a load by the MMU */
! 3450: gen_addr_reg_index(ctx);
1.1 root 3451: op_ldst(lbz);
3452: }
3453:
3454: /* dcbt */
1.1.1.5 ! root 3455: GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
1.1 root 3456: {
1.1.1.5 ! root 3457: /* interpreted as no-op */
! 3458: /* XXX: specification say this is treated as a load by the MMU
! 3459: * but does not generate any exception
! 3460: */
1.1 root 3461: }
3462:
3463: /* dcbtst */
1.1.1.5 ! root 3464: GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
1.1 root 3465: {
1.1.1.5 ! root 3466: /* interpreted as no-op */
! 3467: /* XXX: specification say this is treated as a load by the MMU
! 3468: * but does not generate any exception
! 3469: */
1.1 root 3470: }
3471:
3472: /* dcbz */
1.1.1.5 ! root 3473: #define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
! 3474: static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
! 3475: /* 32 bytes cache line size */
! 3476: {
! 3477: #define gen_op_dcbz_l32_le_raw gen_op_dcbz_l32_raw
! 3478: #define gen_op_dcbz_l32_le_user gen_op_dcbz_l32_user
! 3479: #define gen_op_dcbz_l32_le_kernel gen_op_dcbz_l32_kernel
! 3480: #define gen_op_dcbz_l32_le_hypv gen_op_dcbz_l32_hypv
! 3481: #define gen_op_dcbz_l32_le_64_raw gen_op_dcbz_l32_64_raw
! 3482: #define gen_op_dcbz_l32_le_64_user gen_op_dcbz_l32_64_user
! 3483: #define gen_op_dcbz_l32_le_64_kernel gen_op_dcbz_l32_64_kernel
! 3484: #define gen_op_dcbz_l32_le_64_hypv gen_op_dcbz_l32_64_hypv
! 3485: GEN_MEM_FUNCS(dcbz_l32),
! 3486: },
! 3487: /* 64 bytes cache line size */
! 3488: {
! 3489: #define gen_op_dcbz_l64_le_raw gen_op_dcbz_l64_raw
! 3490: #define gen_op_dcbz_l64_le_user gen_op_dcbz_l64_user
! 3491: #define gen_op_dcbz_l64_le_kernel gen_op_dcbz_l64_kernel
! 3492: #define gen_op_dcbz_l64_le_hypv gen_op_dcbz_l64_hypv
! 3493: #define gen_op_dcbz_l64_le_64_raw gen_op_dcbz_l64_64_raw
! 3494: #define gen_op_dcbz_l64_le_64_user gen_op_dcbz_l64_64_user
! 3495: #define gen_op_dcbz_l64_le_64_kernel gen_op_dcbz_l64_64_kernel
! 3496: #define gen_op_dcbz_l64_le_64_hypv gen_op_dcbz_l64_64_hypv
! 3497: GEN_MEM_FUNCS(dcbz_l64),
! 3498: },
! 3499: /* 128 bytes cache line size */
! 3500: {
! 3501: #define gen_op_dcbz_l128_le_raw gen_op_dcbz_l128_raw
! 3502: #define gen_op_dcbz_l128_le_user gen_op_dcbz_l128_user
! 3503: #define gen_op_dcbz_l128_le_kernel gen_op_dcbz_l128_kernel
! 3504: #define gen_op_dcbz_l128_le_hypv gen_op_dcbz_l128_hypv
! 3505: #define gen_op_dcbz_l128_le_64_raw gen_op_dcbz_l128_64_raw
! 3506: #define gen_op_dcbz_l128_le_64_user gen_op_dcbz_l128_64_user
! 3507: #define gen_op_dcbz_l128_le_64_kernel gen_op_dcbz_l128_64_kernel
! 3508: #define gen_op_dcbz_l128_le_64_hypv gen_op_dcbz_l128_64_hypv
! 3509: GEN_MEM_FUNCS(dcbz_l128),
! 3510: },
! 3511: /* tunable cache line size */
! 3512: {
! 3513: #define gen_op_dcbz_le_raw gen_op_dcbz_raw
! 3514: #define gen_op_dcbz_le_user gen_op_dcbz_user
! 3515: #define gen_op_dcbz_le_kernel gen_op_dcbz_kernel
! 3516: #define gen_op_dcbz_le_hypv gen_op_dcbz_hypv
! 3517: #define gen_op_dcbz_le_64_raw gen_op_dcbz_64_raw
! 3518: #define gen_op_dcbz_le_64_user gen_op_dcbz_64_user
! 3519: #define gen_op_dcbz_le_64_kernel gen_op_dcbz_64_kernel
! 3520: #define gen_op_dcbz_le_64_hypv gen_op_dcbz_64_hypv
! 3521: GEN_MEM_FUNCS(dcbz),
! 3522: },
1.1 root 3523: };
3524:
1.1.1.5 ! root 3525: static always_inline void handler_dcbz (DisasContext *ctx,
! 3526: int dcache_line_size)
1.1 root 3527: {
1.1.1.5 ! root 3528: int n;
! 3529:
! 3530: switch (dcache_line_size) {
! 3531: case 32:
! 3532: n = 0;
! 3533: break;
! 3534: case 64:
! 3535: n = 1;
! 3536: break;
! 3537: case 128:
! 3538: n = 2;
! 3539: break;
! 3540: default:
! 3541: n = 3;
! 3542: break;
1.1 root 3543: }
1.1.1.5 ! root 3544: op_dcbz(n);
! 3545: }
! 3546:
! 3547: GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
! 3548: {
! 3549: gen_addr_reg_index(ctx);
! 3550: handler_dcbz(ctx, ctx->dcache_line_size);
! 3551: gen_op_check_reservation();
! 3552: }
! 3553:
! 3554: GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
! 3555: {
! 3556: gen_addr_reg_index(ctx);
! 3557: if (ctx->opcode & 0x00200000)
! 3558: handler_dcbz(ctx, ctx->dcache_line_size);
! 3559: else
! 3560: handler_dcbz(ctx, -1);
1.1 root 3561: gen_op_check_reservation();
3562: }
3563:
3564: /* icbi */
1.1.1.5 ! root 3565: #define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
! 3566: #define gen_op_icbi_le_raw gen_op_icbi_raw
! 3567: #define gen_op_icbi_le_user gen_op_icbi_user
! 3568: #define gen_op_icbi_le_kernel gen_op_icbi_kernel
! 3569: #define gen_op_icbi_le_hypv gen_op_icbi_hypv
! 3570: #define gen_op_icbi_le_64_raw gen_op_icbi_64_raw
! 3571: #define gen_op_icbi_le_64_user gen_op_icbi_64_user
! 3572: #define gen_op_icbi_le_64_kernel gen_op_icbi_64_kernel
! 3573: #define gen_op_icbi_le_64_hypv gen_op_icbi_64_hypv
! 3574: static GenOpFunc *gen_op_icbi[NB_MEM_FUNCS] = {
! 3575: GEN_MEM_FUNCS(icbi),
! 3576: };
! 3577:
! 3578: GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
1.1 root 3579: {
1.1.1.5 ! root 3580: /* NIP cannot be restored if the memory exception comes from an helper */
! 3581: gen_update_nip(ctx, ctx->nip - 4);
! 3582: gen_addr_reg_index(ctx);
! 3583: op_icbi();
1.1 root 3584: }
3585:
3586: /* Optional: */
3587: /* dcba */
1.1.1.5 ! root 3588: GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
1.1 root 3589: {
1.1.1.5 ! root 3590: /* interpreted as no-op */
! 3591: /* XXX: specification say this is treated as a store by the MMU
! 3592: * but does not generate any exception
! 3593: */
1.1 root 3594: }
3595:
3596: /*** Segment register manipulation ***/
3597: /* Supervisor only: */
3598: /* mfsr */
3599: GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
3600: {
3601: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3602: GEN_EXCP_PRIVREG(ctx);
1.1 root 3603: #else
1.1.1.5 ! root 3604: if (unlikely(!ctx->supervisor)) {
! 3605: GEN_EXCP_PRIVREG(ctx);
1.1 root 3606: return;
3607: }
1.1.1.5 ! root 3608: gen_op_set_T1(SR(ctx->opcode));
! 3609: gen_op_load_sr();
1.1 root 3610: gen_op_store_T0_gpr(rD(ctx->opcode));
3611: #endif
3612: }
3613:
3614: /* mfsrin */
3615: GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
3616: {
3617: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3618: GEN_EXCP_PRIVREG(ctx);
1.1 root 3619: #else
1.1.1.5 ! root 3620: if (unlikely(!ctx->supervisor)) {
! 3621: GEN_EXCP_PRIVREG(ctx);
1.1 root 3622: return;
3623: }
3624: gen_op_load_gpr_T1(rB(ctx->opcode));
1.1.1.5 ! root 3625: gen_op_srli_T1(28);
! 3626: gen_op_load_sr();
1.1 root 3627: gen_op_store_T0_gpr(rD(ctx->opcode));
3628: #endif
3629: }
3630:
3631: /* mtsr */
3632: GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
3633: {
3634: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3635: GEN_EXCP_PRIVREG(ctx);
1.1 root 3636: #else
1.1.1.5 ! root 3637: if (unlikely(!ctx->supervisor)) {
! 3638: GEN_EXCP_PRIVREG(ctx);
1.1 root 3639: return;
3640: }
3641: gen_op_load_gpr_T0(rS(ctx->opcode));
1.1.1.5 ! root 3642: gen_op_set_T1(SR(ctx->opcode));
! 3643: gen_op_store_sr();
1.1 root 3644: #endif
3645: }
3646:
3647: /* mtsrin */
3648: GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
3649: {
3650: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3651: GEN_EXCP_PRIVREG(ctx);
1.1 root 3652: #else
1.1.1.5 ! root 3653: if (unlikely(!ctx->supervisor)) {
! 3654: GEN_EXCP_PRIVREG(ctx);
1.1 root 3655: return;
3656: }
3657: gen_op_load_gpr_T0(rS(ctx->opcode));
3658: gen_op_load_gpr_T1(rB(ctx->opcode));
1.1.1.5 ! root 3659: gen_op_srli_T1(28);
! 3660: gen_op_store_sr();
1.1 root 3661: #endif
3662: }
3663:
1.1.1.5 ! root 3664: #if defined(TARGET_PPC64)
! 3665: /* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
! 3666: /* mfsr */
! 3667: GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
1.1 root 3668: {
3669: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 3670: GEN_EXCP_PRIVREG(ctx);
1.1 root 3671: #else
1.1.1.5 ! root 3672: if (unlikely(!ctx->supervisor)) {
! 3673: GEN_EXCP_PRIVREG(ctx);
1.1 root 3674: return;
3675: }
1.1.1.5 ! root 3676: gen_op_set_T1(SR(ctx->opcode));
! 3677: gen_op_load_slb();
! 3678: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3679: #endif
! 3680: }
! 3681:
! 3682: /* mfsrin */
! 3683: GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
! 3684: PPC_SEGMENT_64B)
! 3685: {
! 3686: #if defined(CONFIG_USER_ONLY)
! 3687: GEN_EXCP_PRIVREG(ctx);
! 3688: #else
! 3689: if (unlikely(!ctx->supervisor)) {
! 3690: GEN_EXCP_PRIVREG(ctx);
! 3691: return;
! 3692: }
! 3693: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3694: gen_op_srli_T1(28);
! 3695: gen_op_load_slb();
! 3696: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3697: #endif
! 3698: }
! 3699:
! 3700: /* mtsr */
! 3701: GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
! 3702: {
! 3703: #if defined(CONFIG_USER_ONLY)
! 3704: GEN_EXCP_PRIVREG(ctx);
! 3705: #else
! 3706: if (unlikely(!ctx->supervisor)) {
! 3707: GEN_EXCP_PRIVREG(ctx);
! 3708: return;
! 3709: }
! 3710: gen_op_load_gpr_T0(rS(ctx->opcode));
! 3711: gen_op_set_T1(SR(ctx->opcode));
! 3712: gen_op_store_slb();
! 3713: #endif
! 3714: }
! 3715:
! 3716: /* mtsrin */
! 3717: GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
! 3718: PPC_SEGMENT_64B)
! 3719: {
! 3720: #if defined(CONFIG_USER_ONLY)
! 3721: GEN_EXCP_PRIVREG(ctx);
! 3722: #else
! 3723: if (unlikely(!ctx->supervisor)) {
! 3724: GEN_EXCP_PRIVREG(ctx);
! 3725: return;
! 3726: }
! 3727: gen_op_load_gpr_T0(rS(ctx->opcode));
! 3728: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3729: gen_op_srli_T1(28);
! 3730: gen_op_store_slb();
! 3731: #endif
! 3732: }
! 3733: #endif /* defined(TARGET_PPC64) */
! 3734:
! 3735: /*** Lookaside buffer management ***/
! 3736: /* Optional & supervisor only: */
! 3737: /* tlbia */
! 3738: GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
! 3739: {
! 3740: #if defined(CONFIG_USER_ONLY)
! 3741: GEN_EXCP_PRIVOPC(ctx);
! 3742: #else
! 3743: if (unlikely(!ctx->supervisor)) {
! 3744: GEN_EXCP_PRIVOPC(ctx);
! 3745: return;
! 3746: }
! 3747: gen_op_tlbia();
1.1 root 3748: #endif
3749: }
3750:
3751: /* tlbie */
1.1.1.5 ! root 3752: GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
! 3753: {
! 3754: #if defined(CONFIG_USER_ONLY)
! 3755: GEN_EXCP_PRIVOPC(ctx);
! 3756: #else
! 3757: if (unlikely(!ctx->supervisor)) {
! 3758: GEN_EXCP_PRIVOPC(ctx);
! 3759: return;
! 3760: }
! 3761: gen_op_load_gpr_T0(rB(ctx->opcode));
! 3762: #if defined(TARGET_PPC64)
! 3763: if (ctx->sf_mode)
! 3764: gen_op_tlbie_64();
! 3765: else
! 3766: #endif
! 3767: gen_op_tlbie();
! 3768: #endif
! 3769: }
! 3770:
! 3771: /* tlbsync */
! 3772: GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
! 3773: {
! 3774: #if defined(CONFIG_USER_ONLY)
! 3775: GEN_EXCP_PRIVOPC(ctx);
! 3776: #else
! 3777: if (unlikely(!ctx->supervisor)) {
! 3778: GEN_EXCP_PRIVOPC(ctx);
! 3779: return;
! 3780: }
! 3781: /* This has no effect: it should ensure that all previous
! 3782: * tlbie have completed
! 3783: */
! 3784: GEN_STOP(ctx);
! 3785: #endif
! 3786: }
! 3787:
! 3788: #if defined(TARGET_PPC64)
! 3789: /* slbia */
! 3790: GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
! 3791: {
! 3792: #if defined(CONFIG_USER_ONLY)
! 3793: GEN_EXCP_PRIVOPC(ctx);
! 3794: #else
! 3795: if (unlikely(!ctx->supervisor)) {
! 3796: GEN_EXCP_PRIVOPC(ctx);
! 3797: return;
! 3798: }
! 3799: gen_op_slbia();
! 3800: #endif
! 3801: }
! 3802:
! 3803: /* slbie */
! 3804: GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
! 3805: {
! 3806: #if defined(CONFIG_USER_ONLY)
! 3807: GEN_EXCP_PRIVOPC(ctx);
! 3808: #else
! 3809: if (unlikely(!ctx->supervisor)) {
! 3810: GEN_EXCP_PRIVOPC(ctx);
! 3811: return;
! 3812: }
! 3813: gen_op_load_gpr_T0(rB(ctx->opcode));
! 3814: gen_op_slbie();
! 3815: #endif
! 3816: }
! 3817: #endif
! 3818:
! 3819: /*** External control ***/
! 3820: /* Optional: */
! 3821: #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
! 3822: #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
! 3823: static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
! 3824: GEN_MEM_FUNCS(eciwx),
! 3825: };
! 3826: static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
! 3827: GEN_MEM_FUNCS(ecowx),
! 3828: };
! 3829:
! 3830: /* eciwx */
! 3831: GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
! 3832: {
! 3833: /* Should check EAR[E] & alignment ! */
! 3834: gen_addr_reg_index(ctx);
! 3835: op_eciwx();
! 3836: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3837: }
! 3838:
! 3839: /* ecowx */
! 3840: GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
! 3841: {
! 3842: /* Should check EAR[E] & alignment ! */
! 3843: gen_addr_reg_index(ctx);
! 3844: gen_op_load_gpr_T1(rS(ctx->opcode));
! 3845: op_ecowx();
! 3846: }
! 3847:
! 3848: /* PowerPC 601 specific instructions */
! 3849: /* abs - abs. */
! 3850: GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
! 3851: {
! 3852: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3853: gen_op_POWER_abs();
! 3854: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3855: if (unlikely(Rc(ctx->opcode) != 0))
! 3856: gen_set_Rc0(ctx);
! 3857: }
! 3858:
! 3859: /* abso - abso. */
! 3860: GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
! 3861: {
! 3862: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3863: gen_op_POWER_abso();
! 3864: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3865: if (unlikely(Rc(ctx->opcode) != 0))
! 3866: gen_set_Rc0(ctx);
! 3867: }
! 3868:
! 3869: /* clcs */
! 3870: GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
! 3871: {
! 3872: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3873: gen_op_POWER_clcs();
! 3874: /* Rc=1 sets CR0 to an undefined state */
! 3875: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3876: }
! 3877:
! 3878: /* div - div. */
! 3879: GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
! 3880: {
! 3881: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3882: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3883: gen_op_POWER_div();
! 3884: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3885: if (unlikely(Rc(ctx->opcode) != 0))
! 3886: gen_set_Rc0(ctx);
! 3887: }
! 3888:
! 3889: /* divo - divo. */
! 3890: GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
! 3891: {
! 3892: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3893: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3894: gen_op_POWER_divo();
! 3895: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3896: if (unlikely(Rc(ctx->opcode) != 0))
! 3897: gen_set_Rc0(ctx);
! 3898: }
! 3899:
! 3900: /* divs - divs. */
! 3901: GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
! 3902: {
! 3903: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3904: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3905: gen_op_POWER_divs();
! 3906: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3907: if (unlikely(Rc(ctx->opcode) != 0))
! 3908: gen_set_Rc0(ctx);
! 3909: }
! 3910:
! 3911: /* divso - divso. */
! 3912: GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
! 3913: {
! 3914: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3915: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3916: gen_op_POWER_divso();
! 3917: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3918: if (unlikely(Rc(ctx->opcode) != 0))
! 3919: gen_set_Rc0(ctx);
! 3920: }
! 3921:
! 3922: /* doz - doz. */
! 3923: GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
! 3924: {
! 3925: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3926: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3927: gen_op_POWER_doz();
! 3928: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3929: if (unlikely(Rc(ctx->opcode) != 0))
! 3930: gen_set_Rc0(ctx);
! 3931: }
! 3932:
! 3933: /* dozo - dozo. */
! 3934: GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
! 3935: {
! 3936: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3937: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3938: gen_op_POWER_dozo();
! 3939: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3940: if (unlikely(Rc(ctx->opcode) != 0))
! 3941: gen_set_Rc0(ctx);
! 3942: }
! 3943:
! 3944: /* dozi */
! 3945: GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
! 3946: {
! 3947: gen_op_load_gpr_T0(rA(ctx->opcode));
! 3948: gen_op_set_T1(SIMM(ctx->opcode));
! 3949: gen_op_POWER_doz();
! 3950: gen_op_store_T0_gpr(rD(ctx->opcode));
! 3951: }
! 3952:
! 3953: /* As lscbx load from memory byte after byte, it's always endian safe.
! 3954: * Original POWER is 32 bits only, define 64 bits ops as 32 bits ones
! 3955: */
! 3956: #define op_POWER_lscbx(start, ra, rb) \
! 3957: (*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
! 3958: #define gen_op_POWER_lscbx_64_raw gen_op_POWER_lscbx_raw
! 3959: #define gen_op_POWER_lscbx_64_user gen_op_POWER_lscbx_user
! 3960: #define gen_op_POWER_lscbx_64_kernel gen_op_POWER_lscbx_kernel
! 3961: #define gen_op_POWER_lscbx_64_hypv gen_op_POWER_lscbx_hypv
! 3962: #define gen_op_POWER_lscbx_le_raw gen_op_POWER_lscbx_raw
! 3963: #define gen_op_POWER_lscbx_le_user gen_op_POWER_lscbx_user
! 3964: #define gen_op_POWER_lscbx_le_kernel gen_op_POWER_lscbx_kernel
! 3965: #define gen_op_POWER_lscbx_le_hypv gen_op_POWER_lscbx_hypv
! 3966: #define gen_op_POWER_lscbx_le_64_raw gen_op_POWER_lscbx_raw
! 3967: #define gen_op_POWER_lscbx_le_64_user gen_op_POWER_lscbx_user
! 3968: #define gen_op_POWER_lscbx_le_64_kernel gen_op_POWER_lscbx_kernel
! 3969: #define gen_op_POWER_lscbx_le_64_hypv gen_op_POWER_lscbx_hypv
! 3970: static GenOpFunc3 *gen_op_POWER_lscbx[NB_MEM_FUNCS] = {
! 3971: GEN_MEM_FUNCS(POWER_lscbx),
! 3972: };
! 3973:
! 3974: /* lscbx - lscbx. */
! 3975: GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
! 3976: {
! 3977: int ra = rA(ctx->opcode);
! 3978: int rb = rB(ctx->opcode);
! 3979:
! 3980: gen_addr_reg_index(ctx);
! 3981: if (ra == 0) {
! 3982: ra = rb;
! 3983: }
! 3984: /* NIP cannot be restored if the memory exception comes from an helper */
! 3985: gen_update_nip(ctx, ctx->nip - 4);
! 3986: gen_op_load_xer_bc();
! 3987: gen_op_load_xer_cmp();
! 3988: op_POWER_lscbx(rD(ctx->opcode), ra, rb);
! 3989: gen_op_store_xer_bc();
! 3990: if (unlikely(Rc(ctx->opcode) != 0))
! 3991: gen_set_Rc0(ctx);
! 3992: }
! 3993:
! 3994: /* maskg - maskg. */
! 3995: GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
! 3996: {
! 3997: gen_op_load_gpr_T0(rS(ctx->opcode));
! 3998: gen_op_load_gpr_T1(rB(ctx->opcode));
! 3999: gen_op_POWER_maskg();
! 4000: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4001: if (unlikely(Rc(ctx->opcode) != 0))
! 4002: gen_set_Rc0(ctx);
! 4003: }
! 4004:
! 4005: /* maskir - maskir. */
! 4006: GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
! 4007: {
! 4008: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4009: gen_op_load_gpr_T1(rS(ctx->opcode));
! 4010: gen_op_load_gpr_T2(rB(ctx->opcode));
! 4011: gen_op_POWER_maskir();
! 4012: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4013: if (unlikely(Rc(ctx->opcode) != 0))
! 4014: gen_set_Rc0(ctx);
! 4015: }
! 4016:
! 4017: /* mul - mul. */
! 4018: GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
! 4019: {
! 4020: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4021: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4022: gen_op_POWER_mul();
! 4023: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4024: if (unlikely(Rc(ctx->opcode) != 0))
! 4025: gen_set_Rc0(ctx);
! 4026: }
! 4027:
! 4028: /* mulo - mulo. */
! 4029: GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
! 4030: {
! 4031: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4032: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4033: gen_op_POWER_mulo();
! 4034: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4035: if (unlikely(Rc(ctx->opcode) != 0))
! 4036: gen_set_Rc0(ctx);
! 4037: }
! 4038:
! 4039: /* nabs - nabs. */
! 4040: GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
! 4041: {
! 4042: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4043: gen_op_POWER_nabs();
! 4044: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4045: if (unlikely(Rc(ctx->opcode) != 0))
! 4046: gen_set_Rc0(ctx);
! 4047: }
! 4048:
! 4049: /* nabso - nabso. */
! 4050: GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
! 4051: {
! 4052: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4053: gen_op_POWER_nabso();
! 4054: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4055: if (unlikely(Rc(ctx->opcode) != 0))
! 4056: gen_set_Rc0(ctx);
! 4057: }
! 4058:
! 4059: /* rlmi - rlmi. */
! 4060: GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
! 4061: {
! 4062: uint32_t mb, me;
! 4063:
! 4064: mb = MB(ctx->opcode);
! 4065: me = ME(ctx->opcode);
! 4066: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4067: gen_op_load_gpr_T1(rA(ctx->opcode));
! 4068: gen_op_load_gpr_T2(rB(ctx->opcode));
! 4069: gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
! 4070: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4071: if (unlikely(Rc(ctx->opcode) != 0))
! 4072: gen_set_Rc0(ctx);
! 4073: }
! 4074:
! 4075: /* rrib - rrib. */
! 4076: GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
! 4077: {
! 4078: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4079: gen_op_load_gpr_T1(rA(ctx->opcode));
! 4080: gen_op_load_gpr_T2(rB(ctx->opcode));
! 4081: gen_op_POWER_rrib();
! 4082: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4083: if (unlikely(Rc(ctx->opcode) != 0))
! 4084: gen_set_Rc0(ctx);
! 4085: }
! 4086:
! 4087: /* sle - sle. */
! 4088: GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
! 4089: {
! 4090: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4091: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4092: gen_op_POWER_sle();
! 4093: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4094: if (unlikely(Rc(ctx->opcode) != 0))
! 4095: gen_set_Rc0(ctx);
! 4096: }
! 4097:
! 4098: /* sleq - sleq. */
! 4099: GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
! 4100: {
! 4101: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4102: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4103: gen_op_POWER_sleq();
! 4104: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4105: if (unlikely(Rc(ctx->opcode) != 0))
! 4106: gen_set_Rc0(ctx);
! 4107: }
! 4108:
! 4109: /* sliq - sliq. */
! 4110: GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
! 4111: {
! 4112: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4113: gen_op_set_T1(SH(ctx->opcode));
! 4114: gen_op_POWER_sle();
! 4115: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4116: if (unlikely(Rc(ctx->opcode) != 0))
! 4117: gen_set_Rc0(ctx);
! 4118: }
! 4119:
! 4120: /* slliq - slliq. */
! 4121: GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
! 4122: {
! 4123: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4124: gen_op_set_T1(SH(ctx->opcode));
! 4125: gen_op_POWER_sleq();
! 4126: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4127: if (unlikely(Rc(ctx->opcode) != 0))
! 4128: gen_set_Rc0(ctx);
! 4129: }
! 4130:
! 4131: /* sllq - sllq. */
! 4132: GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
! 4133: {
! 4134: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4135: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4136: gen_op_POWER_sllq();
! 4137: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4138: if (unlikely(Rc(ctx->opcode) != 0))
! 4139: gen_set_Rc0(ctx);
! 4140: }
! 4141:
! 4142: /* slq - slq. */
! 4143: GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
! 4144: {
! 4145: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4146: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4147: gen_op_POWER_slq();
! 4148: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4149: if (unlikely(Rc(ctx->opcode) != 0))
! 4150: gen_set_Rc0(ctx);
! 4151: }
! 4152:
! 4153: /* sraiq - sraiq. */
! 4154: GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
! 4155: {
! 4156: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4157: gen_op_set_T1(SH(ctx->opcode));
! 4158: gen_op_POWER_sraq();
! 4159: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4160: if (unlikely(Rc(ctx->opcode) != 0))
! 4161: gen_set_Rc0(ctx);
! 4162: }
! 4163:
! 4164: /* sraq - sraq. */
! 4165: GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
! 4166: {
! 4167: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4168: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4169: gen_op_POWER_sraq();
! 4170: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4171: if (unlikely(Rc(ctx->opcode) != 0))
! 4172: gen_set_Rc0(ctx);
! 4173: }
! 4174:
! 4175: /* sre - sre. */
! 4176: GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
! 4177: {
! 4178: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4179: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4180: gen_op_POWER_sre();
! 4181: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4182: if (unlikely(Rc(ctx->opcode) != 0))
! 4183: gen_set_Rc0(ctx);
! 4184: }
! 4185:
! 4186: /* srea - srea. */
! 4187: GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
! 4188: {
! 4189: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4190: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4191: gen_op_POWER_srea();
! 4192: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4193: if (unlikely(Rc(ctx->opcode) != 0))
! 4194: gen_set_Rc0(ctx);
! 4195: }
! 4196:
! 4197: /* sreq */
! 4198: GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
! 4199: {
! 4200: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4201: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4202: gen_op_POWER_sreq();
! 4203: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4204: if (unlikely(Rc(ctx->opcode) != 0))
! 4205: gen_set_Rc0(ctx);
! 4206: }
! 4207:
! 4208: /* sriq */
! 4209: GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
! 4210: {
! 4211: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4212: gen_op_set_T1(SH(ctx->opcode));
! 4213: gen_op_POWER_srq();
! 4214: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4215: if (unlikely(Rc(ctx->opcode) != 0))
! 4216: gen_set_Rc0(ctx);
! 4217: }
! 4218:
! 4219: /* srliq */
! 4220: GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
! 4221: {
! 4222: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4223: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4224: gen_op_set_T1(SH(ctx->opcode));
! 4225: gen_op_POWER_srlq();
! 4226: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4227: if (unlikely(Rc(ctx->opcode) != 0))
! 4228: gen_set_Rc0(ctx);
! 4229: }
! 4230:
! 4231: /* srlq */
! 4232: GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
! 4233: {
! 4234: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4235: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4236: gen_op_POWER_srlq();
! 4237: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4238: if (unlikely(Rc(ctx->opcode) != 0))
! 4239: gen_set_Rc0(ctx);
! 4240: }
! 4241:
! 4242: /* srq */
! 4243: GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
! 4244: {
! 4245: gen_op_load_gpr_T0(rS(ctx->opcode));
! 4246: gen_op_load_gpr_T1(rB(ctx->opcode));
! 4247: gen_op_POWER_srq();
! 4248: gen_op_store_T0_gpr(rA(ctx->opcode));
! 4249: if (unlikely(Rc(ctx->opcode) != 0))
! 4250: gen_set_Rc0(ctx);
! 4251: }
! 4252:
! 4253: /* PowerPC 602 specific instructions */
! 4254: /* dsa */
! 4255: GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
! 4256: {
! 4257: /* XXX: TODO */
! 4258: GEN_EXCP_INVAL(ctx);
! 4259: }
! 4260:
! 4261: /* esa */
! 4262: GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
! 4263: {
! 4264: /* XXX: TODO */
! 4265: GEN_EXCP_INVAL(ctx);
! 4266: }
! 4267:
! 4268: /* mfrom */
! 4269: GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
! 4270: {
! 4271: #if defined(CONFIG_USER_ONLY)
! 4272: GEN_EXCP_PRIVOPC(ctx);
! 4273: #else
! 4274: if (unlikely(!ctx->supervisor)) {
! 4275: GEN_EXCP_PRIVOPC(ctx);
! 4276: return;
! 4277: }
! 4278: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4279: gen_op_602_mfrom();
! 4280: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4281: #endif
! 4282: }
! 4283:
! 4284: /* 602 - 603 - G2 TLB management */
! 4285: /* tlbld */
! 4286: GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
! 4287: {
! 4288: #if defined(CONFIG_USER_ONLY)
! 4289: GEN_EXCP_PRIVOPC(ctx);
! 4290: #else
! 4291: if (unlikely(!ctx->supervisor)) {
! 4292: GEN_EXCP_PRIVOPC(ctx);
! 4293: return;
! 4294: }
! 4295: gen_op_load_gpr_T0(rB(ctx->opcode));
! 4296: gen_op_6xx_tlbld();
! 4297: #endif
! 4298: }
! 4299:
! 4300: /* tlbli */
! 4301: GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
! 4302: {
! 4303: #if defined(CONFIG_USER_ONLY)
! 4304: GEN_EXCP_PRIVOPC(ctx);
! 4305: #else
! 4306: if (unlikely(!ctx->supervisor)) {
! 4307: GEN_EXCP_PRIVOPC(ctx);
! 4308: return;
! 4309: }
! 4310: gen_op_load_gpr_T0(rB(ctx->opcode));
! 4311: gen_op_6xx_tlbli();
! 4312: #endif
! 4313: }
! 4314:
! 4315: /* 74xx TLB management */
! 4316: /* tlbld */
! 4317: GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
! 4318: {
! 4319: #if defined(CONFIG_USER_ONLY)
! 4320: GEN_EXCP_PRIVOPC(ctx);
! 4321: #else
! 4322: if (unlikely(!ctx->supervisor)) {
! 4323: GEN_EXCP_PRIVOPC(ctx);
! 4324: return;
! 4325: }
! 4326: gen_op_load_gpr_T0(rB(ctx->opcode));
! 4327: gen_op_74xx_tlbld();
! 4328: #endif
! 4329: }
! 4330:
! 4331: /* tlbli */
! 4332: GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
! 4333: {
! 4334: #if defined(CONFIG_USER_ONLY)
! 4335: GEN_EXCP_PRIVOPC(ctx);
! 4336: #else
! 4337: if (unlikely(!ctx->supervisor)) {
! 4338: GEN_EXCP_PRIVOPC(ctx);
! 4339: return;
! 4340: }
! 4341: gen_op_load_gpr_T0(rB(ctx->opcode));
! 4342: gen_op_74xx_tlbli();
! 4343: #endif
! 4344: }
! 4345:
! 4346: /* POWER instructions not in PowerPC 601 */
! 4347: /* clf */
! 4348: GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
! 4349: {
! 4350: /* Cache line flush: implemented as no-op */
! 4351: }
! 4352:
! 4353: /* cli */
! 4354: GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
! 4355: {
! 4356: /* Cache line invalidate: privileged and treated as no-op */
! 4357: #if defined(CONFIG_USER_ONLY)
! 4358: GEN_EXCP_PRIVOPC(ctx);
! 4359: #else
! 4360: if (unlikely(!ctx->supervisor)) {
! 4361: GEN_EXCP_PRIVOPC(ctx);
! 4362: return;
! 4363: }
! 4364: #endif
! 4365: }
! 4366:
! 4367: /* dclst */
! 4368: GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
! 4369: {
! 4370: /* Data cache line store: treated as no-op */
! 4371: }
! 4372:
! 4373: GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
! 4374: {
! 4375: #if defined(CONFIG_USER_ONLY)
! 4376: GEN_EXCP_PRIVOPC(ctx);
! 4377: #else
! 4378: if (unlikely(!ctx->supervisor)) {
! 4379: GEN_EXCP_PRIVOPC(ctx);
! 4380: return;
! 4381: }
! 4382: int ra = rA(ctx->opcode);
! 4383: int rd = rD(ctx->opcode);
! 4384:
! 4385: gen_addr_reg_index(ctx);
! 4386: gen_op_POWER_mfsri();
! 4387: gen_op_store_T0_gpr(rd);
! 4388: if (ra != 0 && ra != rd)
! 4389: gen_op_store_T1_gpr(ra);
! 4390: #endif
! 4391: }
! 4392:
! 4393: GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
! 4394: {
! 4395: #if defined(CONFIG_USER_ONLY)
! 4396: GEN_EXCP_PRIVOPC(ctx);
! 4397: #else
! 4398: if (unlikely(!ctx->supervisor)) {
! 4399: GEN_EXCP_PRIVOPC(ctx);
! 4400: return;
! 4401: }
! 4402: gen_addr_reg_index(ctx);
! 4403: gen_op_POWER_rac();
! 4404: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4405: #endif
! 4406: }
! 4407:
! 4408: GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
! 4409: {
! 4410: #if defined(CONFIG_USER_ONLY)
! 4411: GEN_EXCP_PRIVOPC(ctx);
! 4412: #else
! 4413: if (unlikely(!ctx->supervisor)) {
! 4414: GEN_EXCP_PRIVOPC(ctx);
! 4415: return;
! 4416: }
! 4417: gen_op_POWER_rfsvc();
! 4418: GEN_SYNC(ctx);
! 4419: #endif
! 4420: }
! 4421:
! 4422: /* svc is not implemented for now */
! 4423:
! 4424: /* POWER2 specific instructions */
! 4425: /* Quad manipulation (load/store two floats at a time) */
! 4426: /* Original POWER2 is 32 bits only, define 64 bits ops as 32 bits ones */
! 4427: #define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
! 4428: #define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
! 4429: #define gen_op_POWER2_lfq_64_raw gen_op_POWER2_lfq_raw
! 4430: #define gen_op_POWER2_lfq_64_user gen_op_POWER2_lfq_user
! 4431: #define gen_op_POWER2_lfq_64_kernel gen_op_POWER2_lfq_kernel
! 4432: #define gen_op_POWER2_lfq_64_hypv gen_op_POWER2_lfq_hypv
! 4433: #define gen_op_POWER2_lfq_le_64_raw gen_op_POWER2_lfq_le_raw
! 4434: #define gen_op_POWER2_lfq_le_64_user gen_op_POWER2_lfq_le_user
! 4435: #define gen_op_POWER2_lfq_le_64_kernel gen_op_POWER2_lfq_le_kernel
! 4436: #define gen_op_POWER2_lfq_le_64_hypv gen_op_POWER2_lfq_le_hypv
! 4437: #define gen_op_POWER2_stfq_64_raw gen_op_POWER2_stfq_raw
! 4438: #define gen_op_POWER2_stfq_64_user gen_op_POWER2_stfq_user
! 4439: #define gen_op_POWER2_stfq_64_kernel gen_op_POWER2_stfq_kernel
! 4440: #define gen_op_POWER2_stfq_64_hypv gen_op_POWER2_stfq_hypv
! 4441: #define gen_op_POWER2_stfq_le_64_raw gen_op_POWER2_stfq_le_raw
! 4442: #define gen_op_POWER2_stfq_le_64_user gen_op_POWER2_stfq_le_user
! 4443: #define gen_op_POWER2_stfq_le_64_kernel gen_op_POWER2_stfq_le_kernel
! 4444: #define gen_op_POWER2_stfq_le_64_hypv gen_op_POWER2_stfq_le_hypv
! 4445: static GenOpFunc *gen_op_POWER2_lfq[NB_MEM_FUNCS] = {
! 4446: GEN_MEM_FUNCS(POWER2_lfq),
! 4447: };
! 4448: static GenOpFunc *gen_op_POWER2_stfq[NB_MEM_FUNCS] = {
! 4449: GEN_MEM_FUNCS(POWER2_stfq),
! 4450: };
! 4451:
! 4452: /* lfq */
! 4453: GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
! 4454: {
! 4455: /* NIP cannot be restored if the memory exception comes from an helper */
! 4456: gen_update_nip(ctx, ctx->nip - 4);
! 4457: gen_addr_imm_index(ctx, 0);
! 4458: op_POWER2_lfq();
! 4459: gen_op_store_FT0_fpr(rD(ctx->opcode));
! 4460: gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
! 4461: }
! 4462:
! 4463: /* lfqu */
! 4464: GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
! 4465: {
! 4466: int ra = rA(ctx->opcode);
! 4467:
! 4468: /* NIP cannot be restored if the memory exception comes from an helper */
! 4469: gen_update_nip(ctx, ctx->nip - 4);
! 4470: gen_addr_imm_index(ctx, 0);
! 4471: op_POWER2_lfq();
! 4472: gen_op_store_FT0_fpr(rD(ctx->opcode));
! 4473: gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
! 4474: if (ra != 0)
! 4475: gen_op_store_T0_gpr(ra);
! 4476: }
! 4477:
! 4478: /* lfqux */
! 4479: GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
! 4480: {
! 4481: int ra = rA(ctx->opcode);
! 4482:
! 4483: /* NIP cannot be restored if the memory exception comes from an helper */
! 4484: gen_update_nip(ctx, ctx->nip - 4);
! 4485: gen_addr_reg_index(ctx);
! 4486: op_POWER2_lfq();
! 4487: gen_op_store_FT0_fpr(rD(ctx->opcode));
! 4488: gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
! 4489: if (ra != 0)
! 4490: gen_op_store_T0_gpr(ra);
! 4491: }
! 4492:
! 4493: /* lfqx */
! 4494: GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
! 4495: {
! 4496: /* NIP cannot be restored if the memory exception comes from an helper */
! 4497: gen_update_nip(ctx, ctx->nip - 4);
! 4498: gen_addr_reg_index(ctx);
! 4499: op_POWER2_lfq();
! 4500: gen_op_store_FT0_fpr(rD(ctx->opcode));
! 4501: gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
! 4502: }
! 4503:
! 4504: /* stfq */
! 4505: GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
! 4506: {
! 4507: /* NIP cannot be restored if the memory exception comes from an helper */
! 4508: gen_update_nip(ctx, ctx->nip - 4);
! 4509: gen_addr_imm_index(ctx, 0);
! 4510: gen_op_load_fpr_FT0(rS(ctx->opcode));
! 4511: gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
! 4512: op_POWER2_stfq();
! 4513: }
! 4514:
! 4515: /* stfqu */
! 4516: GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
! 4517: {
! 4518: int ra = rA(ctx->opcode);
! 4519:
! 4520: /* NIP cannot be restored if the memory exception comes from an helper */
! 4521: gen_update_nip(ctx, ctx->nip - 4);
! 4522: gen_addr_imm_index(ctx, 0);
! 4523: gen_op_load_fpr_FT0(rS(ctx->opcode));
! 4524: gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
! 4525: op_POWER2_stfq();
! 4526: if (ra != 0)
! 4527: gen_op_store_T0_gpr(ra);
! 4528: }
! 4529:
! 4530: /* stfqux */
! 4531: GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
! 4532: {
! 4533: int ra = rA(ctx->opcode);
! 4534:
! 4535: /* NIP cannot be restored if the memory exception comes from an helper */
! 4536: gen_update_nip(ctx, ctx->nip - 4);
! 4537: gen_addr_reg_index(ctx);
! 4538: gen_op_load_fpr_FT0(rS(ctx->opcode));
! 4539: gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
! 4540: op_POWER2_stfq();
! 4541: if (ra != 0)
! 4542: gen_op_store_T0_gpr(ra);
! 4543: }
! 4544:
! 4545: /* stfqx */
! 4546: GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
! 4547: {
! 4548: /* NIP cannot be restored if the memory exception comes from an helper */
! 4549: gen_update_nip(ctx, ctx->nip - 4);
! 4550: gen_addr_reg_index(ctx);
! 4551: gen_op_load_fpr_FT0(rS(ctx->opcode));
! 4552: gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
! 4553: op_POWER2_stfq();
! 4554: }
! 4555:
! 4556: /* BookE specific instructions */
! 4557: /* XXX: not implemented on 440 ? */
! 4558: GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
! 4559: {
! 4560: /* XXX: TODO */
! 4561: GEN_EXCP_INVAL(ctx);
! 4562: }
! 4563:
! 4564: /* XXX: not implemented on 440 ? */
! 4565: GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
! 4566: {
! 4567: #if defined(CONFIG_USER_ONLY)
! 4568: GEN_EXCP_PRIVOPC(ctx);
! 4569: #else
! 4570: if (unlikely(!ctx->supervisor)) {
! 4571: GEN_EXCP_PRIVOPC(ctx);
! 4572: return;
! 4573: }
! 4574: gen_addr_reg_index(ctx);
! 4575: /* Use the same micro-ops as for tlbie */
! 4576: #if defined(TARGET_PPC64)
! 4577: if (ctx->sf_mode)
! 4578: gen_op_tlbie_64();
! 4579: else
! 4580: #endif
! 4581: gen_op_tlbie();
! 4582: #endif
! 4583: }
! 4584:
! 4585: /* All 405 MAC instructions are translated here */
! 4586: static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
! 4587: int opc2, int opc3,
! 4588: int ra, int rb, int rt, int Rc)
! 4589: {
! 4590: gen_op_load_gpr_T0(ra);
! 4591: gen_op_load_gpr_T1(rb);
! 4592: switch (opc3 & 0x0D) {
! 4593: case 0x05:
! 4594: /* macchw - macchw. - macchwo - macchwo. */
! 4595: /* macchws - macchws. - macchwso - macchwso. */
! 4596: /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
! 4597: /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
! 4598: /* mulchw - mulchw. */
! 4599: gen_op_405_mulchw();
! 4600: break;
! 4601: case 0x04:
! 4602: /* macchwu - macchwu. - macchwuo - macchwuo. */
! 4603: /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
! 4604: /* mulchwu - mulchwu. */
! 4605: gen_op_405_mulchwu();
! 4606: break;
! 4607: case 0x01:
! 4608: /* machhw - machhw. - machhwo - machhwo. */
! 4609: /* machhws - machhws. - machhwso - machhwso. */
! 4610: /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
! 4611: /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
! 4612: /* mulhhw - mulhhw. */
! 4613: gen_op_405_mulhhw();
! 4614: break;
! 4615: case 0x00:
! 4616: /* machhwu - machhwu. - machhwuo - machhwuo. */
! 4617: /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
! 4618: /* mulhhwu - mulhhwu. */
! 4619: gen_op_405_mulhhwu();
! 4620: break;
! 4621: case 0x0D:
! 4622: /* maclhw - maclhw. - maclhwo - maclhwo. */
! 4623: /* maclhws - maclhws. - maclhwso - maclhwso. */
! 4624: /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
! 4625: /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
! 4626: /* mullhw - mullhw. */
! 4627: gen_op_405_mullhw();
! 4628: break;
! 4629: case 0x0C:
! 4630: /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
! 4631: /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
! 4632: /* mullhwu - mullhwu. */
! 4633: gen_op_405_mullhwu();
! 4634: break;
! 4635: }
! 4636: if (opc2 & 0x02) {
! 4637: /* nmultiply-and-accumulate (0x0E) */
! 4638: gen_op_neg();
! 4639: }
! 4640: if (opc2 & 0x04) {
! 4641: /* (n)multiply-and-accumulate (0x0C - 0x0E) */
! 4642: gen_op_load_gpr_T2(rt);
! 4643: gen_op_move_T1_T0();
! 4644: gen_op_405_add_T0_T2();
! 4645: }
! 4646: if (opc3 & 0x10) {
! 4647: /* Check overflow */
! 4648: if (opc3 & 0x01)
! 4649: gen_op_check_addo();
! 4650: else
! 4651: gen_op_405_check_ovu();
! 4652: }
! 4653: if (opc3 & 0x02) {
! 4654: /* Saturate */
! 4655: if (opc3 & 0x01)
! 4656: gen_op_405_check_sat();
! 4657: else
! 4658: gen_op_405_check_satu();
! 4659: }
! 4660: gen_op_store_T0_gpr(rt);
! 4661: if (unlikely(Rc) != 0) {
! 4662: /* Update Rc0 */
! 4663: gen_set_Rc0(ctx);
! 4664: }
! 4665: }
! 4666:
! 4667: #define GEN_MAC_HANDLER(name, opc2, opc3) \
! 4668: GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
! 4669: { \
! 4670: gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
! 4671: rD(ctx->opcode), Rc(ctx->opcode)); \
! 4672: }
! 4673:
! 4674: /* macchw - macchw. */
! 4675: GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
! 4676: /* macchwo - macchwo. */
! 4677: GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
! 4678: /* macchws - macchws. */
! 4679: GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
! 4680: /* macchwso - macchwso. */
! 4681: GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
! 4682: /* macchwsu - macchwsu. */
! 4683: GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
! 4684: /* macchwsuo - macchwsuo. */
! 4685: GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
! 4686: /* macchwu - macchwu. */
! 4687: GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
! 4688: /* macchwuo - macchwuo. */
! 4689: GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
! 4690: /* machhw - machhw. */
! 4691: GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
! 4692: /* machhwo - machhwo. */
! 4693: GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
! 4694: /* machhws - machhws. */
! 4695: GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
! 4696: /* machhwso - machhwso. */
! 4697: GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
! 4698: /* machhwsu - machhwsu. */
! 4699: GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
! 4700: /* machhwsuo - machhwsuo. */
! 4701: GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
! 4702: /* machhwu - machhwu. */
! 4703: GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
! 4704: /* machhwuo - machhwuo. */
! 4705: GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
! 4706: /* maclhw - maclhw. */
! 4707: GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
! 4708: /* maclhwo - maclhwo. */
! 4709: GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
! 4710: /* maclhws - maclhws. */
! 4711: GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
! 4712: /* maclhwso - maclhwso. */
! 4713: GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
! 4714: /* maclhwu - maclhwu. */
! 4715: GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
! 4716: /* maclhwuo - maclhwuo. */
! 4717: GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
! 4718: /* maclhwsu - maclhwsu. */
! 4719: GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
! 4720: /* maclhwsuo - maclhwsuo. */
! 4721: GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
! 4722: /* nmacchw - nmacchw. */
! 4723: GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
! 4724: /* nmacchwo - nmacchwo. */
! 4725: GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
! 4726: /* nmacchws - nmacchws. */
! 4727: GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
! 4728: /* nmacchwso - nmacchwso. */
! 4729: GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
! 4730: /* nmachhw - nmachhw. */
! 4731: GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
! 4732: /* nmachhwo - nmachhwo. */
! 4733: GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
! 4734: /* nmachhws - nmachhws. */
! 4735: GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
! 4736: /* nmachhwso - nmachhwso. */
! 4737: GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
! 4738: /* nmaclhw - nmaclhw. */
! 4739: GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
! 4740: /* nmaclhwo - nmaclhwo. */
! 4741: GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
! 4742: /* nmaclhws - nmaclhws. */
! 4743: GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
! 4744: /* nmaclhwso - nmaclhwso. */
! 4745: GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
! 4746:
! 4747: /* mulchw - mulchw. */
! 4748: GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
! 4749: /* mulchwu - mulchwu. */
! 4750: GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
! 4751: /* mulhhw - mulhhw. */
! 4752: GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
! 4753: /* mulhhwu - mulhhwu. */
! 4754: GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
! 4755: /* mullhw - mullhw. */
! 4756: GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
! 4757: /* mullhwu - mullhwu. */
! 4758: GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
! 4759:
! 4760: /* mfdcr */
! 4761: GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
! 4762: {
! 4763: #if defined(CONFIG_USER_ONLY)
! 4764: GEN_EXCP_PRIVREG(ctx);
! 4765: #else
! 4766: uint32_t dcrn = SPR(ctx->opcode);
! 4767:
! 4768: if (unlikely(!ctx->supervisor)) {
! 4769: GEN_EXCP_PRIVREG(ctx);
! 4770: return;
! 4771: }
! 4772: gen_op_set_T0(dcrn);
! 4773: gen_op_load_dcr();
! 4774: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4775: #endif
! 4776: }
! 4777:
! 4778: /* mtdcr */
! 4779: GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
! 4780: {
! 4781: #if defined(CONFIG_USER_ONLY)
! 4782: GEN_EXCP_PRIVREG(ctx);
! 4783: #else
! 4784: uint32_t dcrn = SPR(ctx->opcode);
! 4785:
! 4786: if (unlikely(!ctx->supervisor)) {
! 4787: GEN_EXCP_PRIVREG(ctx);
! 4788: return;
! 4789: }
! 4790: gen_op_set_T0(dcrn);
! 4791: gen_op_load_gpr_T1(rS(ctx->opcode));
! 4792: gen_op_store_dcr();
! 4793: #endif
! 4794: }
! 4795:
! 4796: /* mfdcrx */
! 4797: /* XXX: not implemented on 440 ? */
! 4798: GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
! 4799: {
! 4800: #if defined(CONFIG_USER_ONLY)
! 4801: GEN_EXCP_PRIVREG(ctx);
! 4802: #else
! 4803: if (unlikely(!ctx->supervisor)) {
! 4804: GEN_EXCP_PRIVREG(ctx);
! 4805: return;
! 4806: }
! 4807: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4808: gen_op_load_dcr();
! 4809: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4810: /* Note: Rc update flag set leads to undefined state of Rc0 */
! 4811: #endif
! 4812: }
! 4813:
! 4814: /* mtdcrx */
! 4815: /* XXX: not implemented on 440 ? */
! 4816: GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
! 4817: {
! 4818: #if defined(CONFIG_USER_ONLY)
! 4819: GEN_EXCP_PRIVREG(ctx);
! 4820: #else
! 4821: if (unlikely(!ctx->supervisor)) {
! 4822: GEN_EXCP_PRIVREG(ctx);
! 4823: return;
! 4824: }
! 4825: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4826: gen_op_load_gpr_T1(rS(ctx->opcode));
! 4827: gen_op_store_dcr();
! 4828: /* Note: Rc update flag set leads to undefined state of Rc0 */
! 4829: #endif
! 4830: }
! 4831:
! 4832: /* mfdcrux (PPC 460) : user-mode access to DCR */
! 4833: GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
! 4834: {
! 4835: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4836: gen_op_load_dcr();
! 4837: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4838: /* Note: Rc update flag set leads to undefined state of Rc0 */
! 4839: }
! 4840:
! 4841: /* mtdcrux (PPC 460) : user-mode access to DCR */
! 4842: GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
! 4843: {
! 4844: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4845: gen_op_load_gpr_T1(rS(ctx->opcode));
! 4846: gen_op_store_dcr();
! 4847: /* Note: Rc update flag set leads to undefined state of Rc0 */
! 4848: }
! 4849:
! 4850: /* dccci */
! 4851: GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
! 4852: {
! 4853: #if defined(CONFIG_USER_ONLY)
! 4854: GEN_EXCP_PRIVOPC(ctx);
! 4855: #else
! 4856: if (unlikely(!ctx->supervisor)) {
! 4857: GEN_EXCP_PRIVOPC(ctx);
! 4858: return;
! 4859: }
! 4860: /* interpreted as no-op */
! 4861: #endif
! 4862: }
! 4863:
! 4864: /* dcread */
! 4865: GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
! 4866: {
! 4867: #if defined(CONFIG_USER_ONLY)
! 4868: GEN_EXCP_PRIVOPC(ctx);
! 4869: #else
! 4870: if (unlikely(!ctx->supervisor)) {
! 4871: GEN_EXCP_PRIVOPC(ctx);
! 4872: return;
! 4873: }
! 4874: gen_addr_reg_index(ctx);
! 4875: op_ldst(lwz);
! 4876: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4877: #endif
! 4878: }
! 4879:
! 4880: /* icbt */
! 4881: GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
! 4882: {
! 4883: /* interpreted as no-op */
! 4884: /* XXX: specification say this is treated as a load by the MMU
! 4885: * but does not generate any exception
! 4886: */
! 4887: }
! 4888:
! 4889: /* iccci */
! 4890: GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
! 4891: {
! 4892: #if defined(CONFIG_USER_ONLY)
! 4893: GEN_EXCP_PRIVOPC(ctx);
! 4894: #else
! 4895: if (unlikely(!ctx->supervisor)) {
! 4896: GEN_EXCP_PRIVOPC(ctx);
! 4897: return;
! 4898: }
! 4899: /* interpreted as no-op */
! 4900: #endif
! 4901: }
! 4902:
! 4903: /* icread */
! 4904: GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
! 4905: {
! 4906: #if defined(CONFIG_USER_ONLY)
! 4907: GEN_EXCP_PRIVOPC(ctx);
! 4908: #else
! 4909: if (unlikely(!ctx->supervisor)) {
! 4910: GEN_EXCP_PRIVOPC(ctx);
! 4911: return;
! 4912: }
! 4913: /* interpreted as no-op */
! 4914: #endif
! 4915: }
! 4916:
! 4917: /* rfci (supervisor only) */
! 4918: GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
! 4919: {
! 4920: #if defined(CONFIG_USER_ONLY)
! 4921: GEN_EXCP_PRIVOPC(ctx);
! 4922: #else
! 4923: if (unlikely(!ctx->supervisor)) {
! 4924: GEN_EXCP_PRIVOPC(ctx);
! 4925: return;
! 4926: }
! 4927: /* Restore CPU state */
! 4928: gen_op_40x_rfci();
! 4929: GEN_SYNC(ctx);
! 4930: #endif
! 4931: }
! 4932:
! 4933: GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
! 4934: {
! 4935: #if defined(CONFIG_USER_ONLY)
! 4936: GEN_EXCP_PRIVOPC(ctx);
! 4937: #else
! 4938: if (unlikely(!ctx->supervisor)) {
! 4939: GEN_EXCP_PRIVOPC(ctx);
! 4940: return;
! 4941: }
! 4942: /* Restore CPU state */
! 4943: gen_op_rfci();
! 4944: GEN_SYNC(ctx);
! 4945: #endif
! 4946: }
! 4947:
! 4948: /* BookE specific */
! 4949: /* XXX: not implemented on 440 ? */
! 4950: GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
! 4951: {
! 4952: #if defined(CONFIG_USER_ONLY)
! 4953: GEN_EXCP_PRIVOPC(ctx);
! 4954: #else
! 4955: if (unlikely(!ctx->supervisor)) {
! 4956: GEN_EXCP_PRIVOPC(ctx);
! 4957: return;
! 4958: }
! 4959: /* Restore CPU state */
! 4960: gen_op_rfdi();
! 4961: GEN_SYNC(ctx);
! 4962: #endif
! 4963: }
! 4964:
! 4965: /* XXX: not implemented on 440 ? */
! 4966: GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
! 4967: {
! 4968: #if defined(CONFIG_USER_ONLY)
! 4969: GEN_EXCP_PRIVOPC(ctx);
! 4970: #else
! 4971: if (unlikely(!ctx->supervisor)) {
! 4972: GEN_EXCP_PRIVOPC(ctx);
! 4973: return;
! 4974: }
! 4975: /* Restore CPU state */
! 4976: gen_op_rfmci();
! 4977: GEN_SYNC(ctx);
! 4978: #endif
! 4979: }
! 4980:
! 4981: /* TLB management - PowerPC 405 implementation */
! 4982: /* tlbre */
! 4983: GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
! 4984: {
! 4985: #if defined(CONFIG_USER_ONLY)
! 4986: GEN_EXCP_PRIVOPC(ctx);
! 4987: #else
! 4988: if (unlikely(!ctx->supervisor)) {
! 4989: GEN_EXCP_PRIVOPC(ctx);
! 4990: return;
! 4991: }
! 4992: switch (rB(ctx->opcode)) {
! 4993: case 0:
! 4994: gen_op_load_gpr_T0(rA(ctx->opcode));
! 4995: gen_op_4xx_tlbre_hi();
! 4996: gen_op_store_T0_gpr(rD(ctx->opcode));
! 4997: break;
! 4998: case 1:
! 4999: gen_op_load_gpr_T0(rA(ctx->opcode));
! 5000: gen_op_4xx_tlbre_lo();
! 5001: gen_op_store_T0_gpr(rD(ctx->opcode));
! 5002: break;
! 5003: default:
! 5004: GEN_EXCP_INVAL(ctx);
! 5005: break;
! 5006: }
! 5007: #endif
! 5008: }
! 5009:
! 5010: /* tlbsx - tlbsx. */
! 5011: GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
! 5012: {
! 5013: #if defined(CONFIG_USER_ONLY)
! 5014: GEN_EXCP_PRIVOPC(ctx);
! 5015: #else
! 5016: if (unlikely(!ctx->supervisor)) {
! 5017: GEN_EXCP_PRIVOPC(ctx);
! 5018: return;
! 5019: }
! 5020: gen_addr_reg_index(ctx);
! 5021: gen_op_4xx_tlbsx();
! 5022: if (Rc(ctx->opcode))
! 5023: gen_op_4xx_tlbsx_check();
! 5024: gen_op_store_T0_gpr(rD(ctx->opcode));
! 5025: #endif
! 5026: }
! 5027:
! 5028: /* tlbwe */
! 5029: GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
! 5030: {
! 5031: #if defined(CONFIG_USER_ONLY)
! 5032: GEN_EXCP_PRIVOPC(ctx);
! 5033: #else
! 5034: if (unlikely(!ctx->supervisor)) {
! 5035: GEN_EXCP_PRIVOPC(ctx);
! 5036: return;
! 5037: }
! 5038: switch (rB(ctx->opcode)) {
! 5039: case 0:
! 5040: gen_op_load_gpr_T0(rA(ctx->opcode));
! 5041: gen_op_load_gpr_T1(rS(ctx->opcode));
! 5042: gen_op_4xx_tlbwe_hi();
! 5043: break;
! 5044: case 1:
! 5045: gen_op_load_gpr_T0(rA(ctx->opcode));
! 5046: gen_op_load_gpr_T1(rS(ctx->opcode));
! 5047: gen_op_4xx_tlbwe_lo();
! 5048: break;
! 5049: default:
! 5050: GEN_EXCP_INVAL(ctx);
! 5051: break;
! 5052: }
! 5053: #endif
! 5054: }
! 5055:
! 5056: /* TLB management - PowerPC 440 implementation */
! 5057: /* tlbre */
! 5058: GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
! 5059: {
! 5060: #if defined(CONFIG_USER_ONLY)
! 5061: GEN_EXCP_PRIVOPC(ctx);
! 5062: #else
! 5063: if (unlikely(!ctx->supervisor)) {
! 5064: GEN_EXCP_PRIVOPC(ctx);
! 5065: return;
! 5066: }
! 5067: switch (rB(ctx->opcode)) {
! 5068: case 0:
! 5069: case 1:
! 5070: case 2:
! 5071: gen_op_load_gpr_T0(rA(ctx->opcode));
! 5072: gen_op_440_tlbre(rB(ctx->opcode));
! 5073: gen_op_store_T0_gpr(rD(ctx->opcode));
! 5074: break;
! 5075: default:
! 5076: GEN_EXCP_INVAL(ctx);
! 5077: break;
! 5078: }
! 5079: #endif
! 5080: }
! 5081:
! 5082: /* tlbsx - tlbsx. */
! 5083: GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
1.1 root 5084: {
5085: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 5086: GEN_EXCP_PRIVOPC(ctx);
1.1 root 5087: #else
1.1.1.5 ! root 5088: if (unlikely(!ctx->supervisor)) {
! 5089: GEN_EXCP_PRIVOPC(ctx);
1.1 root 5090: return;
5091: }
1.1.1.5 ! root 5092: gen_addr_reg_index(ctx);
! 5093: gen_op_440_tlbsx();
! 5094: if (Rc(ctx->opcode))
! 5095: gen_op_4xx_tlbsx_check();
! 5096: gen_op_store_T0_gpr(rD(ctx->opcode));
1.1 root 5097: #endif
5098: }
5099:
1.1.1.5 ! root 5100: /* tlbwe */
! 5101: GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
1.1 root 5102: {
5103: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 5104: GEN_EXCP_PRIVOPC(ctx);
1.1 root 5105: #else
1.1.1.5 ! root 5106: if (unlikely(!ctx->supervisor)) {
! 5107: GEN_EXCP_PRIVOPC(ctx);
1.1 root 5108: return;
5109: }
1.1.1.5 ! root 5110: switch (rB(ctx->opcode)) {
! 5111: case 0:
! 5112: case 1:
! 5113: case 2:
! 5114: gen_op_load_gpr_T0(rA(ctx->opcode));
! 5115: gen_op_load_gpr_T1(rS(ctx->opcode));
! 5116: gen_op_440_tlbwe(rB(ctx->opcode));
! 5117: break;
! 5118: default:
! 5119: GEN_EXCP_INVAL(ctx);
! 5120: break;
! 5121: }
! 5122: #endif
! 5123: }
! 5124:
! 5125: /* wrtee */
! 5126: GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
! 5127: {
! 5128: #if defined(CONFIG_USER_ONLY)
! 5129: GEN_EXCP_PRIVOPC(ctx);
! 5130: #else
! 5131: if (unlikely(!ctx->supervisor)) {
! 5132: GEN_EXCP_PRIVOPC(ctx);
! 5133: return;
! 5134: }
! 5135: gen_op_load_gpr_T0(rD(ctx->opcode));
! 5136: gen_op_wrte();
! 5137: /* Stop translation to have a chance to raise an exception
! 5138: * if we just set msr_ee to 1
1.1 root 5139: */
1.1.1.5 ! root 5140: GEN_STOP(ctx);
1.1 root 5141: #endif
5142: }
5143:
1.1.1.5 ! root 5144: /* wrteei */
! 5145: GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
! 5146: {
1.1 root 5147: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 5148: GEN_EXCP_PRIVOPC(ctx);
! 5149: #else
! 5150: if (unlikely(!ctx->supervisor)) {
! 5151: GEN_EXCP_PRIVOPC(ctx);
! 5152: return;
! 5153: }
! 5154: gen_op_set_T0(ctx->opcode & 0x00010000);
! 5155: gen_op_wrte();
! 5156: /* Stop translation to have a chance to raise an exception
! 5157: * if we just set msr_ee to 1
! 5158: */
! 5159: GEN_STOP(ctx);
! 5160: #endif
! 5161: }
! 5162:
! 5163: /* PowerPC 440 specific instructions */
! 5164: /* dlmzb */
! 5165: GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
! 5166: {
! 5167: gen_op_load_gpr_T0(rS(ctx->opcode));
! 5168: gen_op_load_gpr_T1(rB(ctx->opcode));
! 5169: gen_op_440_dlmzb();
! 5170: gen_op_store_T0_gpr(rA(ctx->opcode));
! 5171: gen_op_store_xer_bc();
! 5172: if (Rc(ctx->opcode)) {
! 5173: gen_op_440_dlmzb_update_Rc();
! 5174: gen_op_store_T0_crf(0);
! 5175: }
! 5176: }
! 5177:
! 5178: /* mbar replaces eieio on 440 */
! 5179: GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
! 5180: {
! 5181: /* interpreted as no-op */
! 5182: }
! 5183:
! 5184: /* msync replaces sync on 440 */
! 5185: GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
! 5186: {
! 5187: /* interpreted as no-op */
! 5188: }
! 5189:
! 5190: /* icbt */
! 5191: GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
! 5192: {
! 5193: /* interpreted as no-op */
! 5194: /* XXX: specification say this is treated as a load by the MMU
! 5195: * but does not generate any exception
! 5196: */
! 5197: }
! 5198:
! 5199: /*** Altivec vector extension ***/
! 5200: /* Altivec registers moves */
! 5201: GEN32(gen_op_load_avr_A0, gen_op_load_avr_A0_avr);
! 5202: GEN32(gen_op_load_avr_A1, gen_op_load_avr_A1_avr);
! 5203: GEN32(gen_op_load_avr_A2, gen_op_load_avr_A2_avr);
! 5204:
! 5205: GEN32(gen_op_store_A0_avr, gen_op_store_A0_avr_avr);
! 5206: GEN32(gen_op_store_A1_avr, gen_op_store_A1_avr_avr);
! 5207: #if 0 // unused
! 5208: GEN32(gen_op_store_A2_avr, gen_op_store_A2_avr_avr);
! 5209: #endif
! 5210:
! 5211: #define op_vr_ldst(name) (*gen_op_##name[ctx->mem_idx])()
! 5212: #define OP_VR_LD_TABLE(name) \
! 5213: static GenOpFunc *gen_op_vr_l##name[NB_MEM_FUNCS] = { \
! 5214: GEN_MEM_FUNCS(vr_l##name), \
1.1 root 5215: };
1.1.1.5 ! root 5216: #define OP_VR_ST_TABLE(name) \
! 5217: static GenOpFunc *gen_op_vr_st##name[NB_MEM_FUNCS] = { \
! 5218: GEN_MEM_FUNCS(vr_st##name), \
! 5219: };
! 5220:
! 5221: #define GEN_VR_LDX(name, opc2, opc3) \
! 5222: GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
! 5223: { \
! 5224: if (unlikely(!ctx->altivec_enabled)) { \
! 5225: GEN_EXCP_NO_VR(ctx); \
! 5226: return; \
! 5227: } \
! 5228: gen_addr_reg_index(ctx); \
! 5229: op_vr_ldst(vr_l##name); \
! 5230: gen_op_store_A0_avr(rD(ctx->opcode)); \
! 5231: }
! 5232:
! 5233: #define GEN_VR_STX(name, opc2, opc3) \
! 5234: GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
! 5235: { \
! 5236: if (unlikely(!ctx->altivec_enabled)) { \
! 5237: GEN_EXCP_NO_VR(ctx); \
! 5238: return; \
! 5239: } \
! 5240: gen_addr_reg_index(ctx); \
! 5241: gen_op_load_avr_A0(rS(ctx->opcode)); \
! 5242: op_vr_ldst(vr_st##name); \
! 5243: }
! 5244:
! 5245: OP_VR_LD_TABLE(vx);
! 5246: GEN_VR_LDX(vx, 0x07, 0x03);
! 5247: /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
! 5248: #define gen_op_vr_lvxl gen_op_vr_lvx
! 5249: GEN_VR_LDX(vxl, 0x07, 0x0B);
! 5250:
! 5251: OP_VR_ST_TABLE(vx);
! 5252: GEN_VR_STX(vx, 0x07, 0x07);
! 5253: /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
! 5254: #define gen_op_vr_stvxl gen_op_vr_stvx
! 5255: GEN_VR_STX(vxl, 0x07, 0x0F);
! 5256:
! 5257: /*** SPE extension ***/
! 5258: /* Register moves */
! 5259: #if !defined(TARGET_PPC64)
! 5260:
! 5261: GEN32(gen_op_load_gpr64_T0, gen_op_load_gpr64_T0_gpr);
! 5262: GEN32(gen_op_load_gpr64_T1, gen_op_load_gpr64_T1_gpr);
! 5263: #if 0 // unused
! 5264: GEN32(gen_op_load_gpr64_T2, gen_op_load_gpr64_T2_gpr);
1.1 root 5265: #endif
5266:
1.1.1.5 ! root 5267: GEN32(gen_op_store_T0_gpr64, gen_op_store_T0_gpr64_gpr);
! 5268: GEN32(gen_op_store_T1_gpr64, gen_op_store_T1_gpr64_gpr);
! 5269: #if 0 // unused
! 5270: GEN32(gen_op_store_T2_gpr64, gen_op_store_T2_gpr64_gpr);
! 5271: #endif
! 5272:
! 5273: #else /* !defined(TARGET_PPC64) */
! 5274:
! 5275: /* No specific load/store functions: GPRs are already 64 bits */
! 5276: #define gen_op_load_gpr64_T0 gen_op_load_gpr_T0
! 5277: #define gen_op_load_gpr64_T1 gen_op_load_gpr_T1
! 5278: #if 0 // unused
! 5279: #define gen_op_load_gpr64_T2 gen_op_load_gpr_T2
! 5280: #endif
! 5281:
! 5282: #define gen_op_store_T0_gpr64 gen_op_store_T0_gpr
! 5283: #define gen_op_store_T1_gpr64 gen_op_store_T1_gpr
! 5284: #if 0 // unused
! 5285: #define gen_op_store_T2_gpr64 gen_op_store_T2_gpr
! 5286: #endif
! 5287:
! 5288: #endif /* !defined(TARGET_PPC64) */
! 5289:
! 5290: #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
! 5291: GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
! 5292: { \
! 5293: if (Rc(ctx->opcode)) \
! 5294: gen_##name1(ctx); \
! 5295: else \
! 5296: gen_##name0(ctx); \
! 5297: }
! 5298:
! 5299: /* Handler for undefined SPE opcodes */
! 5300: static always_inline void gen_speundef (DisasContext *ctx)
1.1 root 5301: {
1.1.1.5 ! root 5302: GEN_EXCP_INVAL(ctx);
! 5303: }
! 5304:
! 5305: /* SPE load and stores */
! 5306: static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
! 5307: {
! 5308: target_long simm = rB(ctx->opcode);
! 5309:
1.1 root 5310: if (rA(ctx->opcode) == 0) {
1.1.1.5 ! root 5311: gen_set_T0(simm << sh);
1.1 root 5312: } else {
5313: gen_op_load_gpr_T0(rA(ctx->opcode));
1.1.1.5 ! root 5314: if (likely(simm != 0))
! 5315: gen_op_addi(simm << sh);
1.1 root 5316: }
1.1.1.5 ! root 5317: }
! 5318:
! 5319: #define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
! 5320: #define OP_SPE_LD_TABLE(name) \
! 5321: static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = { \
! 5322: GEN_MEM_FUNCS(spe_l##name), \
! 5323: };
! 5324: #define OP_SPE_ST_TABLE(name) \
! 5325: static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = { \
! 5326: GEN_MEM_FUNCS(spe_st##name), \
! 5327: };
! 5328:
! 5329: #define GEN_SPE_LD(name, sh) \
! 5330: static always_inline void gen_evl##name (DisasContext *ctx) \
! 5331: { \
! 5332: if (unlikely(!ctx->spe_enabled)) { \
! 5333: GEN_EXCP_NO_AP(ctx); \
! 5334: return; \
! 5335: } \
! 5336: gen_addr_spe_imm_index(ctx, sh); \
! 5337: op_spe_ldst(spe_l##name); \
! 5338: gen_op_store_T1_gpr64(rD(ctx->opcode)); \
! 5339: }
! 5340:
! 5341: #define GEN_SPE_LDX(name) \
! 5342: static always_inline void gen_evl##name##x (DisasContext *ctx) \
! 5343: { \
! 5344: if (unlikely(!ctx->spe_enabled)) { \
! 5345: GEN_EXCP_NO_AP(ctx); \
! 5346: return; \
! 5347: } \
! 5348: gen_addr_reg_index(ctx); \
! 5349: op_spe_ldst(spe_l##name); \
! 5350: gen_op_store_T1_gpr64(rD(ctx->opcode)); \
! 5351: }
! 5352:
! 5353: #define GEN_SPEOP_LD(name, sh) \
! 5354: OP_SPE_LD_TABLE(name); \
! 5355: GEN_SPE_LD(name, sh); \
! 5356: GEN_SPE_LDX(name)
! 5357:
! 5358: #define GEN_SPE_ST(name, sh) \
! 5359: static always_inline void gen_evst##name (DisasContext *ctx) \
! 5360: { \
! 5361: if (unlikely(!ctx->spe_enabled)) { \
! 5362: GEN_EXCP_NO_AP(ctx); \
! 5363: return; \
! 5364: } \
! 5365: gen_addr_spe_imm_index(ctx, sh); \
! 5366: gen_op_load_gpr64_T1(rS(ctx->opcode)); \
! 5367: op_spe_ldst(spe_st##name); \
! 5368: }
! 5369:
! 5370: #define GEN_SPE_STX(name) \
! 5371: static always_inline void gen_evst##name##x (DisasContext *ctx) \
! 5372: { \
! 5373: if (unlikely(!ctx->spe_enabled)) { \
! 5374: GEN_EXCP_NO_AP(ctx); \
! 5375: return; \
! 5376: } \
! 5377: gen_addr_reg_index(ctx); \
! 5378: gen_op_load_gpr64_T1(rS(ctx->opcode)); \
! 5379: op_spe_ldst(spe_st##name); \
! 5380: }
! 5381:
! 5382: #define GEN_SPEOP_ST(name, sh) \
! 5383: OP_SPE_ST_TABLE(name); \
! 5384: GEN_SPE_ST(name, sh); \
! 5385: GEN_SPE_STX(name)
! 5386:
! 5387: #define GEN_SPEOP_LDST(name, sh) \
! 5388: GEN_SPEOP_LD(name, sh); \
! 5389: GEN_SPEOP_ST(name, sh)
! 5390:
! 5391: /* SPE arithmetic and logic */
! 5392: #define GEN_SPEOP_ARITH2(name) \
! 5393: static always_inline void gen_##name (DisasContext *ctx) \
! 5394: { \
! 5395: if (unlikely(!ctx->spe_enabled)) { \
! 5396: GEN_EXCP_NO_AP(ctx); \
! 5397: return; \
! 5398: } \
! 5399: gen_op_load_gpr64_T0(rA(ctx->opcode)); \
! 5400: gen_op_load_gpr64_T1(rB(ctx->opcode)); \
! 5401: gen_op_##name(); \
! 5402: gen_op_store_T0_gpr64(rD(ctx->opcode)); \
! 5403: }
! 5404:
! 5405: #define GEN_SPEOP_ARITH1(name) \
! 5406: static always_inline void gen_##name (DisasContext *ctx) \
! 5407: { \
! 5408: if (unlikely(!ctx->spe_enabled)) { \
! 5409: GEN_EXCP_NO_AP(ctx); \
! 5410: return; \
! 5411: } \
! 5412: gen_op_load_gpr64_T0(rA(ctx->opcode)); \
! 5413: gen_op_##name(); \
! 5414: gen_op_store_T0_gpr64(rD(ctx->opcode)); \
! 5415: }
! 5416:
! 5417: #define GEN_SPEOP_COMP(name) \
! 5418: static always_inline void gen_##name (DisasContext *ctx) \
! 5419: { \
! 5420: if (unlikely(!ctx->spe_enabled)) { \
! 5421: GEN_EXCP_NO_AP(ctx); \
! 5422: return; \
! 5423: } \
! 5424: gen_op_load_gpr64_T0(rA(ctx->opcode)); \
! 5425: gen_op_load_gpr64_T1(rB(ctx->opcode)); \
! 5426: gen_op_##name(); \
! 5427: gen_op_store_T0_crf(crfD(ctx->opcode)); \
! 5428: }
! 5429:
! 5430: /* Logical */
! 5431: GEN_SPEOP_ARITH2(evand);
! 5432: GEN_SPEOP_ARITH2(evandc);
! 5433: GEN_SPEOP_ARITH2(evxor);
! 5434: GEN_SPEOP_ARITH2(evor);
! 5435: GEN_SPEOP_ARITH2(evnor);
! 5436: GEN_SPEOP_ARITH2(eveqv);
! 5437: GEN_SPEOP_ARITH2(evorc);
! 5438: GEN_SPEOP_ARITH2(evnand);
! 5439: GEN_SPEOP_ARITH2(evsrwu);
! 5440: GEN_SPEOP_ARITH2(evsrws);
! 5441: GEN_SPEOP_ARITH2(evslw);
! 5442: GEN_SPEOP_ARITH2(evrlw);
! 5443: GEN_SPEOP_ARITH2(evmergehi);
! 5444: GEN_SPEOP_ARITH2(evmergelo);
! 5445: GEN_SPEOP_ARITH2(evmergehilo);
! 5446: GEN_SPEOP_ARITH2(evmergelohi);
! 5447:
! 5448: /* Arithmetic */
! 5449: GEN_SPEOP_ARITH2(evaddw);
! 5450: GEN_SPEOP_ARITH2(evsubfw);
! 5451: GEN_SPEOP_ARITH1(evabs);
! 5452: GEN_SPEOP_ARITH1(evneg);
! 5453: GEN_SPEOP_ARITH1(evextsb);
! 5454: GEN_SPEOP_ARITH1(evextsh);
! 5455: GEN_SPEOP_ARITH1(evrndw);
! 5456: GEN_SPEOP_ARITH1(evcntlzw);
! 5457: GEN_SPEOP_ARITH1(evcntlsw);
! 5458: static always_inline void gen_brinc (DisasContext *ctx)
! 5459: {
! 5460: /* Note: brinc is usable even if SPE is disabled */
! 5461: gen_op_load_gpr_T0(rA(ctx->opcode));
! 5462: gen_op_load_gpr_T1(rB(ctx->opcode));
! 5463: gen_op_brinc();
1.1 root 5464: gen_op_store_T0_gpr(rD(ctx->opcode));
5465: }
5466:
1.1.1.5 ! root 5467: #define GEN_SPEOP_ARITH_IMM2(name) \
! 5468: static always_inline void gen_##name##i (DisasContext *ctx) \
! 5469: { \
! 5470: if (unlikely(!ctx->spe_enabled)) { \
! 5471: GEN_EXCP_NO_AP(ctx); \
! 5472: return; \
! 5473: } \
! 5474: gen_op_load_gpr64_T0(rB(ctx->opcode)); \
! 5475: gen_op_splatwi_T1_64(rA(ctx->opcode)); \
! 5476: gen_op_##name(); \
! 5477: gen_op_store_T0_gpr64(rD(ctx->opcode)); \
! 5478: }
! 5479:
! 5480: #define GEN_SPEOP_LOGIC_IMM2(name) \
! 5481: static always_inline void gen_##name##i (DisasContext *ctx) \
! 5482: { \
! 5483: if (unlikely(!ctx->spe_enabled)) { \
! 5484: GEN_EXCP_NO_AP(ctx); \
! 5485: return; \
! 5486: } \
! 5487: gen_op_load_gpr64_T0(rA(ctx->opcode)); \
! 5488: gen_op_splatwi_T1_64(rB(ctx->opcode)); \
! 5489: gen_op_##name(); \
! 5490: gen_op_store_T0_gpr64(rD(ctx->opcode)); \
! 5491: }
! 5492:
! 5493: GEN_SPEOP_ARITH_IMM2(evaddw);
! 5494: #define gen_evaddiw gen_evaddwi
! 5495: GEN_SPEOP_ARITH_IMM2(evsubfw);
! 5496: #define gen_evsubifw gen_evsubfwi
! 5497: GEN_SPEOP_LOGIC_IMM2(evslw);
! 5498: GEN_SPEOP_LOGIC_IMM2(evsrwu);
! 5499: #define gen_evsrwis gen_evsrwsi
! 5500: GEN_SPEOP_LOGIC_IMM2(evsrws);
! 5501: #define gen_evsrwiu gen_evsrwui
! 5502: GEN_SPEOP_LOGIC_IMM2(evrlw);
! 5503:
! 5504: static always_inline void gen_evsplati (DisasContext *ctx)
! 5505: {
! 5506: int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
! 5507:
! 5508: gen_op_splatwi_T0_64(imm);
! 5509: gen_op_store_T0_gpr64(rD(ctx->opcode));
! 5510: }
! 5511:
! 5512: static always_inline void gen_evsplatfi (DisasContext *ctx)
! 5513: {
! 5514: uint32_t imm = rA(ctx->opcode) << 27;
! 5515:
! 5516: gen_op_splatwi_T0_64(imm);
! 5517: gen_op_store_T0_gpr64(rD(ctx->opcode));
! 5518: }
! 5519:
! 5520: /* Comparison */
! 5521: GEN_SPEOP_COMP(evcmpgtu);
! 5522: GEN_SPEOP_COMP(evcmpgts);
! 5523: GEN_SPEOP_COMP(evcmpltu);
! 5524: GEN_SPEOP_COMP(evcmplts);
! 5525: GEN_SPEOP_COMP(evcmpeq);
! 5526:
! 5527: GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
! 5528: GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
! 5529: GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
! 5530: GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
! 5531: GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
! 5532: GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
! 5533: GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
! 5534: GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
! 5535: GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
! 5536: GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
! 5537: GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
! 5538: GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
! 5539: GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
! 5540: GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
! 5541: GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
! 5542: GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
! 5543: GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
! 5544: GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
! 5545: GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
! 5546: GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
! 5547: GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
! 5548: GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
! 5549: GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
! 5550: GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
! 5551: GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
! 5552:
! 5553: static always_inline void gen_evsel (DisasContext *ctx)
1.1 root 5554: {
1.1.1.5 ! root 5555: if (unlikely(!ctx->spe_enabled)) {
! 5556: GEN_EXCP_NO_AP(ctx);
! 5557: return;
1.1 root 5558: }
1.1.1.5 ! root 5559: gen_op_load_crf_T0(ctx->opcode & 0x7);
! 5560: gen_op_load_gpr64_T0(rA(ctx->opcode));
! 5561: gen_op_load_gpr64_T1(rB(ctx->opcode));
! 5562: gen_op_evsel();
! 5563: gen_op_store_T0_gpr64(rD(ctx->opcode));
! 5564: }
! 5565:
! 5566: GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
! 5567: {
! 5568: gen_evsel(ctx);
! 5569: }
! 5570: GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
! 5571: {
! 5572: gen_evsel(ctx);
! 5573: }
! 5574: GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
! 5575: {
! 5576: gen_evsel(ctx);
! 5577: }
! 5578: GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
! 5579: {
! 5580: gen_evsel(ctx);
! 5581: }
! 5582:
! 5583: /* Load and stores */
! 5584: #if defined(TARGET_PPC64)
! 5585: /* In that case, we already have 64 bits load & stores
! 5586: * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
! 5587: */
! 5588: #define gen_op_spe_ldd_raw gen_op_ld_raw
! 5589: #define gen_op_spe_ldd_user gen_op_ld_user
! 5590: #define gen_op_spe_ldd_kernel gen_op_ld_kernel
! 5591: #define gen_op_spe_ldd_hypv gen_op_ld_hypv
! 5592: #define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
! 5593: #define gen_op_spe_ldd_64_user gen_op_ld_64_user
! 5594: #define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
! 5595: #define gen_op_spe_ldd_64_hypv gen_op_ld_64_hypv
! 5596: #define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
! 5597: #define gen_op_spe_ldd_le_user gen_op_ld_le_user
! 5598: #define gen_op_spe_ldd_le_kernel gen_op_ld_le_kernel
! 5599: #define gen_op_spe_ldd_le_hypv gen_op_ld_le_hypv
! 5600: #define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
! 5601: #define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
! 5602: #define gen_op_spe_ldd_le_64_kernel gen_op_ld_le_64_kernel
! 5603: #define gen_op_spe_ldd_le_64_hypv gen_op_ld_le_64_hypv
! 5604: #define gen_op_spe_stdd_raw gen_op_std_raw
! 5605: #define gen_op_spe_stdd_user gen_op_std_user
! 5606: #define gen_op_spe_stdd_kernel gen_op_std_kernel
! 5607: #define gen_op_spe_stdd_hypv gen_op_std_hypv
! 5608: #define gen_op_spe_stdd_64_raw gen_op_std_64_raw
! 5609: #define gen_op_spe_stdd_64_user gen_op_std_64_user
! 5610: #define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
! 5611: #define gen_op_spe_stdd_64_hypv gen_op_std_64_hypv
! 5612: #define gen_op_spe_stdd_le_raw gen_op_std_le_raw
! 5613: #define gen_op_spe_stdd_le_user gen_op_std_le_user
! 5614: #define gen_op_spe_stdd_le_kernel gen_op_std_le_kernel
! 5615: #define gen_op_spe_stdd_le_hypv gen_op_std_le_hypv
! 5616: #define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
! 5617: #define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
! 5618: #define gen_op_spe_stdd_le_64_kernel gen_op_std_le_64_kernel
! 5619: #define gen_op_spe_stdd_le_64_hypv gen_op_std_le_64_hypv
! 5620: #endif /* defined(TARGET_PPC64) */
! 5621: GEN_SPEOP_LDST(dd, 3);
! 5622: GEN_SPEOP_LDST(dw, 3);
! 5623: GEN_SPEOP_LDST(dh, 3);
! 5624: GEN_SPEOP_LDST(whe, 2);
! 5625: GEN_SPEOP_LD(whou, 2);
! 5626: GEN_SPEOP_LD(whos, 2);
! 5627: GEN_SPEOP_ST(who, 2);
! 5628:
! 5629: #if defined(TARGET_PPC64)
! 5630: /* In that case, spe_stwwo is equivalent to stw */
! 5631: #define gen_op_spe_stwwo_raw gen_op_stw_raw
! 5632: #define gen_op_spe_stwwo_user gen_op_stw_user
! 5633: #define gen_op_spe_stwwo_kernel gen_op_stw_kernel
! 5634: #define gen_op_spe_stwwo_hypv gen_op_stw_hypv
! 5635: #define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
! 5636: #define gen_op_spe_stwwo_le_user gen_op_stw_le_user
! 5637: #define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
! 5638: #define gen_op_spe_stwwo_le_hypv gen_op_stw_le_hypv
! 5639: #define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
! 5640: #define gen_op_spe_stwwo_64_user gen_op_stw_64_user
! 5641: #define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
! 5642: #define gen_op_spe_stwwo_64_hypv gen_op_stw_64_hypv
! 5643: #define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
! 5644: #define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
! 5645: #define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
! 5646: #define gen_op_spe_stwwo_le_64_hypv gen_op_stw_le_64_hypv
! 5647: #endif
! 5648: #define _GEN_OP_SPE_STWWE(suffix) \
! 5649: static always_inline void gen_op_spe_stwwe_##suffix (void) \
! 5650: { \
! 5651: gen_op_srli32_T1_64(); \
! 5652: gen_op_spe_stwwo_##suffix(); \
! 5653: }
! 5654: #define _GEN_OP_SPE_STWWE_LE(suffix) \
! 5655: static always_inline void gen_op_spe_stwwe_le_##suffix (void) \
! 5656: { \
! 5657: gen_op_srli32_T1_64(); \
! 5658: gen_op_spe_stwwo_le_##suffix(); \
! 5659: }
! 5660: #if defined(TARGET_PPC64)
! 5661: #define GEN_OP_SPE_STWWE(suffix) \
! 5662: _GEN_OP_SPE_STWWE(suffix); \
! 5663: _GEN_OP_SPE_STWWE_LE(suffix); \
! 5664: static always_inline void gen_op_spe_stwwe_64_##suffix (void) \
! 5665: { \
! 5666: gen_op_srli32_T1_64(); \
! 5667: gen_op_spe_stwwo_64_##suffix(); \
! 5668: } \
! 5669: static always_inline void gen_op_spe_stwwe_le_64_##suffix (void) \
! 5670: { \
! 5671: gen_op_srli32_T1_64(); \
! 5672: gen_op_spe_stwwo_le_64_##suffix(); \
! 5673: }
! 5674: #else
! 5675: #define GEN_OP_SPE_STWWE(suffix) \
! 5676: _GEN_OP_SPE_STWWE(suffix); \
! 5677: _GEN_OP_SPE_STWWE_LE(suffix)
! 5678: #endif
! 5679: #if defined(CONFIG_USER_ONLY)
! 5680: GEN_OP_SPE_STWWE(raw);
! 5681: #else /* defined(CONFIG_USER_ONLY) */
! 5682: GEN_OP_SPE_STWWE(user);
! 5683: GEN_OP_SPE_STWWE(kernel);
! 5684: GEN_OP_SPE_STWWE(hypv);
! 5685: #endif /* defined(CONFIG_USER_ONLY) */
! 5686: GEN_SPEOP_ST(wwe, 2);
! 5687: GEN_SPEOP_ST(wwo, 2);
! 5688:
! 5689: #define GEN_SPE_LDSPLAT(name, op, suffix) \
! 5690: static always_inline void gen_op_spe_l##name##_##suffix (void) \
! 5691: { \
! 5692: gen_op_##op##_##suffix(); \
! 5693: gen_op_splatw_T1_64(); \
! 5694: }
! 5695:
! 5696: #define GEN_OP_SPE_LHE(suffix) \
! 5697: static always_inline void gen_op_spe_lhe_##suffix (void) \
! 5698: { \
! 5699: gen_op_spe_lh_##suffix(); \
! 5700: gen_op_sli16_T1_64(); \
! 5701: }
! 5702:
! 5703: #define GEN_OP_SPE_LHX(suffix) \
! 5704: static always_inline void gen_op_spe_lhx_##suffix (void) \
! 5705: { \
! 5706: gen_op_spe_lh_##suffix(); \
! 5707: gen_op_extsh_T1_64(); \
! 5708: }
! 5709:
! 5710: #if defined(CONFIG_USER_ONLY)
! 5711: GEN_OP_SPE_LHE(raw);
! 5712: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
! 5713: GEN_OP_SPE_LHE(le_raw);
! 5714: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
! 5715: GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
! 5716: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
! 5717: GEN_OP_SPE_LHX(raw);
! 5718: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
! 5719: GEN_OP_SPE_LHX(le_raw);
! 5720: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
! 5721: #if defined(TARGET_PPC64)
! 5722: GEN_OP_SPE_LHE(64_raw);
! 5723: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
! 5724: GEN_OP_SPE_LHE(le_64_raw);
! 5725: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
! 5726: GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
! 5727: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
! 5728: GEN_OP_SPE_LHX(64_raw);
! 5729: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
! 5730: GEN_OP_SPE_LHX(le_64_raw);
! 5731: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
! 5732: #endif
! 5733: #else
! 5734: GEN_OP_SPE_LHE(user);
! 5735: GEN_OP_SPE_LHE(kernel);
! 5736: GEN_OP_SPE_LHE(hypv);
! 5737: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
! 5738: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
! 5739: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
! 5740: GEN_OP_SPE_LHE(le_user);
! 5741: GEN_OP_SPE_LHE(le_kernel);
! 5742: GEN_OP_SPE_LHE(le_hypv);
! 5743: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
! 5744: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
! 5745: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
! 5746: GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
! 5747: GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
! 5748: GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
! 5749: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
! 5750: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
! 5751: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
! 5752: GEN_OP_SPE_LHX(user);
! 5753: GEN_OP_SPE_LHX(kernel);
! 5754: GEN_OP_SPE_LHX(hypv);
! 5755: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
! 5756: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
! 5757: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
! 5758: GEN_OP_SPE_LHX(le_user);
! 5759: GEN_OP_SPE_LHX(le_kernel);
! 5760: GEN_OP_SPE_LHX(le_hypv);
! 5761: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
! 5762: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
! 5763: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
! 5764: #if defined(TARGET_PPC64)
! 5765: GEN_OP_SPE_LHE(64_user);
! 5766: GEN_OP_SPE_LHE(64_kernel);
! 5767: GEN_OP_SPE_LHE(64_hypv);
! 5768: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
! 5769: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
! 5770: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
! 5771: GEN_OP_SPE_LHE(le_64_user);
! 5772: GEN_OP_SPE_LHE(le_64_kernel);
! 5773: GEN_OP_SPE_LHE(le_64_hypv);
! 5774: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
! 5775: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
! 5776: GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
! 5777: GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
! 5778: GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
! 5779: GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
! 5780: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
! 5781: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
! 5782: GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
! 5783: GEN_OP_SPE_LHX(64_user);
! 5784: GEN_OP_SPE_LHX(64_kernel);
! 5785: GEN_OP_SPE_LHX(64_hypv);
! 5786: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
! 5787: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
! 5788: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
! 5789: GEN_OP_SPE_LHX(le_64_user);
! 5790: GEN_OP_SPE_LHX(le_64_kernel);
! 5791: GEN_OP_SPE_LHX(le_64_hypv);
! 5792: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
! 5793: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
! 5794: GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
! 5795: #endif
! 5796: #endif
! 5797: GEN_SPEOP_LD(hhesplat, 1);
! 5798: GEN_SPEOP_LD(hhousplat, 1);
! 5799: GEN_SPEOP_LD(hhossplat, 1);
! 5800: GEN_SPEOP_LD(wwsplat, 2);
! 5801: GEN_SPEOP_LD(whsplat, 2);
! 5802:
! 5803: GEN_SPE(evlddx, evldd, 0x00, 0x0C, 0x00000000, PPC_SPE); //
! 5804: GEN_SPE(evldwx, evldw, 0x01, 0x0C, 0x00000000, PPC_SPE); //
! 5805: GEN_SPE(evldhx, evldh, 0x02, 0x0C, 0x00000000, PPC_SPE); //
! 5806: GEN_SPE(evlhhesplatx, evlhhesplat, 0x04, 0x0C, 0x00000000, PPC_SPE); //
! 5807: GEN_SPE(evlhhousplatx, evlhhousplat, 0x06, 0x0C, 0x00000000, PPC_SPE); //
! 5808: GEN_SPE(evlhhossplatx, evlhhossplat, 0x07, 0x0C, 0x00000000, PPC_SPE); //
! 5809: GEN_SPE(evlwhex, evlwhe, 0x08, 0x0C, 0x00000000, PPC_SPE); //
! 5810: GEN_SPE(evlwhoux, evlwhou, 0x0A, 0x0C, 0x00000000, PPC_SPE); //
! 5811: GEN_SPE(evlwhosx, evlwhos, 0x0B, 0x0C, 0x00000000, PPC_SPE); //
! 5812: GEN_SPE(evlwwsplatx, evlwwsplat, 0x0C, 0x0C, 0x00000000, PPC_SPE); //
! 5813: GEN_SPE(evlwhsplatx, evlwhsplat, 0x0E, 0x0C, 0x00000000, PPC_SPE); //
! 5814: GEN_SPE(evstddx, evstdd, 0x10, 0x0C, 0x00000000, PPC_SPE); //
! 5815: GEN_SPE(evstdwx, evstdw, 0x11, 0x0C, 0x00000000, PPC_SPE); //
! 5816: GEN_SPE(evstdhx, evstdh, 0x12, 0x0C, 0x00000000, PPC_SPE); //
! 5817: GEN_SPE(evstwhex, evstwhe, 0x18, 0x0C, 0x00000000, PPC_SPE); //
! 5818: GEN_SPE(evstwhox, evstwho, 0x1A, 0x0C, 0x00000000, PPC_SPE); //
! 5819: GEN_SPE(evstwwex, evstwwe, 0x1C, 0x0C, 0x00000000, PPC_SPE); //
! 5820: GEN_SPE(evstwwox, evstwwo, 0x1E, 0x0C, 0x00000000, PPC_SPE); //
! 5821:
! 5822: /* Multiply and add - TODO */
! 5823: #if 0
! 5824: GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
! 5825: GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
! 5826: GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
! 5827: GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
! 5828: GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
! 5829: GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
! 5830: GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
! 5831: GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
! 5832: GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
! 5833: GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
! 5834: GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
! 5835: GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
! 5836:
! 5837: GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
! 5838: GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
! 5839: GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
! 5840: GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
! 5841: GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
! 5842: GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
! 5843: GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
! 5844: GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
! 5845: GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
! 5846: GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
! 5847: GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
! 5848: GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
! 5849: GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
! 5850: GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
! 5851:
! 5852: GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
! 5853: GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
! 5854: GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
! 5855: GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
! 5856: GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
! 5857: GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
! 5858:
! 5859: GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
! 5860: GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
! 5861: GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
! 5862: GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
! 5863: GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
! 5864: GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
! 5865: GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
! 5866: GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
! 5867: GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
! 5868: GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
! 5869: GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
! 5870: GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
! 5871:
! 5872: GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
! 5873: GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
! 5874: GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
! 5875: GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
! 5876: GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
! 5877:
! 5878: GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
! 5879: GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
! 5880: GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
! 5881: GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
! 5882: GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
! 5883: GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
! 5884: GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
! 5885: GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
! 5886: GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
! 5887: GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
! 5888: GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
! 5889: GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
! 5890:
! 5891: GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
! 5892: GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
! 5893: GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
! 5894: GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
! 5895: GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
! 5896: #endif
! 5897:
! 5898: /*** SPE floating-point extension ***/
! 5899: #define GEN_SPEFPUOP_CONV(name) \
! 5900: static always_inline void gen_##name (DisasContext *ctx) \
! 5901: { \
! 5902: gen_op_load_gpr64_T0(rB(ctx->opcode)); \
! 5903: gen_op_##name(); \
! 5904: gen_op_store_T0_gpr64(rD(ctx->opcode)); \
1.1 root 5905: }
5906:
1.1.1.5 ! root 5907: /* Single precision floating-point vectors operations */
! 5908: /* Arithmetic */
! 5909: GEN_SPEOP_ARITH2(evfsadd);
! 5910: GEN_SPEOP_ARITH2(evfssub);
! 5911: GEN_SPEOP_ARITH2(evfsmul);
! 5912: GEN_SPEOP_ARITH2(evfsdiv);
! 5913: GEN_SPEOP_ARITH1(evfsabs);
! 5914: GEN_SPEOP_ARITH1(evfsnabs);
! 5915: GEN_SPEOP_ARITH1(evfsneg);
! 5916: /* Conversion */
! 5917: GEN_SPEFPUOP_CONV(evfscfui);
! 5918: GEN_SPEFPUOP_CONV(evfscfsi);
! 5919: GEN_SPEFPUOP_CONV(evfscfuf);
! 5920: GEN_SPEFPUOP_CONV(evfscfsf);
! 5921: GEN_SPEFPUOP_CONV(evfsctui);
! 5922: GEN_SPEFPUOP_CONV(evfsctsi);
! 5923: GEN_SPEFPUOP_CONV(evfsctuf);
! 5924: GEN_SPEFPUOP_CONV(evfsctsf);
! 5925: GEN_SPEFPUOP_CONV(evfsctuiz);
! 5926: GEN_SPEFPUOP_CONV(evfsctsiz);
! 5927: /* Comparison */
! 5928: GEN_SPEOP_COMP(evfscmpgt);
! 5929: GEN_SPEOP_COMP(evfscmplt);
! 5930: GEN_SPEOP_COMP(evfscmpeq);
! 5931: GEN_SPEOP_COMP(evfststgt);
! 5932: GEN_SPEOP_COMP(evfststlt);
! 5933: GEN_SPEOP_COMP(evfststeq);
! 5934:
! 5935: /* Opcodes definitions */
! 5936: GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
! 5937: GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
! 5938: GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
! 5939: GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
! 5940: GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
! 5941: GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
! 5942: GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
! 5943: GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
! 5944: GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
! 5945: GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
! 5946: GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
! 5947: GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
! 5948: GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
! 5949: GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
! 5950:
! 5951: /* Single precision floating-point operations */
! 5952: /* Arithmetic */
! 5953: GEN_SPEOP_ARITH2(efsadd);
! 5954: GEN_SPEOP_ARITH2(efssub);
! 5955: GEN_SPEOP_ARITH2(efsmul);
! 5956: GEN_SPEOP_ARITH2(efsdiv);
! 5957: GEN_SPEOP_ARITH1(efsabs);
! 5958: GEN_SPEOP_ARITH1(efsnabs);
! 5959: GEN_SPEOP_ARITH1(efsneg);
! 5960: /* Conversion */
! 5961: GEN_SPEFPUOP_CONV(efscfui);
! 5962: GEN_SPEFPUOP_CONV(efscfsi);
! 5963: GEN_SPEFPUOP_CONV(efscfuf);
! 5964: GEN_SPEFPUOP_CONV(efscfsf);
! 5965: GEN_SPEFPUOP_CONV(efsctui);
! 5966: GEN_SPEFPUOP_CONV(efsctsi);
! 5967: GEN_SPEFPUOP_CONV(efsctuf);
! 5968: GEN_SPEFPUOP_CONV(efsctsf);
! 5969: GEN_SPEFPUOP_CONV(efsctuiz);
! 5970: GEN_SPEFPUOP_CONV(efsctsiz);
! 5971: GEN_SPEFPUOP_CONV(efscfd);
! 5972: /* Comparison */
! 5973: GEN_SPEOP_COMP(efscmpgt);
! 5974: GEN_SPEOP_COMP(efscmplt);
! 5975: GEN_SPEOP_COMP(efscmpeq);
! 5976: GEN_SPEOP_COMP(efststgt);
! 5977: GEN_SPEOP_COMP(efststlt);
! 5978: GEN_SPEOP_COMP(efststeq);
! 5979:
! 5980: /* Opcodes definitions */
! 5981: GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
! 5982: GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
! 5983: GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
! 5984: GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
! 5985: GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
! 5986: GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
! 5987: GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
! 5988: GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
! 5989: GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
! 5990: GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
! 5991: GEN_SPE(efsctuiz, efsctsiz, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
! 5992: GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
! 5993: GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
! 5994:
! 5995: /* Double precision floating-point operations */
! 5996: /* Arithmetic */
! 5997: GEN_SPEOP_ARITH2(efdadd);
! 5998: GEN_SPEOP_ARITH2(efdsub);
! 5999: GEN_SPEOP_ARITH2(efdmul);
! 6000: GEN_SPEOP_ARITH2(efddiv);
! 6001: GEN_SPEOP_ARITH1(efdabs);
! 6002: GEN_SPEOP_ARITH1(efdnabs);
! 6003: GEN_SPEOP_ARITH1(efdneg);
! 6004: /* Conversion */
! 6005:
! 6006: GEN_SPEFPUOP_CONV(efdcfui);
! 6007: GEN_SPEFPUOP_CONV(efdcfsi);
! 6008: GEN_SPEFPUOP_CONV(efdcfuf);
! 6009: GEN_SPEFPUOP_CONV(efdcfsf);
! 6010: GEN_SPEFPUOP_CONV(efdctui);
! 6011: GEN_SPEFPUOP_CONV(efdctsi);
! 6012: GEN_SPEFPUOP_CONV(efdctuf);
! 6013: GEN_SPEFPUOP_CONV(efdctsf);
! 6014: GEN_SPEFPUOP_CONV(efdctuiz);
! 6015: GEN_SPEFPUOP_CONV(efdctsiz);
! 6016: GEN_SPEFPUOP_CONV(efdcfs);
! 6017: GEN_SPEFPUOP_CONV(efdcfuid);
! 6018: GEN_SPEFPUOP_CONV(efdcfsid);
! 6019: GEN_SPEFPUOP_CONV(efdctuidz);
! 6020: GEN_SPEFPUOP_CONV(efdctsidz);
! 6021: /* Comparison */
! 6022: GEN_SPEOP_COMP(efdcmpgt);
! 6023: GEN_SPEOP_COMP(efdcmplt);
! 6024: GEN_SPEOP_COMP(efdcmpeq);
! 6025: GEN_SPEOP_COMP(efdtstgt);
! 6026: GEN_SPEOP_COMP(efdtstlt);
! 6027: GEN_SPEOP_COMP(efdtsteq);
! 6028:
! 6029: /* Opcodes definitions */
! 6030: GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
! 6031: GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6032: GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
! 6033: GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
! 6034: GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
! 6035: GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6036: GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
! 6037: GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
! 6038: GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6039: GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6040: GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6041: GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6042: GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6043: GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
! 6044: GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
! 6045: GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
! 6046:
1.1 root 6047: /* End opcode list */
6048: GEN_OPCODE_MARK(end);
6049:
6050: #include "translate_init.c"
1.1.1.5 ! root 6051: #include "helper_regs.h"
1.1 root 6052:
6053: /*****************************************************************************/
6054: /* Misc PowerPC helpers */
1.1.1.5 ! root 6055: void cpu_dump_state (CPUState *env, FILE *f,
! 6056: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
! 6057: int flags)
! 6058: {
1.1 root 6059: #define RGPL 4
6060: #define RFPL 4
6061:
6062: int i;
6063:
1.1.1.5 ! root 6064: cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n",
! 6065: env->nip, env->lr, env->ctr, hreg_load_xer(env));
! 6066: cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX " HF " ADDRX " idx %d\n",
! 6067: env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
! 6068: #if !defined(NO_TIMER_DUMP)
! 6069: cpu_fprintf(f, "TB %08x %08x "
! 6070: #if !defined(CONFIG_USER_ONLY)
! 6071: "DECR %08x"
! 6072: #endif
! 6073: "\n",
! 6074: cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
! 6075: #if !defined(CONFIG_USER_ONLY)
! 6076: , cpu_ppc_load_decr(env)
! 6077: #endif
! 6078: );
! 6079: #endif
! 6080: for (i = 0; i < 32; i++) {
1.1 root 6081: if ((i & (RGPL - 1)) == 0)
6082: cpu_fprintf(f, "GPR%02d", i);
1.1.1.5 ! root 6083: cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
1.1 root 6084: if ((i & (RGPL - 1)) == (RGPL - 1))
6085: cpu_fprintf(f, "\n");
1.1.1.5 ! root 6086: }
1.1 root 6087: cpu_fprintf(f, "CR ");
1.1.1.5 ! root 6088: for (i = 0; i < 8; i++)
1.1 root 6089: cpu_fprintf(f, "%01x", env->crf[i]);
6090: cpu_fprintf(f, " [");
1.1.1.5 ! root 6091: for (i = 0; i < 8; i++) {
! 6092: char a = '-';
! 6093: if (env->crf[i] & 0x08)
! 6094: a = 'L';
! 6095: else if (env->crf[i] & 0x04)
! 6096: a = 'G';
! 6097: else if (env->crf[i] & 0x02)
! 6098: a = 'E';
1.1 root 6099: cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
1.1.1.5 ! root 6100: }
! 6101: cpu_fprintf(f, " ] RES " ADDRX "\n", env->reserve);
1.1 root 6102: for (i = 0; i < 32; i++) {
6103: if ((i & (RFPL - 1)) == 0)
6104: cpu_fprintf(f, "FPR%02d", i);
1.1.1.3 root 6105: cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
1.1 root 6106: if ((i & (RFPL - 1)) == (RFPL - 1))
6107: cpu_fprintf(f, "\n");
6108: }
1.1.1.5 ! root 6109: #if !defined(CONFIG_USER_ONLY)
! 6110: cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
1.1 root 6111: env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
1.1.1.5 ! root 6112: #endif
1.1 root 6113:
6114: #undef RGPL
6115: #undef RFPL
1.1.1.5 ! root 6116: }
! 6117:
! 6118: void cpu_dump_statistics (CPUState *env, FILE*f,
! 6119: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
! 6120: int flags)
! 6121: {
! 6122: #if defined(DO_PPC_STATISTICS)
! 6123: opc_handler_t **t1, **t2, **t3, *handler;
! 6124: int op1, op2, op3;
! 6125:
! 6126: t1 = env->opcodes;
! 6127: for (op1 = 0; op1 < 64; op1++) {
! 6128: handler = t1[op1];
! 6129: if (is_indirect_opcode(handler)) {
! 6130: t2 = ind_table(handler);
! 6131: for (op2 = 0; op2 < 32; op2++) {
! 6132: handler = t2[op2];
! 6133: if (is_indirect_opcode(handler)) {
! 6134: t3 = ind_table(handler);
! 6135: for (op3 = 0; op3 < 32; op3++) {
! 6136: handler = t3[op3];
! 6137: if (handler->count == 0)
! 6138: continue;
! 6139: cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
! 6140: "%016llx %lld\n",
! 6141: op1, op2, op3, op1, (op3 << 5) | op2,
! 6142: handler->oname,
! 6143: handler->count, handler->count);
! 6144: }
! 6145: } else {
! 6146: if (handler->count == 0)
! 6147: continue;
! 6148: cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
! 6149: "%016llx %lld\n",
! 6150: op1, op2, op1, op2, handler->oname,
! 6151: handler->count, handler->count);
! 6152: }
! 6153: }
! 6154: } else {
! 6155: if (handler->count == 0)
! 6156: continue;
! 6157: cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
! 6158: op1, op1, handler->oname,
! 6159: handler->count, handler->count);
! 6160: }
! 6161: }
! 6162: #endif
1.1 root 6163: }
6164:
6165: /*****************************************************************************/
1.1.1.5 ! root 6166: static always_inline int gen_intermediate_code_internal (CPUState *env,
! 6167: TranslationBlock *tb,
! 6168: int search_pc)
1.1 root 6169: {
6170: DisasContext ctx, *ctxp = &ctx;
6171: opc_handler_t **table, *handler;
6172: target_ulong pc_start;
6173: uint16_t *gen_opc_end;
1.1.1.5 ! root 6174: int supervisor, little_endian;
! 6175: int single_step, branch_step;
1.1 root 6176: int j, lj = -1;
6177:
6178: pc_start = tb->pc;
6179: gen_opc_ptr = gen_opc_buf;
6180: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6181: gen_opparam_ptr = gen_opparam_buf;
1.1.1.5 ! root 6182: #if defined(OPTIMIZE_FPRF_UPDATE)
! 6183: gen_fprf_ptr = gen_fprf_buf;
! 6184: #endif
1.1.1.2 root 6185: nb_gen_labels = 0;
1.1 root 6186: ctx.nip = pc_start;
6187: ctx.tb = tb;
1.1.1.5 ! root 6188: ctx.exception = POWERPC_EXCP_NONE;
1.1 root 6189: ctx.spr_cb = env->spr_cb;
1.1.1.5 ! root 6190: supervisor = env->mmu_idx;
! 6191: #if !defined(CONFIG_USER_ONLY)
! 6192: ctx.supervisor = supervisor;
! 6193: #endif
! 6194: little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
! 6195: #if defined(TARGET_PPC64)
! 6196: ctx.sf_mode = msr_sf;
! 6197: ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
1.1 root 6198: #else
1.1.1.5 ! root 6199: ctx.mem_idx = (supervisor << 1) | little_endian;
1.1 root 6200: #endif
1.1.1.5 ! root 6201: ctx.dcache_line_size = env->dcache_line_size;
1.1 root 6202: ctx.fpu_enabled = msr_fp;
1.1.1.5 ! root 6203: if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
! 6204: ctx.spe_enabled = msr_spe;
! 6205: else
! 6206: ctx.spe_enabled = 0;
! 6207: if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
! 6208: ctx.altivec_enabled = msr_vr;
! 6209: else
! 6210: ctx.altivec_enabled = 0;
! 6211: if ((env->flags & POWERPC_FLAG_SE) && msr_se)
! 6212: single_step = 1;
! 6213: else
! 6214: single_step = 0;
! 6215: if ((env->flags & POWERPC_FLAG_BE) && msr_be)
! 6216: branch_step = 1;
! 6217: else
! 6218: branch_step = 0;
! 6219: ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1;
1.1 root 6220: #if defined (DO_SINGLE_STEP) && 0
6221: /* Single step trace mode */
6222: msr_se = 1;
6223: #endif
6224: /* Set env in case of segfault during code fetch */
1.1.1.5 ! root 6225: while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
! 6226: if (unlikely(env->nb_breakpoints > 0)) {
! 6227: for (j = 0; j < env->nb_breakpoints; j++) {
1.1.1.3 root 6228: if (env->breakpoints[j] == ctx.nip) {
1.1.1.5 ! root 6229: gen_update_nip(&ctx, ctx.nip);
1.1.1.3 root 6230: gen_op_debug();
6231: break;
6232: }
6233: }
6234: }
1.1.1.5 ! root 6235: if (unlikely(search_pc)) {
1.1 root 6236: j = gen_opc_ptr - gen_opc_buf;
6237: if (lj < j) {
6238: lj++;
6239: while (lj < j)
6240: gen_opc_instr_start[lj++] = 0;
6241: gen_opc_pc[lj] = ctx.nip;
6242: gen_opc_instr_start[lj] = 1;
6243: }
6244: }
6245: #if defined PPC_DEBUG_DISAS
6246: if (loglevel & CPU_LOG_TB_IN_ASM) {
6247: fprintf(logfile, "----------------\n");
1.1.1.5 ! root 6248: fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
! 6249: ctx.nip, supervisor, (int)msr_ir);
1.1 root 6250: }
6251: #endif
1.1.1.5 ! root 6252: if (unlikely(little_endian)) {
! 6253: ctx.opcode = bswap32(ldl_code(ctx.nip));
! 6254: } else {
! 6255: ctx.opcode = ldl_code(ctx.nip);
1.1 root 6256: }
6257: #if defined PPC_DEBUG_DISAS
6258: if (loglevel & CPU_LOG_TB_IN_ASM) {
6259: fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6260: ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
1.1.1.5 ! root 6261: opc3(ctx.opcode), little_endian ? "little" : "big");
1.1 root 6262: }
6263: #endif
6264: ctx.nip += 4;
6265: table = env->opcodes;
6266: handler = table[opc1(ctx.opcode)];
6267: if (is_indirect_opcode(handler)) {
6268: table = ind_table(handler);
6269: handler = table[opc2(ctx.opcode)];
6270: if (is_indirect_opcode(handler)) {
6271: table = ind_table(handler);
6272: handler = table[opc3(ctx.opcode)];
6273: }
6274: }
6275: /* Is opcode *REALLY* valid ? */
1.1.1.5 ! root 6276: if (unlikely(handler->handler == &gen_invalid)) {
! 6277: if (loglevel != 0) {
! 6278: fprintf(logfile, "invalid/unsupported opcode: "
! 6279: "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
! 6280: opc1(ctx.opcode), opc2(ctx.opcode),
! 6281: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
1.1 root 6282: } else {
6283: printf("invalid/unsupported opcode: "
1.1.1.5 ! root 6284: "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
1.1 root 6285: opc1(ctx.opcode), opc2(ctx.opcode),
1.1.1.5 ! root 6286: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
1.1 root 6287: }
1.1.1.5 ! root 6288: } else {
! 6289: if (unlikely((ctx.opcode & handler->inval) != 0)) {
! 6290: if (loglevel != 0) {
1.1 root 6291: fprintf(logfile, "invalid bits: %08x for opcode: "
1.1.1.5 ! root 6292: "%02x - %02x - %02x (%08x) " ADDRX "\n",
1.1 root 6293: ctx.opcode & handler->inval, opc1(ctx.opcode),
6294: opc2(ctx.opcode), opc3(ctx.opcode),
6295: ctx.opcode, ctx.nip - 4);
6296: } else {
6297: printf("invalid bits: %08x for opcode: "
1.1.1.5 ! root 6298: "%02x - %02x - %02x (%08x) " ADDRX "\n",
! 6299: ctx.opcode & handler->inval, opc1(ctx.opcode),
! 6300: opc2(ctx.opcode), opc3(ctx.opcode),
1.1 root 6301: ctx.opcode, ctx.nip - 4);
1.1.1.5 ! root 6302: }
! 6303: GEN_EXCP_INVAL(ctxp);
1.1 root 6304: break;
6305: }
6306: }
6307: (*(handler->handler))(&ctx);
1.1.1.5 ! root 6308: #if defined(DO_PPC_STATISTICS)
! 6309: handler->count++;
! 6310: #endif
1.1 root 6311: /* Check trace mode exceptions */
1.1.1.5 ! root 6312: if (unlikely(branch_step != 0 &&
! 6313: ctx.exception == POWERPC_EXCP_BRANCH)) {
! 6314: GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
! 6315: } else if (unlikely(single_step != 0 &&
! 6316: (ctx.nip <= 0x100 || ctx.nip > 0xF00 ||
! 6317: (ctx.nip & 0xFC) != 0x04) &&
! 6318: ctx.exception != POWERPC_SYSCALL &&
! 6319: ctx.exception != POWERPC_EXCP_TRAP)) {
! 6320: GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
! 6321: } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
! 6322: (env->singlestep_enabled))) {
! 6323: /* if we reach a page boundary or are single stepping, stop
! 6324: * generation
1.1 root 6325: */
6326: break;
1.1.1.5 ! root 6327: }
1.1 root 6328: #if defined (DO_SINGLE_STEP)
6329: break;
6330: #endif
6331: }
1.1.1.5 ! root 6332: if (ctx.exception == POWERPC_EXCP_NONE) {
1.1.1.2 root 6333: gen_goto_tb(&ctx, 0, ctx.nip);
1.1.1.5 ! root 6334: } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
! 6335: gen_op_reset_T0();
! 6336: /* Generate the return instruction */
! 6337: gen_op_exit_tb();
1.1 root 6338: }
6339: *gen_opc_ptr = INDEX_op_end;
1.1.1.5 ! root 6340: if (unlikely(search_pc)) {
1.1 root 6341: j = gen_opc_ptr - gen_opc_buf;
6342: lj++;
6343: while (lj <= j)
6344: gen_opc_instr_start[lj++] = 0;
6345: } else {
6346: tb->size = ctx.nip - pc_start;
6347: }
1.1.1.5 ! root 6348: #if defined(DEBUG_DISAS)
1.1 root 6349: if (loglevel & CPU_LOG_TB_CPU) {
6350: fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
6351: cpu_dump_state(env, logfile, fprintf, 0);
6352: }
6353: if (loglevel & CPU_LOG_TB_IN_ASM) {
1.1.1.5 ! root 6354: int flags;
! 6355: flags = env->bfd_mach;
! 6356: flags |= little_endian << 16;
1.1 root 6357: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1.1.1.5 ! root 6358: target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
1.1 root 6359: fprintf(logfile, "\n");
6360: }
6361: if (loglevel & CPU_LOG_TB_OP) {
6362: fprintf(logfile, "OP:\n");
6363: dump_ops(gen_opc_buf, gen_opparam_buf);
6364: fprintf(logfile, "\n");
6365: }
6366: #endif
6367: return 0;
6368: }
6369:
6370: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6371: {
6372: return gen_intermediate_code_internal(env, tb, 0);
6373: }
6374:
6375: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6376: {
6377: return gen_intermediate_code_internal(env, tb, 1);
6378: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.