Annotation of qemu/target-ppc/translate.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.