|
|
1.1 ! root 1: /* ! 2: * PowerPC emulation for qemu: main translation routines. ! 3: * ! 4: * Copyright (c) 2003-2005 Jocelyn Mayer ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, 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: ! 30: //#define DO_SINGLE_STEP ! 31: //#define PPC_DEBUG_DISAS ! 32: ! 33: enum { ! 34: #define DEF(s, n, copy_size) INDEX_op_ ## s, ! 35: #include "opc.h" ! 36: #undef DEF ! 37: NB_OPS, ! 38: }; ! 39: ! 40: static uint16_t *gen_opc_ptr; ! 41: static uint32_t *gen_opparam_ptr; ! 42: ! 43: #include "gen-op.h" ! 44: ! 45: #define GEN8(func, NAME) \ ! 46: static GenOpFunc *NAME ## _table [8] = { \ ! 47: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \ ! 48: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \ ! 49: }; \ ! 50: static inline void func(int n) \ ! 51: { \ ! 52: NAME ## _table[n](); \ ! 53: } ! 54: ! 55: #define GEN16(func, NAME) \ ! 56: static GenOpFunc *NAME ## _table [16] = { \ ! 57: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \ ! 58: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \ ! 59: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \ ! 60: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \ ! 61: }; \ ! 62: static inline void func(int n) \ ! 63: { \ ! 64: NAME ## _table[n](); \ ! 65: } ! 66: ! 67: #define GEN32(func, NAME) \ ! 68: static GenOpFunc *NAME ## _table [32] = { \ ! 69: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \ ! 70: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \ ! 71: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \ ! 72: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \ ! 73: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \ ! 74: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \ ! 75: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \ ! 76: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \ ! 77: }; \ ! 78: static inline void func(int n) \ ! 79: { \ ! 80: NAME ## _table[n](); \ ! 81: } ! 82: ! 83: /* Condition register moves */ ! 84: GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf); ! 85: GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf); ! 86: GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf); ! 87: GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf); ! 88: ! 89: /* Floating point condition and status register moves */ ! 90: GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr); ! 91: GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr); ! 92: GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr); ! 93: static GenOpFunc1 *gen_op_store_T0_fpscri_fpscr_table[8] = { ! 94: &gen_op_store_T0_fpscri_fpscr0, ! 95: &gen_op_store_T0_fpscri_fpscr1, ! 96: &gen_op_store_T0_fpscri_fpscr2, ! 97: &gen_op_store_T0_fpscri_fpscr3, ! 98: &gen_op_store_T0_fpscri_fpscr4, ! 99: &gen_op_store_T0_fpscri_fpscr5, ! 100: &gen_op_store_T0_fpscri_fpscr6, ! 101: &gen_op_store_T0_fpscri_fpscr7, ! 102: }; ! 103: static inline void gen_op_store_T0_fpscri(int n, uint8_t param) ! 104: { ! 105: (*gen_op_store_T0_fpscri_fpscr_table[n])(param); ! 106: } ! 107: ! 108: /* Segment register moves */ ! 109: GEN16(gen_op_load_sr, gen_op_load_sr); ! 110: GEN16(gen_op_store_sr, gen_op_store_sr); ! 111: ! 112: /* General purpose registers moves */ ! 113: GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr); ! 114: GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr); ! 115: GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr); ! 116: ! 117: GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr); ! 118: GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr); ! 119: GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr); ! 120: ! 121: /* floating point registers moves */ ! 122: GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr); ! 123: GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr); ! 124: GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr); ! 125: GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr); ! 126: GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr); ! 127: GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr); ! 128: ! 129: static uint8_t spr_access[1024 / 2]; ! 130: ! 131: /* internal defines */ ! 132: typedef struct DisasContext { ! 133: struct TranslationBlock *tb; ! 134: target_ulong nip; ! 135: uint32_t opcode; ! 136: uint32_t exception; ! 137: /* Routine used to access memory */ ! 138: int mem_idx; ! 139: /* Translation flags */ ! 140: #if !defined(CONFIG_USER_ONLY) ! 141: int supervisor; ! 142: #endif ! 143: int fpu_enabled; ! 144: ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ ! 145: } DisasContext; ! 146: ! 147: struct opc_handler_t { ! 148: /* invalid bits */ ! 149: uint32_t inval; ! 150: /* instruction type */ ! 151: uint32_t type; ! 152: /* handler */ ! 153: void (*handler)(DisasContext *ctx); ! 154: }; ! 155: ! 156: #define RET_EXCP(ctx, excp, error) \ ! 157: do { \ ! 158: if ((ctx)->exception == EXCP_NONE) { \ ! 159: gen_op_update_nip((ctx)->nip); \ ! 160: } \ ! 161: gen_op_raise_exception_err((excp), (error)); \ ! 162: ctx->exception = (excp); \ ! 163: } while (0) ! 164: ! 165: #define RET_INVAL(ctx) \ ! 166: RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL) ! 167: ! 168: #define RET_PRIVOPC(ctx) \ ! 169: RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC) ! 170: ! 171: #define RET_PRIVREG(ctx) \ ! 172: RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG) ! 173: ! 174: #define RET_MTMSR(ctx) \ ! 175: RET_EXCP((ctx), EXCP_MTMSR, 0) ! 176: ! 177: static inline void RET_STOP (DisasContext *ctx) ! 178: { ! 179: RET_EXCP(ctx, EXCP_MTMSR, 0); ! 180: } ! 181: ! 182: static inline void RET_CHG_FLOW (DisasContext *ctx) ! 183: { ! 184: gen_op_raise_exception_err(EXCP_MTMSR, 0); ! 185: ctx->exception = EXCP_MTMSR; ! 186: } ! 187: ! 188: #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \ ! 189: static void gen_##name (DisasContext *ctx); \ ! 190: GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \ ! 191: static void gen_##name (DisasContext *ctx) ! 192: ! 193: typedef struct opcode_t { ! 194: unsigned char opc1, opc2, opc3; ! 195: #if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */ ! 196: unsigned char pad[5]; ! 197: #else ! 198: unsigned char pad[1]; ! 199: #endif ! 200: opc_handler_t handler; ! 201: const unsigned char *oname; ! 202: } opcode_t; ! 203: ! 204: /*** Instruction decoding ***/ ! 205: #define EXTRACT_HELPER(name, shift, nb) \ ! 206: static inline uint32_t name (uint32_t opcode) \ ! 207: { \ ! 208: return (opcode >> (shift)) & ((1 << (nb)) - 1); \ ! 209: } ! 210: ! 211: #define EXTRACT_SHELPER(name, shift, nb) \ ! 212: static inline int32_t name (uint32_t opcode) \ ! 213: { \ ! 214: return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \ ! 215: } ! 216: ! 217: /* Opcode part 1 */ ! 218: EXTRACT_HELPER(opc1, 26, 6); ! 219: /* Opcode part 2 */ ! 220: EXTRACT_HELPER(opc2, 1, 5); ! 221: /* Opcode part 3 */ ! 222: EXTRACT_HELPER(opc3, 6, 5); ! 223: /* Update Cr0 flags */ ! 224: EXTRACT_HELPER(Rc, 0, 1); ! 225: /* Destination */ ! 226: EXTRACT_HELPER(rD, 21, 5); ! 227: /* Source */ ! 228: EXTRACT_HELPER(rS, 21, 5); ! 229: /* First operand */ ! 230: EXTRACT_HELPER(rA, 16, 5); ! 231: /* Second operand */ ! 232: EXTRACT_HELPER(rB, 11, 5); ! 233: /* Third operand */ ! 234: EXTRACT_HELPER(rC, 6, 5); ! 235: /*** Get CRn ***/ ! 236: EXTRACT_HELPER(crfD, 23, 3); ! 237: EXTRACT_HELPER(crfS, 18, 3); ! 238: EXTRACT_HELPER(crbD, 21, 5); ! 239: EXTRACT_HELPER(crbA, 16, 5); ! 240: EXTRACT_HELPER(crbB, 11, 5); ! 241: /* SPR / TBL */ ! 242: EXTRACT_HELPER(_SPR, 11, 10); ! 243: static inline uint32_t SPR (uint32_t opcode) ! 244: { ! 245: uint32_t sprn = _SPR(opcode); ! 246: ! 247: return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5); ! 248: } ! 249: /*** Get constants ***/ ! 250: EXTRACT_HELPER(IMM, 12, 8); ! 251: /* 16 bits signed immediate value */ ! 252: EXTRACT_SHELPER(SIMM, 0, 16); ! 253: /* 16 bits unsigned immediate value */ ! 254: EXTRACT_HELPER(UIMM, 0, 16); ! 255: /* Bit count */ ! 256: EXTRACT_HELPER(NB, 11, 5); ! 257: /* Shift count */ ! 258: EXTRACT_HELPER(SH, 11, 5); ! 259: /* Mask start */ ! 260: EXTRACT_HELPER(MB, 6, 5); ! 261: /* Mask end */ ! 262: EXTRACT_HELPER(ME, 1, 5); ! 263: /* Trap operand */ ! 264: EXTRACT_HELPER(TO, 21, 5); ! 265: ! 266: EXTRACT_HELPER(CRM, 12, 8); ! 267: EXTRACT_HELPER(FM, 17, 8); ! 268: EXTRACT_HELPER(SR, 16, 4); ! 269: EXTRACT_HELPER(FPIMM, 20, 4); ! 270: ! 271: /*** Jump target decoding ***/ ! 272: /* Displacement */ ! 273: EXTRACT_SHELPER(d, 0, 16); ! 274: /* Immediate address */ ! 275: static inline uint32_t LI (uint32_t opcode) ! 276: { ! 277: return (opcode >> 0) & 0x03FFFFFC; ! 278: } ! 279: ! 280: static inline uint32_t BD (uint32_t opcode) ! 281: { ! 282: return (opcode >> 0) & 0xFFFC; ! 283: } ! 284: ! 285: EXTRACT_HELPER(BO, 21, 5); ! 286: EXTRACT_HELPER(BI, 16, 5); ! 287: /* Absolute/relative address */ ! 288: EXTRACT_HELPER(AA, 1, 1); ! 289: /* Link */ ! 290: EXTRACT_HELPER(LK, 0, 1); ! 291: ! 292: /* Create a mask between <start> and <end> bits */ ! 293: static inline uint32_t MASK (uint32_t start, uint32_t end) ! 294: { ! 295: uint32_t ret; ! 296: ! 297: ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1); ! 298: if (start > end) ! 299: return ~ret; ! 300: ! 301: return ret; ! 302: } ! 303: ! 304: #if HOST_LONG_BITS == 64 ! 305: #define OPC_ALIGN 8 ! 306: #else ! 307: #define OPC_ALIGN 4 ! 308: #endif ! 309: #if defined(__APPLE__) ! 310: #define OPCODES_SECTION \ ! 311: __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) )) ! 312: #else ! 313: #define OPCODES_SECTION \ ! 314: __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) )) ! 315: #endif ! 316: ! 317: #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \ ! 318: OPCODES_SECTION opcode_t opc_##name = { \ ! 319: .opc1 = op1, \ ! 320: .opc2 = op2, \ ! 321: .opc3 = op3, \ ! 322: .pad = { 0, }, \ ! 323: .handler = { \ ! 324: .inval = invl, \ ! 325: .type = _typ, \ ! 326: .handler = &gen_##name, \ ! 327: }, \ ! 328: .oname = stringify(name), \ ! 329: } ! 330: ! 331: #define GEN_OPCODE_MARK(name) \ ! 332: OPCODES_SECTION opcode_t opc_##name = { \ ! 333: .opc1 = 0xFF, \ ! 334: .opc2 = 0xFF, \ ! 335: .opc3 = 0xFF, \ ! 336: .pad = { 0, }, \ ! 337: .handler = { \ ! 338: .inval = 0x00000000, \ ! 339: .type = 0x00, \ ! 340: .handler = NULL, \ ! 341: }, \ ! 342: .oname = stringify(name), \ ! 343: } ! 344: ! 345: /* Start opcode list */ ! 346: GEN_OPCODE_MARK(start); ! 347: ! 348: /* Invalid instruction */ ! 349: GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE) ! 350: { ! 351: RET_INVAL(ctx); ! 352: } ! 353: ! 354: static opc_handler_t invalid_handler = { ! 355: .inval = 0xFFFFFFFF, ! 356: .type = PPC_NONE, ! 357: .handler = gen_invalid, ! 358: }; ! 359: ! 360: /*** Integer arithmetic ***/ ! 361: #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval) \ ! 362: GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \ ! 363: { \ ! 364: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 365: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 366: gen_op_##name(); \ ! 367: if (Rc(ctx->opcode) != 0) \ ! 368: gen_op_set_Rc0(); \ ! 369: gen_op_store_T0_gpr(rD(ctx->opcode)); \ ! 370: } ! 371: ! 372: #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \ ! 373: GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \ ! 374: { \ ! 375: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 376: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 377: gen_op_##name(); \ ! 378: if (Rc(ctx->opcode) != 0) \ ! 379: gen_op_set_Rc0(); \ ! 380: gen_op_store_T0_gpr(rD(ctx->opcode)); \ ! 381: } ! 382: ! 383: #define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \ ! 384: GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \ ! 385: { \ ! 386: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 387: gen_op_##name(); \ ! 388: if (Rc(ctx->opcode) != 0) \ ! 389: gen_op_set_Rc0(); \ ! 390: gen_op_store_T0_gpr(rD(ctx->opcode)); \ ! 391: } ! 392: #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \ ! 393: GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \ ! 394: { \ ! 395: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 396: gen_op_##name(); \ ! 397: if (Rc(ctx->opcode) != 0) \ ! 398: gen_op_set_Rc0(); \ ! 399: gen_op_store_T0_gpr(rD(ctx->opcode)); \ ! 400: } ! 401: ! 402: /* Two operands arithmetic functions */ ! 403: #define GEN_INT_ARITH2(name, opc1, opc2, opc3) \ ! 404: __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000) \ ! 405: __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000) ! 406: ! 407: /* Two operands arithmetic functions with no overflow allowed */ ! 408: #define GEN_INT_ARITHN(name, opc1, opc2, opc3) \ ! 409: __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400) ! 410: ! 411: /* One operand arithmetic functions */ ! 412: #define GEN_INT_ARITH1(name, opc1, opc2, opc3) \ ! 413: __GEN_INT_ARITH1(name, opc1, opc2, opc3) \ ! 414: __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10) ! 415: ! 416: /* add add. addo addo. */ ! 417: GEN_INT_ARITH2 (add, 0x1F, 0x0A, 0x08); ! 418: /* addc addc. addco addco. */ ! 419: GEN_INT_ARITH2 (addc, 0x1F, 0x0A, 0x00); ! 420: /* adde adde. addeo addeo. */ ! 421: GEN_INT_ARITH2 (adde, 0x1F, 0x0A, 0x04); ! 422: /* addme addme. addmeo addmeo. */ ! 423: GEN_INT_ARITH1 (addme, 0x1F, 0x0A, 0x07); ! 424: /* addze addze. addzeo addzeo. */ ! 425: GEN_INT_ARITH1 (addze, 0x1F, 0x0A, 0x06); ! 426: /* divw divw. divwo divwo. */ ! 427: GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F); ! 428: /* divwu divwu. divwuo divwuo. */ ! 429: GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E); ! 430: /* mulhw mulhw. */ ! 431: GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02); ! 432: /* mulhwu mulhwu. */ ! 433: GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00); ! 434: /* mullw mullw. mullwo mullwo. */ ! 435: GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07); ! 436: /* neg neg. nego nego. */ ! 437: GEN_INT_ARITH1 (neg, 0x1F, 0x08, 0x03); ! 438: /* subf subf. subfo subfo. */ ! 439: GEN_INT_ARITH2 (subf, 0x1F, 0x08, 0x01); ! 440: /* subfc subfc. subfco subfco. */ ! 441: GEN_INT_ARITH2 (subfc, 0x1F, 0x08, 0x00); ! 442: /* subfe subfe. subfeo subfeo. */ ! 443: GEN_INT_ARITH2 (subfe, 0x1F, 0x08, 0x04); ! 444: /* subfme subfme. subfmeo subfmeo. */ ! 445: GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07); ! 446: /* subfze subfze. subfzeo subfzeo. */ ! 447: GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06); ! 448: /* addi */ ! 449: GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 450: { ! 451: int32_t simm = SIMM(ctx->opcode); ! 452: ! 453: if (rA(ctx->opcode) == 0) { ! 454: gen_op_set_T0(simm); ! 455: } else { ! 456: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 457: gen_op_addi(simm); ! 458: } ! 459: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 460: } ! 461: /* addic */ ! 462: GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 463: { ! 464: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 465: gen_op_addic(SIMM(ctx->opcode)); ! 466: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 467: } ! 468: /* addic. */ ! 469: GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 470: { ! 471: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 472: gen_op_addic(SIMM(ctx->opcode)); ! 473: gen_op_set_Rc0(); ! 474: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 475: } ! 476: /* addis */ ! 477: GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 478: { ! 479: int32_t simm = SIMM(ctx->opcode); ! 480: ! 481: if (rA(ctx->opcode) == 0) { ! 482: gen_op_set_T0(simm << 16); ! 483: } else { ! 484: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 485: gen_op_addi(simm << 16); ! 486: } ! 487: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 488: } ! 489: /* mulli */ ! 490: GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 491: { ! 492: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 493: gen_op_mulli(SIMM(ctx->opcode)); ! 494: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 495: } ! 496: /* subfic */ ! 497: GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 498: { ! 499: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 500: gen_op_subfic(SIMM(ctx->opcode)); ! 501: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 502: } ! 503: ! 504: /*** Integer comparison ***/ ! 505: #define GEN_CMP(name, opc) \ ! 506: GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \ ! 507: { \ ! 508: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 509: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 510: gen_op_##name(); \ ! 511: gen_op_store_T0_crf(crfD(ctx->opcode)); \ ! 512: } ! 513: ! 514: /* cmp */ ! 515: GEN_CMP(cmp, 0x00); ! 516: /* cmpi */ ! 517: GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER) ! 518: { ! 519: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 520: gen_op_cmpi(SIMM(ctx->opcode)); ! 521: gen_op_store_T0_crf(crfD(ctx->opcode)); ! 522: } ! 523: /* cmpl */ ! 524: GEN_CMP(cmpl, 0x01); ! 525: /* cmpli */ ! 526: GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER) ! 527: { ! 528: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 529: gen_op_cmpli(UIMM(ctx->opcode)); ! 530: gen_op_store_T0_crf(crfD(ctx->opcode)); ! 531: } ! 532: ! 533: /*** Integer logical ***/ ! 534: #define __GEN_LOGICAL2(name, opc2, opc3) \ ! 535: GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \ ! 536: { \ ! 537: gen_op_load_gpr_T0(rS(ctx->opcode)); \ ! 538: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 539: gen_op_##name(); \ ! 540: if (Rc(ctx->opcode) != 0) \ ! 541: gen_op_set_Rc0(); \ ! 542: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 543: } ! 544: #define GEN_LOGICAL2(name, opc) \ ! 545: __GEN_LOGICAL2(name, 0x1C, opc) ! 546: ! 547: #define GEN_LOGICAL1(name, opc) \ ! 548: GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \ ! 549: { \ ! 550: gen_op_load_gpr_T0(rS(ctx->opcode)); \ ! 551: gen_op_##name(); \ ! 552: if (Rc(ctx->opcode) != 0) \ ! 553: gen_op_set_Rc0(); \ ! 554: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 555: } ! 556: ! 557: /* and & and. */ ! 558: GEN_LOGICAL2(and, 0x00); ! 559: /* andc & andc. */ ! 560: GEN_LOGICAL2(andc, 0x01); ! 561: /* andi. */ ! 562: GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 563: { ! 564: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 565: gen_op_andi_(UIMM(ctx->opcode)); ! 566: gen_op_set_Rc0(); ! 567: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 568: } ! 569: /* andis. */ ! 570: GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 571: { ! 572: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 573: gen_op_andi_(UIMM(ctx->opcode) << 16); ! 574: gen_op_set_Rc0(); ! 575: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 576: } ! 577: ! 578: /* cntlzw */ ! 579: GEN_LOGICAL1(cntlzw, 0x00); ! 580: /* eqv & eqv. */ ! 581: GEN_LOGICAL2(eqv, 0x08); ! 582: /* extsb & extsb. */ ! 583: GEN_LOGICAL1(extsb, 0x1D); ! 584: /* extsh & extsh. */ ! 585: GEN_LOGICAL1(extsh, 0x1C); ! 586: /* nand & nand. */ ! 587: GEN_LOGICAL2(nand, 0x0E); ! 588: /* nor & nor. */ ! 589: GEN_LOGICAL2(nor, 0x03); ! 590: ! 591: /* or & or. */ ! 592: GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER) ! 593: { ! 594: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 595: /* Optimisation for mr case */ ! 596: if (rS(ctx->opcode) != rB(ctx->opcode)) { ! 597: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 598: gen_op_or(); ! 599: } ! 600: if (Rc(ctx->opcode) != 0) ! 601: gen_op_set_Rc0(); ! 602: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 603: } ! 604: ! 605: /* orc & orc. */ ! 606: GEN_LOGICAL2(orc, 0x0C); ! 607: /* xor & xor. */ ! 608: GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER) ! 609: { ! 610: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 611: /* Optimisation for "set to zero" case */ ! 612: if (rS(ctx->opcode) != rB(ctx->opcode)) { ! 613: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 614: gen_op_xor(); ! 615: } else { ! 616: gen_op_set_T0(0); ! 617: } ! 618: if (Rc(ctx->opcode) != 0) ! 619: gen_op_set_Rc0(); ! 620: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 621: } ! 622: /* ori */ ! 623: GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 624: { ! 625: uint32_t uimm = UIMM(ctx->opcode); ! 626: ! 627: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { ! 628: /* NOP */ ! 629: return; ! 630: } ! 631: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 632: if (uimm != 0) ! 633: gen_op_ori(uimm); ! 634: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 635: } ! 636: /* oris */ ! 637: GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 638: { ! 639: uint32_t uimm = UIMM(ctx->opcode); ! 640: ! 641: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { ! 642: /* NOP */ ! 643: return; ! 644: } ! 645: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 646: if (uimm != 0) ! 647: gen_op_ori(uimm << 16); ! 648: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 649: } ! 650: /* xori */ ! 651: GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 652: { ! 653: uint32_t uimm = UIMM(ctx->opcode); ! 654: ! 655: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { ! 656: /* NOP */ ! 657: return; ! 658: } ! 659: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 660: if (uimm != 0) ! 661: gen_op_xori(uimm); ! 662: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 663: } ! 664: ! 665: /* xoris */ ! 666: GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 667: { ! 668: uint32_t uimm = UIMM(ctx->opcode); ! 669: ! 670: if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { ! 671: /* NOP */ ! 672: return; ! 673: } ! 674: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 675: if (uimm != 0) ! 676: gen_op_xori(uimm << 16); ! 677: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 678: } ! 679: ! 680: /*** Integer rotate ***/ ! 681: /* rlwimi & rlwimi. */ ! 682: GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 683: { ! 684: uint32_t mb, me; ! 685: ! 686: mb = MB(ctx->opcode); ! 687: me = ME(ctx->opcode); ! 688: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 689: gen_op_load_gpr_T1(rA(ctx->opcode)); ! 690: gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me)); ! 691: if (Rc(ctx->opcode) != 0) ! 692: gen_op_set_Rc0(); ! 693: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 694: } ! 695: /* rlwinm & rlwinm. */ ! 696: GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 697: { ! 698: uint32_t mb, me, sh; ! 699: ! 700: sh = SH(ctx->opcode); ! 701: mb = MB(ctx->opcode); ! 702: me = ME(ctx->opcode); ! 703: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 704: #if 1 // TRY ! 705: if (sh == 0) { ! 706: gen_op_andi_(MASK(mb, me)); ! 707: goto store; ! 708: } ! 709: #endif ! 710: if (mb == 0) { ! 711: if (me == 31) { ! 712: gen_op_rotlwi(sh); ! 713: goto store; ! 714: #if 0 ! 715: } else if (me == (31 - sh)) { ! 716: gen_op_slwi(sh); ! 717: goto store; ! 718: #endif ! 719: } ! 720: } else if (me == 31) { ! 721: #if 0 ! 722: if (sh == (32 - mb)) { ! 723: gen_op_srwi(mb); ! 724: goto store; ! 725: } ! 726: #endif ! 727: } ! 728: gen_op_rlwinm(sh, MASK(mb, me)); ! 729: store: ! 730: if (Rc(ctx->opcode) != 0) ! 731: gen_op_set_Rc0(); ! 732: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 733: } ! 734: /* rlwnm & rlwnm. */ ! 735: GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 736: { ! 737: uint32_t mb, me; ! 738: ! 739: mb = MB(ctx->opcode); ! 740: me = ME(ctx->opcode); ! 741: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 742: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 743: if (mb == 0 && me == 31) { ! 744: gen_op_rotl(); ! 745: } else ! 746: { ! 747: gen_op_rlwnm(MASK(mb, me)); ! 748: } ! 749: if (Rc(ctx->opcode) != 0) ! 750: gen_op_set_Rc0(); ! 751: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 752: } ! 753: ! 754: /*** Integer shift ***/ ! 755: /* slw & slw. */ ! 756: __GEN_LOGICAL2(slw, 0x18, 0x00); ! 757: /* sraw & sraw. */ ! 758: __GEN_LOGICAL2(sraw, 0x18, 0x18); ! 759: /* srawi & srawi. */ ! 760: GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) ! 761: { ! 762: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 763: if (SH(ctx->opcode) != 0) ! 764: gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31)); ! 765: if (Rc(ctx->opcode) != 0) ! 766: gen_op_set_Rc0(); ! 767: gen_op_store_T0_gpr(rA(ctx->opcode)); ! 768: } ! 769: /* srw & srw. */ ! 770: __GEN_LOGICAL2(srw, 0x18, 0x10); ! 771: ! 772: /*** Floating-Point arithmetic ***/ ! 773: #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat) \ ! 774: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ ! 775: { \ ! 776: if (!ctx->fpu_enabled) { \ ! 777: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 778: return; \ ! 779: } \ ! 780: gen_op_reset_scrfx(); \ ! 781: gen_op_load_fpr_FT0(rA(ctx->opcode)); \ ! 782: gen_op_load_fpr_FT1(rC(ctx->opcode)); \ ! 783: gen_op_load_fpr_FT2(rB(ctx->opcode)); \ ! 784: gen_op_f##op(); \ ! 785: if (isfloat) { \ ! 786: gen_op_frsp(); \ ! 787: } \ ! 788: gen_op_store_FT0_fpr(rD(ctx->opcode)); \ ! 789: if (Rc(ctx->opcode)) \ ! 790: gen_op_set_Rc1(); \ ! 791: } ! 792: ! 793: #define GEN_FLOAT_ACB(name, op2) \ ! 794: _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0); \ ! 795: _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1); ! 796: ! 797: #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \ ! 798: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ ! 799: { \ ! 800: if (!ctx->fpu_enabled) { \ ! 801: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 802: return; \ ! 803: } \ ! 804: gen_op_reset_scrfx(); \ ! 805: gen_op_load_fpr_FT0(rA(ctx->opcode)); \ ! 806: gen_op_load_fpr_FT1(rB(ctx->opcode)); \ ! 807: gen_op_f##op(); \ ! 808: if (isfloat) { \ ! 809: gen_op_frsp(); \ ! 810: } \ ! 811: gen_op_store_FT0_fpr(rD(ctx->opcode)); \ ! 812: if (Rc(ctx->opcode)) \ ! 813: gen_op_set_Rc1(); \ ! 814: } ! 815: #define GEN_FLOAT_AB(name, op2, inval) \ ! 816: _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \ ! 817: _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1); ! 818: ! 819: #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \ ! 820: GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ ! 821: { \ ! 822: if (!ctx->fpu_enabled) { \ ! 823: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 824: return; \ ! 825: } \ ! 826: gen_op_reset_scrfx(); \ ! 827: gen_op_load_fpr_FT0(rA(ctx->opcode)); \ ! 828: gen_op_load_fpr_FT1(rC(ctx->opcode)); \ ! 829: gen_op_f##op(); \ ! 830: if (isfloat) { \ ! 831: gen_op_frsp(); \ ! 832: } \ ! 833: gen_op_store_FT0_fpr(rD(ctx->opcode)); \ ! 834: if (Rc(ctx->opcode)) \ ! 835: gen_op_set_Rc1(); \ ! 836: } ! 837: #define GEN_FLOAT_AC(name, op2, inval) \ ! 838: _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \ ! 839: _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1); ! 840: ! 841: #define GEN_FLOAT_B(name, op2, op3) \ ! 842: GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ ! 843: { \ ! 844: if (!ctx->fpu_enabled) { \ ! 845: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 846: return; \ ! 847: } \ ! 848: gen_op_reset_scrfx(); \ ! 849: gen_op_load_fpr_FT0(rB(ctx->opcode)); \ ! 850: gen_op_f##name(); \ ! 851: gen_op_store_FT0_fpr(rD(ctx->opcode)); \ ! 852: if (Rc(ctx->opcode)) \ ! 853: gen_op_set_Rc1(); \ ! 854: } ! 855: ! 856: #define GEN_FLOAT_BS(name, op1, op2) \ ! 857: GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ ! 858: { \ ! 859: if (!ctx->fpu_enabled) { \ ! 860: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 861: return; \ ! 862: } \ ! 863: gen_op_reset_scrfx(); \ ! 864: gen_op_load_fpr_FT0(rB(ctx->opcode)); \ ! 865: gen_op_f##name(); \ ! 866: gen_op_store_FT0_fpr(rD(ctx->opcode)); \ ! 867: if (Rc(ctx->opcode)) \ ! 868: gen_op_set_Rc1(); \ ! 869: } ! 870: ! 871: /* fadd - fadds */ ! 872: GEN_FLOAT_AB(add, 0x15, 0x000007C0); ! 873: /* fdiv - fdivs */ ! 874: GEN_FLOAT_AB(div, 0x12, 0x000007C0); ! 875: /* fmul - fmuls */ ! 876: GEN_FLOAT_AC(mul, 0x19, 0x0000F800); ! 877: ! 878: /* fres */ ! 879: GEN_FLOAT_BS(res, 0x3B, 0x18); ! 880: ! 881: /* frsqrte */ ! 882: GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A); ! 883: ! 884: /* fsel */ ! 885: _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0); ! 886: /* fsub - fsubs */ ! 887: GEN_FLOAT_AB(sub, 0x14, 0x000007C0); ! 888: /* Optional: */ ! 889: /* fsqrt */ ! 890: GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) ! 891: { ! 892: if (!ctx->fpu_enabled) { ! 893: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 894: return; ! 895: } ! 896: gen_op_reset_scrfx(); ! 897: gen_op_load_fpr_FT0(rB(ctx->opcode)); ! 898: gen_op_fsqrt(); ! 899: gen_op_store_FT0_fpr(rD(ctx->opcode)); ! 900: if (Rc(ctx->opcode)) ! 901: gen_op_set_Rc1(); ! 902: } ! 903: ! 904: GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) ! 905: { ! 906: if (!ctx->fpu_enabled) { ! 907: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 908: return; ! 909: } ! 910: gen_op_reset_scrfx(); ! 911: gen_op_load_fpr_FT0(rB(ctx->opcode)); ! 912: gen_op_fsqrt(); ! 913: gen_op_frsp(); ! 914: gen_op_store_FT0_fpr(rD(ctx->opcode)); ! 915: if (Rc(ctx->opcode)) ! 916: gen_op_set_Rc1(); ! 917: } ! 918: ! 919: /*** Floating-Point multiply-and-add ***/ ! 920: /* fmadd - fmadds */ ! 921: GEN_FLOAT_ACB(madd, 0x1D); ! 922: /* fmsub - fmsubs */ ! 923: GEN_FLOAT_ACB(msub, 0x1C); ! 924: /* fnmadd - fnmadds */ ! 925: GEN_FLOAT_ACB(nmadd, 0x1F); ! 926: /* fnmsub - fnmsubs */ ! 927: GEN_FLOAT_ACB(nmsub, 0x1E); ! 928: ! 929: /*** Floating-Point round & convert ***/ ! 930: /* fctiw */ ! 931: GEN_FLOAT_B(ctiw, 0x0E, 0x00); ! 932: /* fctiwz */ ! 933: GEN_FLOAT_B(ctiwz, 0x0F, 0x00); ! 934: /* frsp */ ! 935: GEN_FLOAT_B(rsp, 0x0C, 0x00); ! 936: ! 937: /*** Floating-Point compare ***/ ! 938: /* fcmpo */ ! 939: GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) ! 940: { ! 941: if (!ctx->fpu_enabled) { ! 942: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 943: return; ! 944: } ! 945: gen_op_reset_scrfx(); ! 946: gen_op_load_fpr_FT0(rA(ctx->opcode)); ! 947: gen_op_load_fpr_FT1(rB(ctx->opcode)); ! 948: gen_op_fcmpo(); ! 949: gen_op_store_T0_crf(crfD(ctx->opcode)); ! 950: } ! 951: ! 952: /* fcmpu */ ! 953: GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) ! 954: { ! 955: if (!ctx->fpu_enabled) { ! 956: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 957: return; ! 958: } ! 959: gen_op_reset_scrfx(); ! 960: gen_op_load_fpr_FT0(rA(ctx->opcode)); ! 961: gen_op_load_fpr_FT1(rB(ctx->opcode)); ! 962: gen_op_fcmpu(); ! 963: gen_op_store_T0_crf(crfD(ctx->opcode)); ! 964: } ! 965: ! 966: /*** Floating-point move ***/ ! 967: /* fabs */ ! 968: GEN_FLOAT_B(abs, 0x08, 0x08); ! 969: ! 970: /* fmr - fmr. */ ! 971: GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT) ! 972: { ! 973: if (!ctx->fpu_enabled) { ! 974: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 975: return; ! 976: } ! 977: gen_op_reset_scrfx(); ! 978: gen_op_load_fpr_FT0(rB(ctx->opcode)); ! 979: gen_op_store_FT0_fpr(rD(ctx->opcode)); ! 980: if (Rc(ctx->opcode)) ! 981: gen_op_set_Rc1(); ! 982: } ! 983: ! 984: /* fnabs */ ! 985: GEN_FLOAT_B(nabs, 0x08, 0x04); ! 986: /* fneg */ ! 987: GEN_FLOAT_B(neg, 0x08, 0x01); ! 988: ! 989: /*** Floating-Point status & ctrl register ***/ ! 990: /* mcrfs */ ! 991: GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) ! 992: { ! 993: if (!ctx->fpu_enabled) { ! 994: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 995: return; ! 996: } ! 997: gen_op_load_fpscr_T0(crfS(ctx->opcode)); ! 998: gen_op_store_T0_crf(crfD(ctx->opcode)); ! 999: gen_op_clear_fpscr(crfS(ctx->opcode)); ! 1000: } ! 1001: ! 1002: /* mffs */ ! 1003: GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) ! 1004: { ! 1005: if (!ctx->fpu_enabled) { ! 1006: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 1007: return; ! 1008: } ! 1009: gen_op_load_fpscr(); ! 1010: gen_op_store_FT0_fpr(rD(ctx->opcode)); ! 1011: if (Rc(ctx->opcode)) ! 1012: gen_op_set_Rc1(); ! 1013: } ! 1014: ! 1015: /* mtfsb0 */ ! 1016: GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) ! 1017: { ! 1018: uint8_t crb; ! 1019: ! 1020: if (!ctx->fpu_enabled) { ! 1021: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 1022: return; ! 1023: } ! 1024: crb = crbD(ctx->opcode) >> 2; ! 1025: gen_op_load_fpscr_T0(crb); ! 1026: gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03))); ! 1027: gen_op_store_T0_fpscr(crb); ! 1028: if (Rc(ctx->opcode)) ! 1029: gen_op_set_Rc1(); ! 1030: } ! 1031: ! 1032: /* mtfsb1 */ ! 1033: GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) ! 1034: { ! 1035: uint8_t crb; ! 1036: ! 1037: if (!ctx->fpu_enabled) { ! 1038: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 1039: return; ! 1040: } ! 1041: crb = crbD(ctx->opcode) >> 2; ! 1042: gen_op_load_fpscr_T0(crb); ! 1043: gen_op_ori(1 << (crbD(ctx->opcode) & 0x03)); ! 1044: gen_op_store_T0_fpscr(crb); ! 1045: if (Rc(ctx->opcode)) ! 1046: gen_op_set_Rc1(); ! 1047: } ! 1048: ! 1049: /* mtfsf */ ! 1050: GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) ! 1051: { ! 1052: if (!ctx->fpu_enabled) { ! 1053: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 1054: return; ! 1055: } ! 1056: gen_op_load_fpr_FT0(rB(ctx->opcode)); ! 1057: gen_op_store_fpscr(FM(ctx->opcode)); ! 1058: if (Rc(ctx->opcode)) ! 1059: gen_op_set_Rc1(); ! 1060: } ! 1061: ! 1062: /* mtfsfi */ ! 1063: GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) ! 1064: { ! 1065: if (!ctx->fpu_enabled) { ! 1066: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 1067: return; ! 1068: } ! 1069: gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode)); ! 1070: if (Rc(ctx->opcode)) ! 1071: gen_op_set_Rc1(); ! 1072: } ! 1073: ! 1074: /*** Integer load ***/ ! 1075: #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])() ! 1076: #if defined(CONFIG_USER_ONLY) ! 1077: #define OP_LD_TABLE(width) \ ! 1078: static GenOpFunc *gen_op_l##width[] = { \ ! 1079: &gen_op_l##width##_raw, \ ! 1080: &gen_op_l##width##_le_raw, \ ! 1081: }; ! 1082: #define OP_ST_TABLE(width) \ ! 1083: static GenOpFunc *gen_op_st##width[] = { \ ! 1084: &gen_op_st##width##_raw, \ ! 1085: &gen_op_st##width##_le_raw, \ ! 1086: }; ! 1087: /* Byte access routine are endian safe */ ! 1088: #define gen_op_stb_le_raw gen_op_stb_raw ! 1089: #define gen_op_lbz_le_raw gen_op_lbz_raw ! 1090: #else ! 1091: #define OP_LD_TABLE(width) \ ! 1092: static GenOpFunc *gen_op_l##width[] = { \ ! 1093: &gen_op_l##width##_user, \ ! 1094: &gen_op_l##width##_le_user, \ ! 1095: &gen_op_l##width##_kernel, \ ! 1096: &gen_op_l##width##_le_kernel, \ ! 1097: }; ! 1098: #define OP_ST_TABLE(width) \ ! 1099: static GenOpFunc *gen_op_st##width[] = { \ ! 1100: &gen_op_st##width##_user, \ ! 1101: &gen_op_st##width##_le_user, \ ! 1102: &gen_op_st##width##_kernel, \ ! 1103: &gen_op_st##width##_le_kernel, \ ! 1104: }; ! 1105: /* Byte access routine are endian safe */ ! 1106: #define gen_op_stb_le_user gen_op_stb_user ! 1107: #define gen_op_lbz_le_user gen_op_lbz_user ! 1108: #define gen_op_stb_le_kernel gen_op_stb_kernel ! 1109: #define gen_op_lbz_le_kernel gen_op_lbz_kernel ! 1110: #endif ! 1111: ! 1112: #define GEN_LD(width, opc) \ ! 1113: GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ ! 1114: { \ ! 1115: uint32_t simm = SIMM(ctx->opcode); \ ! 1116: if (rA(ctx->opcode) == 0) { \ ! 1117: gen_op_set_T0(simm); \ ! 1118: } else { \ ! 1119: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1120: if (simm != 0) \ ! 1121: gen_op_addi(simm); \ ! 1122: } \ ! 1123: op_ldst(l##width); \ ! 1124: gen_op_store_T1_gpr(rD(ctx->opcode)); \ ! 1125: } ! 1126: ! 1127: #define GEN_LDU(width, opc) \ ! 1128: GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ ! 1129: { \ ! 1130: uint32_t simm = SIMM(ctx->opcode); \ ! 1131: if (rA(ctx->opcode) == 0 || \ ! 1132: rA(ctx->opcode) == rD(ctx->opcode)) { \ ! 1133: RET_INVAL(ctx); \ ! 1134: return; \ ! 1135: } \ ! 1136: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1137: if (simm != 0) \ ! 1138: gen_op_addi(simm); \ ! 1139: op_ldst(l##width); \ ! 1140: gen_op_store_T1_gpr(rD(ctx->opcode)); \ ! 1141: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1142: } ! 1143: ! 1144: #define GEN_LDUX(width, opc) \ ! 1145: GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ ! 1146: { \ ! 1147: if (rA(ctx->opcode) == 0 || \ ! 1148: rA(ctx->opcode) == rD(ctx->opcode)) { \ ! 1149: RET_INVAL(ctx); \ ! 1150: return; \ ! 1151: } \ ! 1152: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1153: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1154: gen_op_add(); \ ! 1155: op_ldst(l##width); \ ! 1156: gen_op_store_T1_gpr(rD(ctx->opcode)); \ ! 1157: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1158: } ! 1159: ! 1160: #define GEN_LDX(width, opc2, opc3) \ ! 1161: GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ ! 1162: { \ ! 1163: if (rA(ctx->opcode) == 0) { \ ! 1164: gen_op_load_gpr_T0(rB(ctx->opcode)); \ ! 1165: } else { \ ! 1166: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1167: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1168: gen_op_add(); \ ! 1169: } \ ! 1170: op_ldst(l##width); \ ! 1171: gen_op_store_T1_gpr(rD(ctx->opcode)); \ ! 1172: } ! 1173: ! 1174: #define GEN_LDS(width, op) \ ! 1175: OP_LD_TABLE(width); \ ! 1176: GEN_LD(width, op | 0x20); \ ! 1177: GEN_LDU(width, op | 0x21); \ ! 1178: GEN_LDUX(width, op | 0x01); \ ! 1179: GEN_LDX(width, 0x17, op | 0x00) ! 1180: ! 1181: /* lbz lbzu lbzux lbzx */ ! 1182: GEN_LDS(bz, 0x02); ! 1183: /* lha lhau lhaux lhax */ ! 1184: GEN_LDS(ha, 0x0A); ! 1185: /* lhz lhzu lhzux lhzx */ ! 1186: GEN_LDS(hz, 0x08); ! 1187: /* lwz lwzu lwzux lwzx */ ! 1188: GEN_LDS(wz, 0x00); ! 1189: ! 1190: /*** Integer store ***/ ! 1191: #define GEN_ST(width, opc) \ ! 1192: GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ ! 1193: { \ ! 1194: uint32_t simm = SIMM(ctx->opcode); \ ! 1195: if (rA(ctx->opcode) == 0) { \ ! 1196: gen_op_set_T0(simm); \ ! 1197: } else { \ ! 1198: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1199: if (simm != 0) \ ! 1200: gen_op_addi(simm); \ ! 1201: } \ ! 1202: gen_op_load_gpr_T1(rS(ctx->opcode)); \ ! 1203: op_ldst(st##width); \ ! 1204: } ! 1205: ! 1206: #define GEN_STU(width, opc) \ ! 1207: GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ ! 1208: { \ ! 1209: uint32_t simm = SIMM(ctx->opcode); \ ! 1210: if (rA(ctx->opcode) == 0) { \ ! 1211: RET_INVAL(ctx); \ ! 1212: return; \ ! 1213: } \ ! 1214: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1215: if (simm != 0) \ ! 1216: gen_op_addi(simm); \ ! 1217: gen_op_load_gpr_T1(rS(ctx->opcode)); \ ! 1218: op_ldst(st##width); \ ! 1219: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1220: } ! 1221: ! 1222: #define GEN_STUX(width, opc) \ ! 1223: GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ ! 1224: { \ ! 1225: if (rA(ctx->opcode) == 0) { \ ! 1226: RET_INVAL(ctx); \ ! 1227: return; \ ! 1228: } \ ! 1229: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1230: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1231: gen_op_add(); \ ! 1232: gen_op_load_gpr_T1(rS(ctx->opcode)); \ ! 1233: op_ldst(st##width); \ ! 1234: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1235: } ! 1236: ! 1237: #define GEN_STX(width, opc2, opc3) \ ! 1238: GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ ! 1239: { \ ! 1240: if (rA(ctx->opcode) == 0) { \ ! 1241: gen_op_load_gpr_T0(rB(ctx->opcode)); \ ! 1242: } else { \ ! 1243: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1244: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1245: gen_op_add(); \ ! 1246: } \ ! 1247: gen_op_load_gpr_T1(rS(ctx->opcode)); \ ! 1248: op_ldst(st##width); \ ! 1249: } ! 1250: ! 1251: #define GEN_STS(width, op) \ ! 1252: OP_ST_TABLE(width); \ ! 1253: GEN_ST(width, op | 0x20); \ ! 1254: GEN_STU(width, op | 0x21); \ ! 1255: GEN_STUX(width, op | 0x01); \ ! 1256: GEN_STX(width, 0x17, op | 0x00) ! 1257: ! 1258: /* stb stbu stbux stbx */ ! 1259: GEN_STS(b, 0x06); ! 1260: /* sth sthu sthux sthx */ ! 1261: GEN_STS(h, 0x0C); ! 1262: /* stw stwu stwux stwx */ ! 1263: GEN_STS(w, 0x04); ! 1264: ! 1265: /*** Integer load and store with byte reverse ***/ ! 1266: /* lhbrx */ ! 1267: OP_LD_TABLE(hbr); ! 1268: GEN_LDX(hbr, 0x16, 0x18); ! 1269: /* lwbrx */ ! 1270: OP_LD_TABLE(wbr); ! 1271: GEN_LDX(wbr, 0x16, 0x10); ! 1272: /* sthbrx */ ! 1273: OP_ST_TABLE(hbr); ! 1274: GEN_STX(hbr, 0x16, 0x1C); ! 1275: /* stwbrx */ ! 1276: OP_ST_TABLE(wbr); ! 1277: GEN_STX(wbr, 0x16, 0x14); ! 1278: ! 1279: /*** Integer load and store multiple ***/ ! 1280: #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg) ! 1281: #if defined(CONFIG_USER_ONLY) ! 1282: static GenOpFunc1 *gen_op_lmw[] = { ! 1283: &gen_op_lmw_raw, ! 1284: &gen_op_lmw_le_raw, ! 1285: }; ! 1286: static GenOpFunc1 *gen_op_stmw[] = { ! 1287: &gen_op_stmw_raw, ! 1288: &gen_op_stmw_le_raw, ! 1289: }; ! 1290: #else ! 1291: static GenOpFunc1 *gen_op_lmw[] = { ! 1292: &gen_op_lmw_user, ! 1293: &gen_op_lmw_le_user, ! 1294: &gen_op_lmw_kernel, ! 1295: &gen_op_lmw_le_kernel, ! 1296: }; ! 1297: static GenOpFunc1 *gen_op_stmw[] = { ! 1298: &gen_op_stmw_user, ! 1299: &gen_op_stmw_le_user, ! 1300: &gen_op_stmw_kernel, ! 1301: &gen_op_stmw_le_kernel, ! 1302: }; ! 1303: #endif ! 1304: ! 1305: /* lmw */ ! 1306: GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 1307: { ! 1308: int simm = SIMM(ctx->opcode); ! 1309: ! 1310: if (rA(ctx->opcode) == 0) { ! 1311: gen_op_set_T0(simm); ! 1312: } else { ! 1313: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 1314: if (simm != 0) ! 1315: gen_op_addi(simm); ! 1316: } ! 1317: op_ldstm(lmw, rD(ctx->opcode)); ! 1318: } ! 1319: ! 1320: /* stmw */ ! 1321: GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) ! 1322: { ! 1323: int simm = SIMM(ctx->opcode); ! 1324: ! 1325: if (rA(ctx->opcode) == 0) { ! 1326: gen_op_set_T0(simm); ! 1327: } else { ! 1328: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 1329: if (simm != 0) ! 1330: gen_op_addi(simm); ! 1331: } ! 1332: op_ldstm(stmw, rS(ctx->opcode)); ! 1333: } ! 1334: ! 1335: /*** Integer load and store strings ***/ ! 1336: #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start) ! 1337: #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb) ! 1338: #if defined(CONFIG_USER_ONLY) ! 1339: static GenOpFunc1 *gen_op_lswi[] = { ! 1340: &gen_op_lswi_raw, ! 1341: &gen_op_lswi_le_raw, ! 1342: }; ! 1343: static GenOpFunc3 *gen_op_lswx[] = { ! 1344: &gen_op_lswx_raw, ! 1345: &gen_op_lswx_le_raw, ! 1346: }; ! 1347: static GenOpFunc1 *gen_op_stsw[] = { ! 1348: &gen_op_stsw_raw, ! 1349: &gen_op_stsw_le_raw, ! 1350: }; ! 1351: #else ! 1352: static GenOpFunc1 *gen_op_lswi[] = { ! 1353: &gen_op_lswi_user, ! 1354: &gen_op_lswi_le_user, ! 1355: &gen_op_lswi_kernel, ! 1356: &gen_op_lswi_le_kernel, ! 1357: }; ! 1358: static GenOpFunc3 *gen_op_lswx[] = { ! 1359: &gen_op_lswx_user, ! 1360: &gen_op_lswx_le_user, ! 1361: &gen_op_lswx_kernel, ! 1362: &gen_op_lswx_le_kernel, ! 1363: }; ! 1364: static GenOpFunc1 *gen_op_stsw[] = { ! 1365: &gen_op_stsw_user, ! 1366: &gen_op_stsw_le_user, ! 1367: &gen_op_stsw_kernel, ! 1368: &gen_op_stsw_le_kernel, ! 1369: }; ! 1370: #endif ! 1371: ! 1372: /* lswi */ ! 1373: /* PowerPC32 specification says we must generate an exception if ! 1374: * rA is in the range of registers to be loaded. ! 1375: * In an other hand, IBM says this is valid, but rA won't be loaded. ! 1376: * For now, I'll follow the spec... ! 1377: */ ! 1378: GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER) ! 1379: { ! 1380: int nb = NB(ctx->opcode); ! 1381: int start = rD(ctx->opcode); ! 1382: int ra = rA(ctx->opcode); ! 1383: int nr; ! 1384: ! 1385: if (nb == 0) ! 1386: nb = 32; ! 1387: nr = nb / 4; ! 1388: if (((start + nr) > 32 && start <= ra && (start + nr - 32) > ra) || ! 1389: ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) { ! 1390: RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX); ! 1391: return; ! 1392: } ! 1393: if (ra == 0) { ! 1394: gen_op_set_T0(0); ! 1395: } else { ! 1396: gen_op_load_gpr_T0(ra); ! 1397: } ! 1398: gen_op_set_T1(nb); ! 1399: /* NIP cannot be restored if the memory exception comes from an helper */ ! 1400: gen_op_update_nip((ctx)->nip - 4); ! 1401: op_ldsts(lswi, start); ! 1402: } ! 1403: ! 1404: /* lswx */ ! 1405: GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER) ! 1406: { ! 1407: int ra = rA(ctx->opcode); ! 1408: int rb = rB(ctx->opcode); ! 1409: ! 1410: if (ra == 0) { ! 1411: gen_op_load_gpr_T0(rb); ! 1412: ra = rb; ! 1413: } else { ! 1414: gen_op_load_gpr_T0(ra); ! 1415: gen_op_load_gpr_T1(rb); ! 1416: gen_op_add(); ! 1417: } ! 1418: gen_op_load_xer_bc(); ! 1419: /* NIP cannot be restored if the memory exception comes from an helper */ ! 1420: gen_op_update_nip((ctx)->nip - 4); ! 1421: op_ldstsx(lswx, rD(ctx->opcode), ra, rb); ! 1422: } ! 1423: ! 1424: /* stswi */ ! 1425: GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER) ! 1426: { ! 1427: int nb = NB(ctx->opcode); ! 1428: ! 1429: if (rA(ctx->opcode) == 0) { ! 1430: gen_op_set_T0(0); ! 1431: } else { ! 1432: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 1433: } ! 1434: if (nb == 0) ! 1435: nb = 32; ! 1436: gen_op_set_T1(nb); ! 1437: /* NIP cannot be restored if the memory exception comes from an helper */ ! 1438: gen_op_update_nip((ctx)->nip - 4); ! 1439: op_ldsts(stsw, rS(ctx->opcode)); ! 1440: } ! 1441: ! 1442: /* stswx */ ! 1443: GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER) ! 1444: { ! 1445: int ra = rA(ctx->opcode); ! 1446: ! 1447: if (ra == 0) { ! 1448: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 1449: ra = rB(ctx->opcode); ! 1450: } else { ! 1451: gen_op_load_gpr_T0(ra); ! 1452: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 1453: gen_op_add(); ! 1454: } ! 1455: gen_op_load_xer_bc(); ! 1456: /* NIP cannot be restored if the memory exception comes from an helper */ ! 1457: gen_op_update_nip((ctx)->nip - 4); ! 1458: op_ldsts(stsw, rS(ctx->opcode)); ! 1459: } ! 1460: ! 1461: /*** Memory synchronisation ***/ ! 1462: /* eieio */ ! 1463: GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM) ! 1464: { ! 1465: } ! 1466: ! 1467: /* isync */ ! 1468: GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM) ! 1469: { ! 1470: } ! 1471: ! 1472: #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])() ! 1473: #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])() ! 1474: #if defined(CONFIG_USER_ONLY) ! 1475: static GenOpFunc *gen_op_lwarx[] = { ! 1476: &gen_op_lwarx_raw, ! 1477: &gen_op_lwarx_le_raw, ! 1478: }; ! 1479: static GenOpFunc *gen_op_stwcx[] = { ! 1480: &gen_op_stwcx_raw, ! 1481: &gen_op_stwcx_le_raw, ! 1482: }; ! 1483: #else ! 1484: static GenOpFunc *gen_op_lwarx[] = { ! 1485: &gen_op_lwarx_user, ! 1486: &gen_op_lwarx_le_user, ! 1487: &gen_op_lwarx_kernel, ! 1488: &gen_op_lwarx_le_kernel, ! 1489: }; ! 1490: static GenOpFunc *gen_op_stwcx[] = { ! 1491: &gen_op_stwcx_user, ! 1492: &gen_op_stwcx_le_user, ! 1493: &gen_op_stwcx_kernel, ! 1494: &gen_op_stwcx_le_kernel, ! 1495: }; ! 1496: #endif ! 1497: ! 1498: /* lwarx */ ! 1499: GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES) ! 1500: { ! 1501: if (rA(ctx->opcode) == 0) { ! 1502: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 1503: } else { ! 1504: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 1505: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 1506: gen_op_add(); ! 1507: } ! 1508: op_lwarx(); ! 1509: gen_op_store_T1_gpr(rD(ctx->opcode)); ! 1510: } ! 1511: ! 1512: /* stwcx. */ ! 1513: GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES) ! 1514: { ! 1515: if (rA(ctx->opcode) == 0) { ! 1516: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 1517: } else { ! 1518: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 1519: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 1520: gen_op_add(); ! 1521: } ! 1522: gen_op_load_gpr_T1(rS(ctx->opcode)); ! 1523: op_stwcx(); ! 1524: } ! 1525: ! 1526: /* sync */ ! 1527: GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM) ! 1528: { ! 1529: } ! 1530: ! 1531: /*** Floating-point load ***/ ! 1532: #define GEN_LDF(width, opc) \ ! 1533: GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ ! 1534: { \ ! 1535: uint32_t simm = SIMM(ctx->opcode); \ ! 1536: if (!ctx->fpu_enabled) { \ ! 1537: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1538: return; \ ! 1539: } \ ! 1540: if (rA(ctx->opcode) == 0) { \ ! 1541: gen_op_set_T0(simm); \ ! 1542: } else { \ ! 1543: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1544: if (simm != 0) \ ! 1545: gen_op_addi(simm); \ ! 1546: } \ ! 1547: op_ldst(l##width); \ ! 1548: gen_op_store_FT1_fpr(rD(ctx->opcode)); \ ! 1549: } ! 1550: ! 1551: #define GEN_LDUF(width, opc) \ ! 1552: GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ ! 1553: { \ ! 1554: uint32_t simm = SIMM(ctx->opcode); \ ! 1555: if (!ctx->fpu_enabled) { \ ! 1556: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1557: return; \ ! 1558: } \ ! 1559: if (rA(ctx->opcode) == 0 || \ ! 1560: rA(ctx->opcode) == rD(ctx->opcode)) { \ ! 1561: RET_INVAL(ctx); \ ! 1562: return; \ ! 1563: } \ ! 1564: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1565: if (simm != 0) \ ! 1566: gen_op_addi(simm); \ ! 1567: op_ldst(l##width); \ ! 1568: gen_op_store_FT1_fpr(rD(ctx->opcode)); \ ! 1569: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1570: } ! 1571: ! 1572: #define GEN_LDUXF(width, opc) \ ! 1573: GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ ! 1574: { \ ! 1575: if (!ctx->fpu_enabled) { \ ! 1576: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1577: return; \ ! 1578: } \ ! 1579: if (rA(ctx->opcode) == 0 || \ ! 1580: rA(ctx->opcode) == rD(ctx->opcode)) { \ ! 1581: RET_INVAL(ctx); \ ! 1582: return; \ ! 1583: } \ ! 1584: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1585: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1586: gen_op_add(); \ ! 1587: op_ldst(l##width); \ ! 1588: gen_op_store_FT1_fpr(rD(ctx->opcode)); \ ! 1589: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1590: } ! 1591: ! 1592: #define GEN_LDXF(width, opc2, opc3) \ ! 1593: GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT) \ ! 1594: { \ ! 1595: if (!ctx->fpu_enabled) { \ ! 1596: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1597: return; \ ! 1598: } \ ! 1599: if (rA(ctx->opcode) == 0) { \ ! 1600: gen_op_load_gpr_T0(rB(ctx->opcode)); \ ! 1601: } else { \ ! 1602: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1603: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1604: gen_op_add(); \ ! 1605: } \ ! 1606: op_ldst(l##width); \ ! 1607: gen_op_store_FT1_fpr(rD(ctx->opcode)); \ ! 1608: } ! 1609: ! 1610: #define GEN_LDFS(width, op) \ ! 1611: OP_LD_TABLE(width); \ ! 1612: GEN_LDF(width, op | 0x20); \ ! 1613: GEN_LDUF(width, op | 0x21); \ ! 1614: GEN_LDUXF(width, op | 0x01); \ ! 1615: GEN_LDXF(width, 0x17, op | 0x00) ! 1616: ! 1617: /* lfd lfdu lfdux lfdx */ ! 1618: GEN_LDFS(fd, 0x12); ! 1619: /* lfs lfsu lfsux lfsx */ ! 1620: GEN_LDFS(fs, 0x10); ! 1621: ! 1622: /*** Floating-point store ***/ ! 1623: #define GEN_STF(width, opc) \ ! 1624: GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ ! 1625: { \ ! 1626: uint32_t simm = SIMM(ctx->opcode); \ ! 1627: if (!ctx->fpu_enabled) { \ ! 1628: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1629: return; \ ! 1630: } \ ! 1631: if (rA(ctx->opcode) == 0) { \ ! 1632: gen_op_set_T0(simm); \ ! 1633: } else { \ ! 1634: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1635: if (simm != 0) \ ! 1636: gen_op_addi(simm); \ ! 1637: } \ ! 1638: gen_op_load_fpr_FT1(rS(ctx->opcode)); \ ! 1639: op_ldst(st##width); \ ! 1640: } ! 1641: ! 1642: #define GEN_STUF(width, opc) \ ! 1643: GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ ! 1644: { \ ! 1645: uint32_t simm = SIMM(ctx->opcode); \ ! 1646: if (!ctx->fpu_enabled) { \ ! 1647: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1648: return; \ ! 1649: } \ ! 1650: if (rA(ctx->opcode) == 0) { \ ! 1651: RET_INVAL(ctx); \ ! 1652: return; \ ! 1653: } \ ! 1654: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1655: if (simm != 0) \ ! 1656: gen_op_addi(simm); \ ! 1657: gen_op_load_fpr_FT1(rS(ctx->opcode)); \ ! 1658: op_ldst(st##width); \ ! 1659: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1660: } ! 1661: ! 1662: #define GEN_STUXF(width, opc) \ ! 1663: GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ ! 1664: { \ ! 1665: if (!ctx->fpu_enabled) { \ ! 1666: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1667: return; \ ! 1668: } \ ! 1669: if (rA(ctx->opcode) == 0) { \ ! 1670: RET_INVAL(ctx); \ ! 1671: return; \ ! 1672: } \ ! 1673: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1674: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1675: gen_op_add(); \ ! 1676: gen_op_load_fpr_FT1(rS(ctx->opcode)); \ ! 1677: op_ldst(st##width); \ ! 1678: gen_op_store_T0_gpr(rA(ctx->opcode)); \ ! 1679: } ! 1680: ! 1681: #define GEN_STXF(width, opc2, opc3) \ ! 1682: GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT) \ ! 1683: { \ ! 1684: if (!ctx->fpu_enabled) { \ ! 1685: RET_EXCP(ctx, EXCP_NO_FP, 0); \ ! 1686: return; \ ! 1687: } \ ! 1688: if (rA(ctx->opcode) == 0) { \ ! 1689: gen_op_load_gpr_T0(rB(ctx->opcode)); \ ! 1690: } else { \ ! 1691: gen_op_load_gpr_T0(rA(ctx->opcode)); \ ! 1692: gen_op_load_gpr_T1(rB(ctx->opcode)); \ ! 1693: gen_op_add(); \ ! 1694: } \ ! 1695: gen_op_load_fpr_FT1(rS(ctx->opcode)); \ ! 1696: op_ldst(st##width); \ ! 1697: } ! 1698: ! 1699: #define GEN_STFS(width, op) \ ! 1700: OP_ST_TABLE(width); \ ! 1701: GEN_STF(width, op | 0x20); \ ! 1702: GEN_STUF(width, op | 0x21); \ ! 1703: GEN_STUXF(width, op | 0x01); \ ! 1704: GEN_STXF(width, 0x17, op | 0x00) ! 1705: ! 1706: /* stfd stfdu stfdux stfdx */ ! 1707: GEN_STFS(fd, 0x16); ! 1708: /* stfs stfsu stfsux stfsx */ ! 1709: GEN_STFS(fs, 0x14); ! 1710: ! 1711: /* Optional: */ ! 1712: /* stfiwx */ ! 1713: GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) ! 1714: { ! 1715: if (!ctx->fpu_enabled) { ! 1716: RET_EXCP(ctx, EXCP_NO_FP, 0); ! 1717: return; ! 1718: } ! 1719: RET_INVAL(ctx); ! 1720: } ! 1721: ! 1722: /*** Branch ***/ ! 1723: ! 1724: /* b ba bl bla */ ! 1725: GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) ! 1726: { ! 1727: uint32_t li, target; ! 1728: ! 1729: /* sign extend LI */ ! 1730: li = ((int32_t)LI(ctx->opcode) << 6) >> 6; ! 1731: ! 1732: if (AA(ctx->opcode) == 0) ! 1733: target = ctx->nip + li - 4; ! 1734: else ! 1735: target = li; ! 1736: if (LK(ctx->opcode)) { ! 1737: gen_op_setlr(ctx->nip); ! 1738: } ! 1739: gen_op_b((long)ctx->tb, target); ! 1740: ctx->exception = EXCP_BRANCH; ! 1741: } ! 1742: ! 1743: #define BCOND_IM 0 ! 1744: #define BCOND_LR 1 ! 1745: #define BCOND_CTR 2 ! 1746: ! 1747: static inline void gen_bcond(DisasContext *ctx, int type) ! 1748: { ! 1749: uint32_t target = 0; ! 1750: uint32_t bo = BO(ctx->opcode); ! 1751: uint32_t bi = BI(ctx->opcode); ! 1752: uint32_t mask; ! 1753: uint32_t li; ! 1754: ! 1755: if ((bo & 0x4) == 0) ! 1756: gen_op_dec_ctr(); ! 1757: switch(type) { ! 1758: case BCOND_IM: ! 1759: li = (int32_t)((int16_t)(BD(ctx->opcode))); ! 1760: if (AA(ctx->opcode) == 0) { ! 1761: target = ctx->nip + li - 4; ! 1762: } else { ! 1763: target = li; ! 1764: } ! 1765: break; ! 1766: case BCOND_CTR: ! 1767: gen_op_movl_T1_ctr(); ! 1768: break; ! 1769: default: ! 1770: case BCOND_LR: ! 1771: gen_op_movl_T1_lr(); ! 1772: break; ! 1773: } ! 1774: if (LK(ctx->opcode)) { ! 1775: gen_op_setlr(ctx->nip); ! 1776: } ! 1777: if (bo & 0x10) { ! 1778: /* No CR condition */ ! 1779: switch (bo & 0x6) { ! 1780: case 0: ! 1781: gen_op_test_ctr(); ! 1782: break; ! 1783: case 2: ! 1784: gen_op_test_ctrz(); ! 1785: break; ! 1786: default: ! 1787: case 4: ! 1788: case 6: ! 1789: if (type == BCOND_IM) { ! 1790: gen_op_b((long)ctx->tb, target); ! 1791: } else { ! 1792: gen_op_b_T1(); ! 1793: } ! 1794: goto no_test; ! 1795: } ! 1796: } else { ! 1797: mask = 1 << (3 - (bi & 0x03)); ! 1798: gen_op_load_crf_T0(bi >> 2); ! 1799: if (bo & 0x8) { ! 1800: switch (bo & 0x6) { ! 1801: case 0: ! 1802: gen_op_test_ctr_true(mask); ! 1803: break; ! 1804: case 2: ! 1805: gen_op_test_ctrz_true(mask); ! 1806: break; ! 1807: default: ! 1808: case 4: ! 1809: case 6: ! 1810: gen_op_test_true(mask); ! 1811: break; ! 1812: } ! 1813: } else { ! 1814: switch (bo & 0x6) { ! 1815: case 0: ! 1816: gen_op_test_ctr_false(mask); ! 1817: break; ! 1818: case 2: ! 1819: gen_op_test_ctrz_false(mask); ! 1820: break; ! 1821: default: ! 1822: case 4: ! 1823: case 6: ! 1824: gen_op_test_false(mask); ! 1825: break; ! 1826: } ! 1827: } ! 1828: } ! 1829: if (type == BCOND_IM) { ! 1830: gen_op_btest((long)ctx->tb, target, ctx->nip); ! 1831: } else { ! 1832: gen_op_btest_T1(ctx->nip); ! 1833: } ! 1834: no_test: ! 1835: ctx->exception = EXCP_BRANCH; ! 1836: } ! 1837: ! 1838: GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW) ! 1839: { ! 1840: gen_bcond(ctx, BCOND_IM); ! 1841: } ! 1842: ! 1843: GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW) ! 1844: { ! 1845: gen_bcond(ctx, BCOND_CTR); ! 1846: } ! 1847: ! 1848: GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW) ! 1849: { ! 1850: gen_bcond(ctx, BCOND_LR); ! 1851: } ! 1852: ! 1853: /*** Condition register logical ***/ ! 1854: #define GEN_CRLOGIC(op, opc) \ ! 1855: GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \ ! 1856: { \ ! 1857: gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \ ! 1858: gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03)); \ ! 1859: gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \ ! 1860: gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03)); \ ! 1861: gen_op_##op(); \ ! 1862: gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \ ! 1863: gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \ ! 1864: 3 - (crbD(ctx->opcode) & 0x03)); \ ! 1865: gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \ ! 1866: } ! 1867: ! 1868: /* crand */ ! 1869: GEN_CRLOGIC(and, 0x08) ! 1870: /* crandc */ ! 1871: GEN_CRLOGIC(andc, 0x04) ! 1872: /* creqv */ ! 1873: GEN_CRLOGIC(eqv, 0x09) ! 1874: /* crnand */ ! 1875: GEN_CRLOGIC(nand, 0x07) ! 1876: /* crnor */ ! 1877: GEN_CRLOGIC(nor, 0x01) ! 1878: /* cror */ ! 1879: GEN_CRLOGIC(or, 0x0E) ! 1880: /* crorc */ ! 1881: GEN_CRLOGIC(orc, 0x0D) ! 1882: /* crxor */ ! 1883: GEN_CRLOGIC(xor, 0x06) ! 1884: /* mcrf */ ! 1885: GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER) ! 1886: { ! 1887: gen_op_load_crf_T0(crfS(ctx->opcode)); ! 1888: gen_op_store_T0_crf(crfD(ctx->opcode)); ! 1889: } ! 1890: ! 1891: /*** System linkage ***/ ! 1892: /* rfi (supervisor only) */ ! 1893: GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW) ! 1894: { ! 1895: #if defined(CONFIG_USER_ONLY) ! 1896: RET_PRIVOPC(ctx); ! 1897: #else ! 1898: /* Restore CPU state */ ! 1899: if (!ctx->supervisor) { ! 1900: RET_PRIVOPC(ctx); ! 1901: return; ! 1902: } ! 1903: gen_op_rfi(); ! 1904: RET_CHG_FLOW(ctx); ! 1905: #endif ! 1906: } ! 1907: ! 1908: /* sc */ ! 1909: GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW) ! 1910: { ! 1911: #if defined(CONFIG_USER_ONLY) ! 1912: RET_EXCP(ctx, EXCP_SYSCALL_USER, 0); ! 1913: #else ! 1914: RET_EXCP(ctx, EXCP_SYSCALL, 0); ! 1915: #endif ! 1916: } ! 1917: ! 1918: /*** Trap ***/ ! 1919: /* tw */ ! 1920: GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW) ! 1921: { ! 1922: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 1923: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 1924: gen_op_tw(TO(ctx->opcode)); ! 1925: } ! 1926: ! 1927: /* twi */ ! 1928: GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW) ! 1929: { ! 1930: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 1931: #if 0 ! 1932: printf("%s: param=0x%04x T0=0x%04x\n", __func__, ! 1933: SIMM(ctx->opcode), TO(ctx->opcode)); ! 1934: #endif ! 1935: gen_op_twi(SIMM(ctx->opcode), TO(ctx->opcode)); ! 1936: } ! 1937: ! 1938: /*** Processor control ***/ ! 1939: static inline int check_spr_access (int spr, int rw, int supervisor) ! 1940: { ! 1941: uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1)); ! 1942: ! 1943: #if 0 ! 1944: if (spr != LR && spr != CTR) { ! 1945: if (loglevel > 0) { ! 1946: fprintf(logfile, "%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__, ! 1947: SPR_ENCODE(spr), supervisor, rw, rights, ! 1948: (rights >> ((2 * supervisor) + rw)) & 1); ! 1949: } else { ! 1950: printf("%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__, ! 1951: SPR_ENCODE(spr), supervisor, rw, rights, ! 1952: (rights >> ((2 * supervisor) + rw)) & 1); ! 1953: } ! 1954: } ! 1955: #endif ! 1956: if (rights == 0) ! 1957: return -1; ! 1958: rights = rights >> (2 * supervisor); ! 1959: rights = rights >> rw; ! 1960: ! 1961: return rights & 1; ! 1962: } ! 1963: ! 1964: /* mcrxr */ ! 1965: GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC) ! 1966: { ! 1967: gen_op_load_xer_cr(); ! 1968: gen_op_store_T0_crf(crfD(ctx->opcode)); ! 1969: gen_op_clear_xer_cr(); ! 1970: } ! 1971: ! 1972: /* mfcr */ ! 1973: GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC) ! 1974: { ! 1975: gen_op_load_cr(); ! 1976: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 1977: } ! 1978: ! 1979: /* mfmsr */ ! 1980: GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC) ! 1981: { ! 1982: #if defined(CONFIG_USER_ONLY) ! 1983: RET_PRIVREG(ctx); ! 1984: #else ! 1985: if (!ctx->supervisor) { ! 1986: RET_PRIVREG(ctx); ! 1987: return; ! 1988: } ! 1989: gen_op_load_msr(); ! 1990: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 1991: #endif ! 1992: } ! 1993: ! 1994: #if 0 ! 1995: #define SPR_NOACCESS ((void *)(-1)) ! 1996: #else ! 1997: static void spr_noaccess (void *opaque, int sprn) ! 1998: { ! 1999: sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5); ! 2000: printf("ERROR: try to access SPR %d !\n", sprn); ! 2001: } ! 2002: #define SPR_NOACCESS (&spr_noaccess) ! 2003: #endif ! 2004: ! 2005: /* mfspr */ ! 2006: static inline void gen_op_mfspr (DisasContext *ctx) ! 2007: { ! 2008: void (*read_cb)(void *opaque, int sprn); ! 2009: uint32_t sprn = SPR(ctx->opcode); ! 2010: ! 2011: #if !defined(CONFIG_USER_ONLY) ! 2012: if (ctx->supervisor) ! 2013: read_cb = ctx->spr_cb[sprn].oea_read; ! 2014: else ! 2015: #endif ! 2016: read_cb = ctx->spr_cb[sprn].uea_read; ! 2017: if (read_cb != NULL) { ! 2018: if (read_cb != SPR_NOACCESS) { ! 2019: (*read_cb)(ctx, sprn); ! 2020: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 2021: } else { ! 2022: /* Privilege exception */ ! 2023: printf("Trying to read priviledged spr %d %03x\n", sprn, sprn); ! 2024: RET_PRIVREG(ctx); ! 2025: } ! 2026: } else { ! 2027: /* Not defined */ ! 2028: printf("Trying to read invalid spr %d %03x\n", sprn, sprn); ! 2029: RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR); ! 2030: } ! 2031: } ! 2032: ! 2033: GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC) ! 2034: { ! 2035: gen_op_mfspr(ctx); ! 2036: } ! 2037: ! 2038: /* mftb */ ! 2039: GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_TB) ! 2040: { ! 2041: gen_op_mfspr(ctx); ! 2042: } ! 2043: ! 2044: /* mtcrf */ ! 2045: /* The mask should be 0x00100801, but Mac OS X 10.4 use an alternate form */ ! 2046: GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC) ! 2047: { ! 2048: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 2049: gen_op_store_cr(CRM(ctx->opcode)); ! 2050: } ! 2051: ! 2052: /* mtmsr */ ! 2053: GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) ! 2054: { ! 2055: #if defined(CONFIG_USER_ONLY) ! 2056: RET_PRIVREG(ctx); ! 2057: #else ! 2058: if (!ctx->supervisor) { ! 2059: RET_PRIVREG(ctx); ! 2060: return; ! 2061: } ! 2062: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 2063: gen_op_store_msr(); ! 2064: /* Must stop the translation as machine state (may have) changed */ ! 2065: RET_MTMSR(ctx); ! 2066: #endif ! 2067: } ! 2068: ! 2069: /* mtspr */ ! 2070: GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) ! 2071: { ! 2072: void (*write_cb)(void *opaque, int sprn); ! 2073: uint32_t sprn = SPR(ctx->opcode); ! 2074: ! 2075: #if !defined(CONFIG_USER_ONLY) ! 2076: if (ctx->supervisor) ! 2077: write_cb = ctx->spr_cb[sprn].oea_write; ! 2078: else ! 2079: #endif ! 2080: write_cb = ctx->spr_cb[sprn].uea_write; ! 2081: if (write_cb != NULL) { ! 2082: if (write_cb != SPR_NOACCESS) { ! 2083: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 2084: (*write_cb)(ctx, sprn); ! 2085: } else { ! 2086: /* Privilege exception */ ! 2087: printf("Trying to write priviledged spr %d %03x\n", sprn, sprn); ! 2088: RET_PRIVREG(ctx); ! 2089: } ! 2090: } else { ! 2091: /* Not defined */ ! 2092: printf("Trying to write invalid spr %d %03x\n", sprn, sprn); ! 2093: RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR); ! 2094: } ! 2095: } ! 2096: ! 2097: /*** Cache management ***/ ! 2098: /* For now, all those will be implemented as nop: ! 2099: * this is valid, regarding the PowerPC specs... ! 2100: * We just have to flush tb while invalidating instruction cache lines... ! 2101: */ ! 2102: /* dcbf */ ! 2103: GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE) ! 2104: { ! 2105: if (rA(ctx->opcode) == 0) { ! 2106: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2107: } else { ! 2108: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 2109: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2110: gen_op_add(); ! 2111: } ! 2112: op_ldst(lbz); ! 2113: } ! 2114: ! 2115: /* dcbi (Supervisor only) */ ! 2116: GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE) ! 2117: { ! 2118: #if defined(CONFIG_USER_ONLY) ! 2119: RET_PRIVOPC(ctx); ! 2120: #else ! 2121: if (!ctx->supervisor) { ! 2122: RET_PRIVOPC(ctx); ! 2123: return; ! 2124: } ! 2125: if (rA(ctx->opcode) == 0) { ! 2126: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2127: } else { ! 2128: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 2129: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2130: gen_op_add(); ! 2131: } ! 2132: op_ldst(lbz); ! 2133: op_ldst(stb); ! 2134: #endif ! 2135: } ! 2136: ! 2137: /* dcdst */ ! 2138: GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE) ! 2139: { ! 2140: if (rA(ctx->opcode) == 0) { ! 2141: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2142: } else { ! 2143: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 2144: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2145: gen_op_add(); ! 2146: } ! 2147: op_ldst(lbz); ! 2148: } ! 2149: ! 2150: /* dcbt */ ! 2151: GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE) ! 2152: { ! 2153: } ! 2154: ! 2155: /* dcbtst */ ! 2156: GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE) ! 2157: { ! 2158: } ! 2159: ! 2160: /* dcbz */ ! 2161: #if defined(CONFIG_USER_ONLY) ! 2162: #define op_dcbz() gen_op_dcbz_raw() ! 2163: #else ! 2164: #define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])() ! 2165: static GenOpFunc *gen_op_dcbz[] = { ! 2166: &gen_op_dcbz_user, ! 2167: &gen_op_dcbz_user, ! 2168: &gen_op_dcbz_kernel, ! 2169: &gen_op_dcbz_kernel, ! 2170: }; ! 2171: #endif ! 2172: ! 2173: GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE) ! 2174: { ! 2175: if (rA(ctx->opcode) == 0) { ! 2176: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2177: } else { ! 2178: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 2179: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2180: gen_op_add(); ! 2181: } ! 2182: op_dcbz(); ! 2183: gen_op_check_reservation(); ! 2184: } ! 2185: ! 2186: /* icbi */ ! 2187: GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE) ! 2188: { ! 2189: if (rA(ctx->opcode) == 0) { ! 2190: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2191: } else { ! 2192: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 2193: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2194: gen_op_add(); ! 2195: } ! 2196: gen_op_icbi(); ! 2197: } ! 2198: ! 2199: /* Optional: */ ! 2200: /* dcba */ ! 2201: GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_OPT) ! 2202: { ! 2203: } ! 2204: ! 2205: /*** Segment register manipulation ***/ ! 2206: /* Supervisor only: */ ! 2207: /* mfsr */ ! 2208: GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) ! 2209: { ! 2210: #if defined(CONFIG_USER_ONLY) ! 2211: RET_PRIVREG(ctx); ! 2212: #else ! 2213: if (!ctx->supervisor) { ! 2214: RET_PRIVREG(ctx); ! 2215: return; ! 2216: } ! 2217: gen_op_load_sr(SR(ctx->opcode)); ! 2218: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 2219: #endif ! 2220: } ! 2221: ! 2222: /* mfsrin */ ! 2223: GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) ! 2224: { ! 2225: #if defined(CONFIG_USER_ONLY) ! 2226: RET_PRIVREG(ctx); ! 2227: #else ! 2228: if (!ctx->supervisor) { ! 2229: RET_PRIVREG(ctx); ! 2230: return; ! 2231: } ! 2232: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2233: gen_op_load_srin(); ! 2234: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 2235: #endif ! 2236: } ! 2237: ! 2238: /* mtsr */ ! 2239: GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) ! 2240: { ! 2241: #if defined(CONFIG_USER_ONLY) ! 2242: RET_PRIVREG(ctx); ! 2243: #else ! 2244: if (!ctx->supervisor) { ! 2245: RET_PRIVREG(ctx); ! 2246: return; ! 2247: } ! 2248: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 2249: gen_op_store_sr(SR(ctx->opcode)); ! 2250: #endif ! 2251: } ! 2252: ! 2253: /* mtsrin */ ! 2254: GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) ! 2255: { ! 2256: #if defined(CONFIG_USER_ONLY) ! 2257: RET_PRIVREG(ctx); ! 2258: #else ! 2259: if (!ctx->supervisor) { ! 2260: RET_PRIVREG(ctx); ! 2261: return; ! 2262: } ! 2263: gen_op_load_gpr_T0(rS(ctx->opcode)); ! 2264: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2265: gen_op_store_srin(); ! 2266: #endif ! 2267: } ! 2268: ! 2269: /*** Lookaside buffer management ***/ ! 2270: /* Optional & supervisor only: */ ! 2271: /* tlbia */ ! 2272: GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA) ! 2273: { ! 2274: #if defined(CONFIG_USER_ONLY) ! 2275: RET_PRIVOPC(ctx); ! 2276: #else ! 2277: if (!ctx->supervisor) { ! 2278: if (loglevel) ! 2279: fprintf(logfile, "%s: ! supervisor\n", __func__); ! 2280: RET_PRIVOPC(ctx); ! 2281: return; ! 2282: } ! 2283: gen_op_tlbia(); ! 2284: RET_MTMSR(ctx); ! 2285: #endif ! 2286: } ! 2287: ! 2288: /* tlbie */ ! 2289: GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM) ! 2290: { ! 2291: #if defined(CONFIG_USER_ONLY) ! 2292: RET_PRIVOPC(ctx); ! 2293: #else ! 2294: if (!ctx->supervisor) { ! 2295: RET_PRIVOPC(ctx); ! 2296: return; ! 2297: } ! 2298: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2299: gen_op_tlbie(); ! 2300: RET_MTMSR(ctx); ! 2301: #endif ! 2302: } ! 2303: ! 2304: /* tlbsync */ ! 2305: GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM) ! 2306: { ! 2307: #if defined(CONFIG_USER_ONLY) ! 2308: RET_PRIVOPC(ctx); ! 2309: #else ! 2310: if (!ctx->supervisor) { ! 2311: RET_PRIVOPC(ctx); ! 2312: return; ! 2313: } ! 2314: /* This has no effect: it should ensure that all previous ! 2315: * tlbie have completed ! 2316: */ ! 2317: RET_MTMSR(ctx); ! 2318: #endif ! 2319: } ! 2320: ! 2321: /*** External control ***/ ! 2322: /* Optional: */ ! 2323: #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])() ! 2324: #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])() ! 2325: #if defined(CONFIG_USER_ONLY) ! 2326: static GenOpFunc *gen_op_eciwx[] = { ! 2327: &gen_op_eciwx_raw, ! 2328: &gen_op_eciwx_le_raw, ! 2329: }; ! 2330: static GenOpFunc *gen_op_ecowx[] = { ! 2331: &gen_op_ecowx_raw, ! 2332: &gen_op_ecowx_le_raw, ! 2333: }; ! 2334: #else ! 2335: static GenOpFunc *gen_op_eciwx[] = { ! 2336: &gen_op_eciwx_user, ! 2337: &gen_op_eciwx_le_user, ! 2338: &gen_op_eciwx_kernel, ! 2339: &gen_op_eciwx_le_kernel, ! 2340: }; ! 2341: static GenOpFunc *gen_op_ecowx[] = { ! 2342: &gen_op_ecowx_user, ! 2343: &gen_op_ecowx_le_user, ! 2344: &gen_op_ecowx_kernel, ! 2345: &gen_op_ecowx_le_kernel, ! 2346: }; ! 2347: #endif ! 2348: ! 2349: /* eciwx */ ! 2350: GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN) ! 2351: { ! 2352: /* Should check EAR[E] & alignment ! */ ! 2353: if (rA(ctx->opcode) == 0) { ! 2354: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2355: } else { ! 2356: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 2357: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2358: gen_op_add(); ! 2359: } ! 2360: op_eciwx(); ! 2361: gen_op_store_T0_gpr(rD(ctx->opcode)); ! 2362: } ! 2363: ! 2364: /* ecowx */ ! 2365: GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN) ! 2366: { ! 2367: /* Should check EAR[E] & alignment ! */ ! 2368: if (rA(ctx->opcode) == 0) { ! 2369: gen_op_load_gpr_T0(rB(ctx->opcode)); ! 2370: } else { ! 2371: gen_op_load_gpr_T0(rA(ctx->opcode)); ! 2372: gen_op_load_gpr_T1(rB(ctx->opcode)); ! 2373: gen_op_add(); ! 2374: } ! 2375: gen_op_load_gpr_T2(rS(ctx->opcode)); ! 2376: op_ecowx(); ! 2377: } ! 2378: ! 2379: /* End opcode list */ ! 2380: GEN_OPCODE_MARK(end); ! 2381: ! 2382: #include "translate_init.c" ! 2383: ! 2384: /*****************************************************************************/ ! 2385: /* Misc PowerPC helpers */ ! 2386: void cpu_dump_state(CPUState *env, FILE *f, ! 2387: int (*cpu_fprintf)(FILE *f, const char *fmt, ...), ! 2388: int flags) ! 2389: { ! 2390: #if defined(TARGET_PPC64) || 1 ! 2391: #define FILL "" ! 2392: #define REGX "%016llx" ! 2393: #define RGPL 4 ! 2394: #define RFPL 4 ! 2395: #else ! 2396: #define FILL " " ! 2397: #define REGX "%08llx" ! 2398: #define RGPL 8 ! 2399: #define RFPL 4 ! 2400: #endif ! 2401: ! 2402: int i; ! 2403: ! 2404: cpu_fprintf(f, "NIP " REGX " LR " REGX " CTR " REGX "\n", ! 2405: env->nip, env->lr, env->ctr); ! 2406: cpu_fprintf(f, "MSR " REGX FILL " XER %08x TB %08x %08x DECR %08x\n", ! 2407: do_load_msr(env), do_load_xer(env), cpu_ppc_load_tbu(env), ! 2408: cpu_ppc_load_tbl(env), cpu_ppc_load_decr(env)); ! 2409: for (i = 0; i < 32; i++) { ! 2410: if ((i & (RGPL - 1)) == 0) ! 2411: cpu_fprintf(f, "GPR%02d", i); ! 2412: cpu_fprintf(f, " " REGX, env->gpr[i]); ! 2413: if ((i & (RGPL - 1)) == (RGPL - 1)) ! 2414: cpu_fprintf(f, "\n"); ! 2415: } ! 2416: cpu_fprintf(f, "CR "); ! 2417: for (i = 0; i < 8; i++) ! 2418: cpu_fprintf(f, "%01x", env->crf[i]); ! 2419: cpu_fprintf(f, " ["); ! 2420: for (i = 0; i < 8; i++) { ! 2421: char a = '-'; ! 2422: if (env->crf[i] & 0x08) ! 2423: a = 'L'; ! 2424: else if (env->crf[i] & 0x04) ! 2425: a = 'G'; ! 2426: else if (env->crf[i] & 0x02) ! 2427: a = 'E'; ! 2428: cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' '); ! 2429: } ! 2430: cpu_fprintf(f, " ] " FILL "RES " REGX "\n", env->reserve); ! 2431: for (i = 0; i < 32; i++) { ! 2432: if ((i & (RFPL - 1)) == 0) ! 2433: cpu_fprintf(f, "FPR%02d", i); ! 2434: cpu_fprintf(f, " %016llx", *((uint64_t *)&env->fpr[i])); ! 2435: if ((i & (RFPL - 1)) == (RFPL - 1)) ! 2436: cpu_fprintf(f, "\n"); ! 2437: } ! 2438: cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX " " FILL FILL FILL ! 2439: "SDR1 " REGX "\n", ! 2440: env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1); ! 2441: ! 2442: #undef REGX ! 2443: #undef RGPL ! 2444: #undef RFPL ! 2445: #undef FILL ! 2446: } ! 2447: ! 2448: /*****************************************************************************/ ! 2449: int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ! 2450: int search_pc) ! 2451: { ! 2452: DisasContext ctx, *ctxp = &ctx; ! 2453: opc_handler_t **table, *handler; ! 2454: target_ulong pc_start; ! 2455: uint16_t *gen_opc_end; ! 2456: int j, lj = -1; ! 2457: ! 2458: pc_start = tb->pc; ! 2459: gen_opc_ptr = gen_opc_buf; ! 2460: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; ! 2461: gen_opparam_ptr = gen_opparam_buf; ! 2462: ctx.nip = pc_start; ! 2463: ctx.tb = tb; ! 2464: ctx.exception = EXCP_NONE; ! 2465: ctx.spr_cb = env->spr_cb; ! 2466: #if defined(CONFIG_USER_ONLY) ! 2467: ctx.mem_idx = msr_le; ! 2468: #else ! 2469: ctx.supervisor = 1 - msr_pr; ! 2470: ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le; ! 2471: #endif ! 2472: ctx.fpu_enabled = msr_fp; ! 2473: #if defined (DO_SINGLE_STEP) && 0 ! 2474: /* Single step trace mode */ ! 2475: msr_se = 1; ! 2476: #endif ! 2477: /* Set env in case of segfault during code fetch */ ! 2478: while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) { ! 2479: if (search_pc) { ! 2480: j = gen_opc_ptr - gen_opc_buf; ! 2481: if (lj < j) { ! 2482: lj++; ! 2483: while (lj < j) ! 2484: gen_opc_instr_start[lj++] = 0; ! 2485: gen_opc_pc[lj] = ctx.nip; ! 2486: gen_opc_instr_start[lj] = 1; ! 2487: } ! 2488: } ! 2489: #if defined PPC_DEBUG_DISAS ! 2490: if (loglevel & CPU_LOG_TB_IN_ASM) { ! 2491: fprintf(logfile, "----------------\n"); ! 2492: fprintf(logfile, "nip=%08x super=%d ir=%d\n", ! 2493: ctx.nip, 1 - msr_pr, msr_ir); ! 2494: } ! 2495: #endif ! 2496: ctx.opcode = ldl_code(ctx.nip); ! 2497: if (msr_le) { ! 2498: ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) | ! 2499: ((ctx.opcode & 0x00FF0000) >> 8) | ! 2500: ((ctx.opcode & 0x0000FF00) << 8) | ! 2501: ((ctx.opcode & 0x000000FF) << 24); ! 2502: } ! 2503: #if defined PPC_DEBUG_DISAS ! 2504: if (loglevel & CPU_LOG_TB_IN_ASM) { ! 2505: fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n", ! 2506: ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), ! 2507: opc3(ctx.opcode), msr_le ? "little" : "big"); ! 2508: } ! 2509: #endif ! 2510: ctx.nip += 4; ! 2511: table = env->opcodes; ! 2512: handler = table[opc1(ctx.opcode)]; ! 2513: if (is_indirect_opcode(handler)) { ! 2514: table = ind_table(handler); ! 2515: handler = table[opc2(ctx.opcode)]; ! 2516: if (is_indirect_opcode(handler)) { ! 2517: table = ind_table(handler); ! 2518: handler = table[opc3(ctx.opcode)]; ! 2519: } ! 2520: } ! 2521: /* Is opcode *REALLY* valid ? */ ! 2522: if (handler->handler == &gen_invalid) { ! 2523: if (loglevel > 0) { ! 2524: fprintf(logfile, "invalid/unsupported opcode: " ! 2525: "%02x - %02x - %02x (%08x) 0x%08x %d\n", ! 2526: opc1(ctx.opcode), opc2(ctx.opcode), ! 2527: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir); ! 2528: } else { ! 2529: printf("invalid/unsupported opcode: " ! 2530: "%02x - %02x - %02x (%08x) 0x%08x %d\n", ! 2531: opc1(ctx.opcode), opc2(ctx.opcode), ! 2532: opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir); ! 2533: } ! 2534: } else { ! 2535: if ((ctx.opcode & handler->inval) != 0) { ! 2536: if (loglevel > 0) { ! 2537: fprintf(logfile, "invalid bits: %08x for opcode: " ! 2538: "%02x -%02x - %02x (0x%08x) (0x%08x)\n", ! 2539: ctx.opcode & handler->inval, opc1(ctx.opcode), ! 2540: opc2(ctx.opcode), opc3(ctx.opcode), ! 2541: ctx.opcode, ctx.nip - 4); ! 2542: } else { ! 2543: printf("invalid bits: %08x for opcode: " ! 2544: "%02x -%02x - %02x (0x%08x) (0x%08x)\n", ! 2545: ctx.opcode & handler->inval, opc1(ctx.opcode), ! 2546: opc2(ctx.opcode), opc3(ctx.opcode), ! 2547: ctx.opcode, ctx.nip - 4); ! 2548: } ! 2549: RET_INVAL(ctxp); ! 2550: break; ! 2551: } ! 2552: } ! 2553: (*(handler->handler))(&ctx); ! 2554: /* Check trace mode exceptions */ ! 2555: if ((msr_be && ctx.exception == EXCP_BRANCH) || ! 2556: /* Check in single step trace mode ! 2557: * we need to stop except if: ! 2558: * - rfi, trap or syscall ! 2559: * - first instruction of an exception handler ! 2560: */ ! 2561: (msr_se && (ctx.nip < 0x100 || ! 2562: ctx.nip > 0xF00 || ! 2563: (ctx.nip & 0xFC) != 0x04) && ! 2564: ctx.exception != EXCP_SYSCALL && ! 2565: ctx.exception != EXCP_SYSCALL_USER && ! 2566: ctx.exception != EXCP_TRAP)) { ! 2567: RET_EXCP(ctxp, EXCP_TRACE, 0); ! 2568: } ! 2569: /* if we reach a page boundary, stop generation */ ! 2570: if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) { ! 2571: break; ! 2572: } ! 2573: #if defined (DO_SINGLE_STEP) ! 2574: break; ! 2575: #endif ! 2576: } ! 2577: if (ctx.exception == EXCP_NONE) { ! 2578: gen_op_b((unsigned long)ctx.tb, ctx.nip); ! 2579: } else if (ctx.exception != EXCP_BRANCH) { ! 2580: gen_op_set_T0(0); ! 2581: } ! 2582: #if 1 ! 2583: /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump ! 2584: * do bad business and then qemu crashes ! ! 2585: */ ! 2586: gen_op_set_T0(0); ! 2587: #endif ! 2588: /* Generate the return instruction */ ! 2589: gen_op_exit_tb(); ! 2590: *gen_opc_ptr = INDEX_op_end; ! 2591: if (search_pc) { ! 2592: j = gen_opc_ptr - gen_opc_buf; ! 2593: lj++; ! 2594: while (lj <= j) ! 2595: gen_opc_instr_start[lj++] = 0; ! 2596: tb->size = 0; ! 2597: #if 0 ! 2598: if (loglevel > 0) { ! 2599: page_dump(logfile); ! 2600: } ! 2601: #endif ! 2602: } else { ! 2603: tb->size = ctx.nip - pc_start; ! 2604: } ! 2605: #ifdef DEBUG_DISAS ! 2606: if (loglevel & CPU_LOG_TB_CPU) { ! 2607: fprintf(logfile, "---------------- excp: %04x\n", ctx.exception); ! 2608: cpu_dump_state(env, logfile, fprintf, 0); ! 2609: } ! 2610: if (loglevel & CPU_LOG_TB_IN_ASM) { ! 2611: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); ! 2612: target_disas(logfile, pc_start, ctx.nip - pc_start, 0); ! 2613: fprintf(logfile, "\n"); ! 2614: } ! 2615: if (loglevel & CPU_LOG_TB_OP) { ! 2616: fprintf(logfile, "OP:\n"); ! 2617: dump_ops(gen_opc_buf, gen_opparam_buf); ! 2618: fprintf(logfile, "\n"); ! 2619: } ! 2620: #endif ! 2621: return 0; ! 2622: } ! 2623: ! 2624: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) ! 2625: { ! 2626: return gen_intermediate_code_internal(env, tb, 0); ! 2627: } ! 2628: ! 2629: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) ! 2630: { ! 2631: return gen_intermediate_code_internal(env, tb, 1); ! 2632: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.