removed stdout reference (not portable)
[qemu] / target-ppc / translate.c
index bd0dc67..e09e9a7 100644 (file)
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include "dyngen-exec.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
 #include "cpu.h"
-#include "exec.h"
+#include "exec-all.h"
 #include "disas.h"
 
 //#define DO_SINGLE_STEP
-//#define DO_STEP_FLUSH
-//#define DEBUG_DISAS
+//#define PPC_DEBUG_DISAS
 
 enum {
 #define DEF(s, n, copy_size) INDEX_op_ ## s,
@@ -127,13 +131,9 @@ static uint8_t  spr_access[1024 / 2];
 /* internal defines */
 typedef struct DisasContext {
     struct TranslationBlock *tb;
-    uint32_t *nip;
+    uint32_t nip;
     uint32_t opcode;
     uint32_t exception;
-    /* Time base offset */
-    uint32_t tb_offset;
-    /* Decrementer offset */
-    uint32_t decr_offset;
     /* Execution mode */
 #if !defined(CONFIG_USER_ONLY)
     int supervisor;
@@ -151,21 +151,26 @@ typedef struct opc_handler_t {
     void (*handler)(DisasContext *ctx);
 } opc_handler_t;
 
-#define RET_EXCP(excp, error)                                                 \
+#define RET_EXCP(ctx, excp, error)                                            \
 do {                                                                          \
-    gen_op_queue_exception_err(excp, error);                                  \
-    ctx->exception = excp;                                                    \
-    return;                                                                   \
+    if ((ctx)->exception == EXCP_NONE) {                                      \
+        gen_op_update_nip((ctx)->nip);                                        \
+    }                                                                         \
+    gen_op_raise_exception_err((excp), (error));                              \
+    ctx->exception = (excp);                                                  \
 } while (0)
 
-#define RET_INVAL()                                                           \
-RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
+#define RET_INVAL(ctx)                                                        \
+RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
+
+#define RET_PRIVOPC(ctx)                                                      \
+RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
 
-#define RET_PRIVOPC()                                                         \
-RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
+#define RET_PRIVREG(ctx)                                                      \
+RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
 
-#define RET_PRIVREG()                                                         \
-RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
+#define RET_MTMSR(ctx)                                                        \
+RET_EXCP((ctx), EXCP_MTMSR, 0)
 
 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
 static void gen_##name (DisasContext *ctx);                                   \
@@ -177,10 +182,6 @@ typedef struct opcode_t {
     opc_handler_t handler;
 } opcode_t;
 
-/* XXX: move that elsewhere */
-extern FILE *logfile;
-extern int loglevel;
-
 /***                           Instruction decoding                        ***/
 #define EXTRACT_HELPER(name, shift, nb)                                       \
 static inline uint32_t name (uint32_t opcode)                                 \
@@ -276,7 +277,7 @@ static inline uint32_t MASK (uint32_t start, uint32_t end)
 }
 
 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
-__attribute__ ((section(".opcodes"), unused))                                 \
+__attribute__ ((section(".opcodes"), unused, aligned (8) ))                   \
 static opcode_t opc_##name = {                                                \
     .opc1 = op1,                                                              \
     .opc2 = op2,                                                              \
@@ -289,7 +290,7 @@ static opcode_t opc_##name = {                                                \
 }
 
 #define GEN_OPCODE_MARK(name)                                                 \
-__attribute__ ((section(".opcodes"), unused))                                 \
+__attribute__ ((section(".opcodes"), unused, aligned (8) ))                   \
 static opcode_t opc_##name = {                                                \
     .opc1 = 0xFF,                                                             \
     .opc2 = 0xFF,                                                             \
@@ -307,29 +308,26 @@ GEN_OPCODE_MARK(start);
 /* Invalid instruction */
 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
 {
-    RET_INVAL();
+    RET_INVAL(ctx);
 }
 
 /* Special opcode to stop emulation */
 GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON)
 {
-    gen_op_queue_exception(EXCP_HLT);
-    ctx->exception = EXCP_HLT;
+    RET_EXCP(ctx, EXCP_HLT, 0);
 }
 
 /* Special opcode to call open-firmware */
 GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON)
 {
-    gen_op_queue_exception(EXCP_OFCALL);
-    ctx->exception = EXCP_OFCALL;
+    RET_EXCP(ctx, EXCP_OFCALL, 0);
 }
 
 /* Special opcode to call RTAS */
 GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON)
 {
     printf("RTAS entry point !\n");
-    gen_op_queue_exception(EXCP_RTASCALL);
-    ctx->exception = EXCP_RTASCALL;
+    RET_EXCP(ctx, EXCP_RTASCALL, 0);
 }
 
 static opc_handler_t invalid_handler = {
@@ -639,7 +637,7 @@ GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     if (uimm != 0)
-    gen_op_xori(UIMM(ctx->opcode));
+    gen_op_xori(uimm);
     gen_op_store_T0_gpr(rA(ctx->opcode));
 }
 
@@ -654,7 +652,7 @@ GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     if (uimm != 0)
-    gen_op_xori(UIMM(ctx->opcode) << 16);
+    gen_op_xori(uimm << 16);
     gen_op_store_T0_gpr(rA(ctx->opcode));
 }
 
@@ -682,25 +680,29 @@ GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
     mb = MB(ctx->opcode);
     me = ME(ctx->opcode);
     gen_op_load_gpr_T0(rS(ctx->opcode));
+#if 1 // TRY
+    if (sh == 0) {
+        gen_op_andi_(MASK(mb, me));
+        goto store;
+    }
+#endif
     if (mb == 0) {
         if (me == 31) {
             gen_op_rotlwi(sh);
             goto store;
+#if 0
         } else if (me == (31 - sh)) {
             gen_op_slwi(sh);
             goto store;
-        } else if (sh == 0) {
-            gen_op_andi_(MASK(0, me));
-            goto store;
+#endif
         }
     } else if (me == 31) {
+#if 0
         if (sh == (32 - mb)) {
             gen_op_srwi(mb);
             goto store;
-        } else if (sh == 0) {
-            gen_op_andi_(MASK(mb, 31));
-            goto store;
         }
+#endif
     }
     gen_op_rlwinm(sh, MASK(mb, me));
 store:
@@ -1005,7 +1007,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
     uint32_t simm = SIMM(ctx->opcode);                                        \
     if (rA(ctx->opcode) == 0 ||                                               \
         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     if (simm != 0)                                                            \
@@ -1020,7 +1023,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
 {                                                                             \
     if (rA(ctx->opcode) == 0 ||                                               \
         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
@@ -1081,7 +1085,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
 {                                                                             \
     uint32_t simm = SIMM(ctx->opcode);                                        \
     if (rA(ctx->opcode) == 0) {                                               \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     if (simm != 0)                                                            \
@@ -1095,7 +1100,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)          \
 {                                                                             \
     if (rA(ctx->opcode) == 0) {                                               \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
@@ -1231,7 +1237,8 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
     nr = nb / 4;
     if (((start + nr) > 32  && start <= ra && (start + nr - 32) > ra) ||
         ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) {
-        RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+        return;
     }
     if (ra == 0) {
         gen_op_set_T0(0);
@@ -1263,12 +1270,16 @@ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
 /* stswi */
 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
 {
+    int nb = NB(ctx->opcode);
+
     if (rA(ctx->opcode) == 0) {
         gen_op_set_T0(0);
     } else {
         gen_op_load_gpr_T0(rA(ctx->opcode));
     }
-    gen_op_set_T1(NB(ctx->opcode));
+    if (nb == 0)
+        nb = 32;
+    gen_op_set_T1(nb);
     op_ldsts(stsw, rS(ctx->opcode));
 }
 
@@ -1371,7 +1382,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
     uint32_t simm = SIMM(ctx->opcode);                                        \
     if (rA(ctx->opcode) == 0 ||                                               \
         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     if (simm != 0)                                                            \
@@ -1386,7 +1398,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
 {                                                                             \
     if (rA(ctx->opcode) == 0 ||                                               \
         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
@@ -1443,7 +1456,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
 {                                                                             \
     uint32_t simm = SIMM(ctx->opcode);                                        \
     if (rA(ctx->opcode) == 0) {                                               \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     if (simm != 0)                                                            \
@@ -1457,7 +1471,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)          \
 {                                                                             \
     if (rA(ctx->opcode) == 0) {                                               \
-        RET_INVAL();                                                          \
+        RET_INVAL(ctx);                                                       \
+        return;                                                               \
     }                                                                         \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
@@ -1497,7 +1512,7 @@ GEN_STFS(fs, 0x14);
 /* stfiwx */
 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
 {
-    RET_INVAL();
+    RET_INVAL(ctx);
 }
 
 /***                                Branch                                 ***/
@@ -1505,17 +1520,17 @@ GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
 /* b ba bl bla */
 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
 {
-    uint32_t li = s_ext24(LI(ctx->opcode)), target;
+    uint32_t li, target;
+
+    /* sign extend LI */
+    li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
 
-    gen_op_update_tb(ctx->tb_offset);
-    gen_op_update_decr(ctx->decr_offset);
-    gen_op_process_exceptions((uint32_t)ctx->nip - 4);
     if (AA(ctx->opcode) == 0)
-        target = (uint32_t)ctx->nip + li - 4;
+        target = ctx->nip + li - 4;
     else
         target = li;
     if (LK(ctx->opcode)) {
-        gen_op_setlr((uint32_t)ctx->nip);
+        gen_op_setlr(ctx->nip);
     }
     gen_op_b((long)ctx->tb, target);
     ctx->exception = EXCP_BRANCH;
@@ -1533,17 +1548,13 @@ static inline void gen_bcond(DisasContext *ctx, int type)
     uint32_t mask;                                                            
     uint32_t li;
 
-    gen_op_update_tb(ctx->tb_offset);                                         
-    gen_op_update_decr(ctx->decr_offset);                                     
-    gen_op_process_exceptions((uint32_t)ctx->nip - 4);                        
-
     if ((bo & 0x4) == 0)
         gen_op_dec_ctr();                                                     
     switch(type) {
     case BCOND_IM:
         li = s_ext16(BD(ctx->opcode));
         if (AA(ctx->opcode) == 0) {
-            target = (uint32_t)ctx->nip + li - 4;
+            target = ctx->nip + li - 4;
         } else {
             target = li;
         }
@@ -1557,7 +1568,7 @@ static inline void gen_bcond(DisasContext *ctx, int type)
         break;
     }
     if (LK(ctx->opcode)) {                                        
-        gen_op_setlr((uint32_t)ctx->nip);
+        gen_op_setlr(ctx->nip);
     }
     if (bo & 0x10) {
         /* No CR condition */                                                 
@@ -1612,9 +1623,9 @@ static inline void gen_bcond(DisasContext *ctx, int type)
         }                                                                     
     }                                                                         
     if (type == BCOND_IM) {
-        gen_op_btest((long)ctx->tb, target, (uint32_t)ctx->nip);
+        gen_op_btest((long)ctx->tb, target, ctx->nip);
     } else {
-        gen_op_btest_T1((uint32_t)ctx->nip);
+        gen_op_btest_T1(ctx->nip);
     }
  no_test:
     ctx->exception = EXCP_BRANCH;                                             
@@ -1678,14 +1689,15 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC();
+    RET_PRIVOPC(ctx);
 #else
     /* Restore CPU state */
     if (!ctx->supervisor) {
-        RET_PRIVOPC();
+        RET_PRIVOPC(ctx);
+        return;
     }
     gen_op_rfi();
-    ctx->exception = EXCP_RFI;
+    RET_EXCP(ctx, EXCP_RFI, 0);
 #endif
 }
 
@@ -1693,11 +1705,10 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
 {
 #if defined(CONFIG_USER_ONLY)
-    gen_op_queue_exception(EXCP_SYSCALL_USER);
+    RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
 #else
-    gen_op_queue_exception(EXCP_SYSCALL);
+    RET_EXCP(ctx, EXCP_SYSCALL, 0);
 #endif
-    ctx->exception = EXCP_SYSCALL;
 }
 
 /***                                Trap                                   ***/
@@ -1765,10 +1776,11 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG();
+    RET_PRIVREG(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVREG();
+        RET_PRIVREG(ctx);
+        return;
     }
     gen_op_load_msr();
     gen_op_store_T0_gpr(rD(ctx->opcode));
@@ -1787,11 +1799,11 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
 #endif
     {
     case -1:
-        RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
-        break;
+        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
+        return;
     case 0:
-        RET_PRIVREG();
-        break;
+        RET_PRIVREG(ctx);
+        return;
     default:
         break;
         }
@@ -1905,19 +1917,13 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
         gen_op_load_sdr1();
         break;
     case V_TBL:
-        gen_op_update_tb(ctx->tb_offset);
-        ctx->tb_offset = 0;
-        /* TBL is still in T0 */
+        gen_op_load_tbl();
         break;
     case V_TBU:
-        gen_op_update_tb(ctx->tb_offset);
-        ctx->tb_offset = 0;
-        gen_op_load_tb(1);
+        gen_op_load_tbu();
         break;
     case DECR:
-        gen_op_update_decr(ctx->decr_offset);
-        ctx->decr_offset = 0;
-        /* decr is still in T0 */
+        gen_op_load_decr();
         break;
     default:
         gen_op_load_spr(sprn);
@@ -1934,18 +1940,15 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
         /* We need to update the time base before reading it */
     switch (sprn) {
     case V_TBL:
-        gen_op_update_tb(ctx->tb_offset);
-        /* TBL is still in T0 */
+        gen_op_load_tbl();
         break;
     case V_TBU:
-        gen_op_update_tb(ctx->tb_offset);
-        gen_op_load_tb(1);
+        gen_op_load_tbu();
         break;
     default:
-        RET_INVAL();
-        break;
+        RET_INVAL(ctx);
+        return;
     }
-    ctx->tb_offset = 0;
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
 
@@ -1960,15 +1963,16 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG();
+    RET_PRIVREG(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVREG();
+        RET_PRIVREG(ctx);
+        return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_store_msr();
     /* Must stop the translation as machine state (may have) changed */
-    ctx->exception = EXCP_MTMSR;
+    RET_MTMSR(ctx);
 #endif
 }
 
@@ -1990,10 +1994,10 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
 #endif
     {
     case -1:
-        RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
+        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
         break;
     case 0:
-        RET_PRIVREG();
+        RET_PRIVREG(ctx);
         break;
     default:
         break;
@@ -2004,7 +2008,6 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
         gen_op_store_xer();
         break;
     case LR:
-        gen_op_andi_(~0x03);
         gen_op_store_lr();
         break;
     case CTR:
@@ -2012,148 +2015,150 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
         break;
     case IBAT0U:
         gen_op_store_ibat(0, 0);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT1U:
         gen_op_store_ibat(0, 1);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT2U:
         gen_op_store_ibat(0, 2);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT3U:
         gen_op_store_ibat(0, 3);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT4U:
         gen_op_store_ibat(0, 4);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT5U:
         gen_op_store_ibat(0, 5);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT6U:
         gen_op_store_ibat(0, 6);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT7U:
         gen_op_store_ibat(0, 7);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT0L:
         gen_op_store_ibat(1, 0);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT1L:
         gen_op_store_ibat(1, 1);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT2L:
         gen_op_store_ibat(1, 2);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT3L:
         gen_op_store_ibat(1, 3);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT4L:
         gen_op_store_ibat(1, 4);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT5L:
         gen_op_store_ibat(1, 5);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT6L:
         gen_op_store_ibat(1, 6);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case IBAT7L:
         gen_op_store_ibat(1, 7);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT0U:
         gen_op_store_dbat(0, 0);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT1U:
         gen_op_store_dbat(0, 1);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT2U:
         gen_op_store_dbat(0, 2);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT3U:
         gen_op_store_dbat(0, 3);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT4U:
         gen_op_store_dbat(0, 4);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT5U:
         gen_op_store_dbat(0, 5);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT6U:
         gen_op_store_dbat(0, 6);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT7U:
         gen_op_store_dbat(0, 7);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT0L:
         gen_op_store_dbat(1, 0);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT1L:
         gen_op_store_dbat(1, 1);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT2L:
         gen_op_store_dbat(1, 2);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT3L:
         gen_op_store_dbat(1, 3);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT4L:
         gen_op_store_dbat(1, 4);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT5L:
         gen_op_store_dbat(1, 5);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT6L:
         gen_op_store_dbat(1, 6);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case DBAT7L:
         gen_op_store_dbat(1, 7);
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case SDR1:
         gen_op_store_sdr1();
-        gen_op_tlbia();
+        RET_MTMSR(ctx);
         break;
     case O_TBL:
-        gen_op_store_tb(0);
-        ctx->tb_offset = 0;
+        gen_op_store_tbl();
         break;
     case O_TBU:
-        gen_op_store_tb(1);
-        ctx->tb_offset = 0;
+        gen_op_store_tbu();
         break;
     case DECR:
         gen_op_store_decr();
-        ctx->decr_offset = 0;
         break;
+#if 0
+    case HID0:
+        gen_op_store_hid0();
+        break;
+#endif
     default:
         gen_op_store_spr(sprn);
         break;
@@ -2182,10 +2187,11 @@ GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC();
+    RET_PRIVOPC(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVOPC();
+        RET_PRIVOPC(ctx);
+        return;
     }
     if (rA(ctx->opcode) == 0) {
         gen_op_load_gpr_T0(rB(ctx->opcode));
@@ -2243,6 +2249,7 @@ GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
         gen_op_add();
     }
     op_dcbz();
+    gen_op_check_reservation();
 }
 
 /* icbi */
@@ -2270,10 +2277,11 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT)
 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG();
+    RET_PRIVREG(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVREG();
+        RET_PRIVREG(ctx);
+        return;
     }
     gen_op_load_sr(SR(ctx->opcode));
     gen_op_store_T0_gpr(rD(ctx->opcode));
@@ -2284,10 +2292,11 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG();
+    RET_PRIVREG(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVREG();
+        RET_PRIVREG(ctx);
+        return;
     }
     gen_op_load_gpr_T1(rB(ctx->opcode));
     gen_op_load_srin();
@@ -2296,17 +2305,17 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
 }
 
 /* mtsr */
-GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT)
+GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG();
+    RET_PRIVREG(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVREG();
+        RET_PRIVREG(ctx);
+        return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_store_sr(SR(ctx->opcode));
-    gen_op_tlbia();
 #endif
 }
 
@@ -2314,15 +2323,15 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT)
 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG();
+    RET_PRIVREG(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVREG();
+        RET_PRIVREG(ctx);
+        return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_load_gpr_T1(rB(ctx->opcode));
     gen_op_store_srin();
-    gen_op_tlbia();
 #endif
 }
 
@@ -2332,12 +2341,16 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC();
+    RET_PRIVOPC(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVOPC();
+        if (loglevel)
+            fprintf(logfile, "%s: ! supervisor\n", __func__);
+        RET_PRIVOPC(ctx);
+        return;
     }
     gen_op_tlbia();
+    RET_MTMSR(ctx);
 #endif
 }
 
@@ -2345,28 +2358,32 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC();
+    RET_PRIVOPC(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVOPC();
+        RET_PRIVOPC(ctx);
+        return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
     gen_op_tlbie();
+    RET_MTMSR(ctx);
 #endif
 }
 
 /* tlbsync */
-GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM)
+GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC();
+    RET_PRIVOPC(ctx);
 #else
     if (!ctx->supervisor) {
-        RET_PRIVOPC();
+        RET_PRIVOPC(ctx);
+        return;
     }
     /* This has no effect: it should ensure that all previous
      * tlbie have completed
      */
+    RET_MTMSR(ctx);
 #endif
 }
 
@@ -2687,59 +2704,78 @@ static void init_spr_rights (uint32_t pvr)
     spr_set_rights(DBAT3U, SPR_SR | SPR_SW);
     /* DBAT3L (SPR 543) */
     spr_set_rights(DBAT3L, SPR_SR | SPR_SW);
-    /* DABR   (SPR 1013) */
-    spr_set_rights(DABR,   SPR_SR | SPR_SW);
     /* FPECR  (SPR 1022) */
     spr_set_rights(FPECR,  SPR_SR | SPR_SW);
-    /* PIR    (SPR 1023) */
+    /* Special registers for PPC 604 */
+    if ((pvr & 0xFFFF0000) == 0x00040000) {
+        /* IABR */
+        spr_set_rights(IABR ,  SPR_SR | SPR_SW);
+        /* DABR   (SPR 1013) */
+        spr_set_rights(DABR,   SPR_SR | SPR_SW);
+        /* HID0 */
+        spr_set_rights(HID0,   SPR_SR | SPR_SW);
+        /* PIR */
     spr_set_rights(PIR,    SPR_SR | SPR_SW);
+        /* PMC1 */
+        spr_set_rights(PMC1,   SPR_SR | SPR_SW);
+        /* PMC2 */
+        spr_set_rights(PMC2,   SPR_SR | SPR_SW);
+        /* MMCR0 */
+        spr_set_rights(MMCR0,  SPR_SR | SPR_SW);
+        /* SIA */
+        spr_set_rights(SIA,    SPR_SR | SPR_SW);
+        /* SDA */
+        spr_set_rights(SDA,    SPR_SR | SPR_SW);
+    }
     /* Special registers for MPC740/745/750/755 (aka G3) & IBM 750 */
     if ((pvr & 0xFFFF0000) == 0x00080000 ||
         (pvr & 0xFFFF0000) == 0x70000000) {
         /* HID0 */
-        spr_set_rights(SPR_ENCODE(1008), SPR_SR | SPR_SW);
+        spr_set_rights(HID0,   SPR_SR | SPR_SW);
         /* HID1 */
-        spr_set_rights(SPR_ENCODE(1009), SPR_SR | SPR_SW);
+        spr_set_rights(HID1,   SPR_SR | SPR_SW);
         /* IABR */
-        spr_set_rights(SPR_ENCODE(1010), SPR_SR | SPR_SW);
+        spr_set_rights(IABR,   SPR_SR | SPR_SW);
         /* ICTC */
-        spr_set_rights(SPR_ENCODE(1019), SPR_SR | SPR_SW);
+        spr_set_rights(ICTC,   SPR_SR | SPR_SW);
         /* L2CR */
-        spr_set_rights(SPR_ENCODE(1017), SPR_SR | SPR_SW);
+        spr_set_rights(L2CR,   SPR_SR | SPR_SW);
         /* MMCR0 */
-        spr_set_rights(SPR_ENCODE(952), SPR_SR | SPR_SW);
+        spr_set_rights(MMCR0,  SPR_SR | SPR_SW);
         /* MMCR1 */
-        spr_set_rights(SPR_ENCODE(956), SPR_SR | SPR_SW);
+        spr_set_rights(MMCR1,  SPR_SR | SPR_SW);
         /* PMC1 */
-        spr_set_rights(SPR_ENCODE(953), SPR_SR | SPR_SW);
+        spr_set_rights(PMC1,   SPR_SR | SPR_SW);
         /* PMC2 */
-        spr_set_rights(SPR_ENCODE(954), SPR_SR | SPR_SW);
+        spr_set_rights(PMC2,   SPR_SR | SPR_SW);
         /* PMC3 */
-        spr_set_rights(SPR_ENCODE(957), SPR_SR | SPR_SW);
+        spr_set_rights(PMC3,   SPR_SR | SPR_SW);
         /* PMC4 */
-        spr_set_rights(SPR_ENCODE(958), SPR_SR | SPR_SW);
+        spr_set_rights(PMC4,   SPR_SR | SPR_SW);
         /* SIA */
-        spr_set_rights(SPR_ENCODE(955), SPR_SR | SPR_SW);
+        spr_set_rights(SIA,    SPR_SR | SPR_SW);
+        /* SDA */
+        spr_set_rights(SDA,    SPR_SR | SPR_SW);
         /* THRM1 */
-        spr_set_rights(SPR_ENCODE(1020), SPR_SR | SPR_SW);
+        spr_set_rights(THRM1,  SPR_SR | SPR_SW);
         /* THRM2 */
-        spr_set_rights(SPR_ENCODE(1021), SPR_SR | SPR_SW);
+        spr_set_rights(THRM2,  SPR_SR | SPR_SW);
         /* THRM3 */
-        spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW);
+        spr_set_rights(THRM3,  SPR_SR | SPR_SW);
         /* UMMCR0 */
-        spr_set_rights(SPR_ENCODE(936), SPR_UR | SPR_UW);
+        spr_set_rights(UMMCR0, SPR_UR | SPR_UW);
         /* UMMCR1 */
-        spr_set_rights(SPR_ENCODE(940), SPR_UR | SPR_UW);
+        spr_set_rights(UMMCR1, SPR_UR | SPR_UW);
         /* UPMC1 */
-        spr_set_rights(SPR_ENCODE(937), SPR_UR | SPR_UW);
+        spr_set_rights(UPMC1,  SPR_UR | SPR_UW);
         /* UPMC2 */
-        spr_set_rights(SPR_ENCODE(938), SPR_UR | SPR_UW);
+        spr_set_rights(UPMC2,  SPR_UR | SPR_UW);
         /* UPMC3 */
-        spr_set_rights(SPR_ENCODE(941), SPR_UR | SPR_UW);
+        spr_set_rights(UPMC3,  SPR_UR | SPR_UW);
         /* UPMC4 */
-        spr_set_rights(SPR_ENCODE(942), SPR_UR | SPR_UW);
+        spr_set_rights(UPMC4,  SPR_UR | SPR_UW);
         /* USIA */
-        spr_set_rights(SPR_ENCODE(939), SPR_UR | SPR_UW);
+        spr_set_rights(USIA,   SPR_UR | SPR_UW);
     }
     /* MPC755 has special registers */
     if (pvr == 0x00083100) {
@@ -2784,23 +2820,23 @@ static void init_spr_rights (uint32_t pvr)
         /* DBAT7L */
         spr_set_rights(DBAT7L, SPR_SR | SPR_SW);
         /* DMISS */
-        spr_set_rights(SPR_ENCODE(976), SPR_SR | SPR_SW);
+        spr_set_rights(DMISS,  SPR_SR | SPR_SW);
         /* DCMP */
-        spr_set_rights(SPR_ENCODE(977), SPR_SR | SPR_SW);
+        spr_set_rights(DCMP,   SPR_SR | SPR_SW);
         /* DHASH1 */
-        spr_set_rights(SPR_ENCODE(978), SPR_SR | SPR_SW);
+        spr_set_rights(DHASH1, SPR_SR | SPR_SW);
         /* DHASH2 */
-        spr_set_rights(SPR_ENCODE(979), SPR_SR | SPR_SW);
+        spr_set_rights(DHASH2, SPR_SR | SPR_SW);
         /* IMISS */
-        spr_set_rights(SPR_ENCODE(980), SPR_SR | SPR_SW);
+        spr_set_rights(IMISS,  SPR_SR | SPR_SW);
         /* ICMP */
-        spr_set_rights(SPR_ENCODE(981), SPR_SR | SPR_SW);
+        spr_set_rights(ICMP,   SPR_SR | SPR_SW);
         /* RPA */
-        spr_set_rights(SPR_ENCODE(982), SPR_SR | SPR_SW);
+        spr_set_rights(RPA,    SPR_SR | SPR_SW);
         /* HID2 */
-        spr_set_rights(SPR_ENCODE(1011), SPR_SR | SPR_SW);
+        spr_set_rights(HID2,   SPR_SR | SPR_SW);
         /* L2PM */
-        spr_set_rights(SPR_ENCODE(1016), SPR_SR | SPR_SW);
+        spr_set_rights(L2PM,   SPR_SR | SPR_SW);
     }
 }
 
@@ -2881,7 +2917,6 @@ static int create_ppc_proc (opc_handler_t **ppc_opcodes, unsigned long pvr)
 
 /*****************************************************************************/
 /* Misc PPC helpers */
-FILE *stdout;
 
 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
 {
@@ -2912,7 +2947,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
         fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
         }
     fprintf(f, " ] ");
-    fprintf(f, "TB: 0x%08x %08x\n", env->tb[1], env->tb[0]);
+    fprintf(f, "TB: 0x%08x %08x\n", cpu_ppc_load_tbu(env),
+            cpu_ppc_load_tbl(env));
         for (i = 0; i < 16; i++) {
             if ((i & 3) == 0)
             fprintf(f, "FPR%02d:", i);
@@ -2920,8 +2956,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
             if ((i & 3) == 3)
             fprintf(f, "\n");
     }
-    fprintf(f, "SRR0 0x%08x SRR1 0x%08x DECR=0x%08x excp:0x%08x\n",
-            env->spr[SRR0], env->spr[SRR1], env->decr, env->exceptions);
+    fprintf(f, "SRR0 0x%08x SRR1 0x%08x DECR=0x%08x\n",
+            env->spr[SRR0], env->spr[SRR1], cpu_ppc_load_decr(env));
     fprintf(f, "reservation 0x%08x\n", env->reserve);
     fflush(f);
 }
@@ -2936,10 +2972,9 @@ CPUPPCState *cpu_ppc_init(void)
 
     cpu_exec_init();
 
-    env = malloc(sizeof(CPUPPCState));
+    env = qemu_mallocz(sizeof(CPUPPCState));
     if (!env)
         return NULL;
-    memset(env, 0, sizeof(CPUPPCState));
 #if !defined(CONFIG_USER_ONLY) && defined (USE_OPEN_FIRMWARE)
     setup_machine(env, 0);
 #else
@@ -2948,23 +2983,34 @@ CPUPPCState *cpu_ppc_init(void)
 //    env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */
 //    env->spr[PVR] = 0x00070100; /* IBM 750FX */
 #endif
-    env->decr = 0xFFFFFFFF;
-    if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
-        return NULL;
-    init_spr_rights(env->spr[PVR]);
     tlb_flush(env, 1);
 #if defined (DO_SINGLE_STEP)
     /* Single step trace mode */
     msr_se = 1;
 #endif
+    msr_fp = 1; /* Allow floating point exceptions */
+    msr_me = 1; /* Allow machine check exceptions  */
 #if defined(CONFIG_USER_ONLY)
     msr_pr = 1;
+    cpu_ppc_register(env, 0x00080000);
+#else
+    env->nip = 0xFFFFFFFC;
 #endif
     env->access_type = ACCESS_INT;
-
+    cpu_single_env = env;
     return env;
 }
 
+int cpu_ppc_register (CPUPPCState *env, uint32_t pvr)
+{
+    env->spr[PVR] = pvr;
+    if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
+        return -1;
+    init_spr_rights(env->spr[PVR]);
+
+    return 0;
+}
+
 void cpu_ppc_close(CPUPPCState *env)
 {
     /* Should also remove all opcode tables... */
@@ -2972,14 +3018,13 @@ void cpu_ppc_close(CPUPPCState *env)
 }
 
 /*****************************************************************************/
-void raise_exception_err (int exception_index, int error_code);
 int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
                         int dialect);
 
 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                                     int search_pc)
 {
-    DisasContext ctx;
+    DisasContext ctx, *ctxp = &ctx;
     opc_handler_t **table, *handler;
     uint32_t pc_start;
     uint16_t *gen_opc_end;
@@ -2989,9 +3034,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
     gen_opc_ptr = gen_opc_buf;
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
     gen_opparam_ptr = gen_opparam_buf;
-    ctx.nip = (uint32_t *)pc_start;
-    ctx.tb_offset = 0;
-    ctx.decr_offset = 0;
+    ctx.nip = pc_start;
     ctx.tb = tb;
     ctx.exception = EXCP_NONE;
 #if defined(CONFIG_USER_ONLY)
@@ -3015,30 +3058,26 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                 lj++;
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
-                gen_opc_pc[lj] = (uint32_t)ctx.nip;
+                gen_opc_pc[lj] = ctx.nip;
                 gen_opc_instr_start[lj] = 1;
             }
         }
-#if defined DEBUG_DISAS
-        if (loglevel > 0) {
+#if defined PPC_DEBUG_DISAS
+        if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "----------------\n");
-            fprintf(logfile, "nip=%p super=%d ir=%d\n",
+            fprintf(logfile, "nip=%08x super=%d ir=%d\n",
                     ctx.nip, 1 - msr_pr, msr_ir);
         }
 #endif
-        ctx.opcode = ldl_code(ctx.nip);
-#if defined DEBUG_DISAS
-        if (loglevel > 0) {
+        ctx.opcode = ldl_code((void *)ctx.nip);
+#if defined PPC_DEBUG_DISAS
+        if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n",
                     ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
                     opc3(ctx.opcode));
         }
 #endif
-        ctx.nip++;
-        ctx.tb_offset++;
-        /* Check decrementer exception */
-        if (++ctx.decr_offset == env->decr + 1)
-            ctx.exception = EXCP_DECR;
+        ctx.nip += 4;
         table = ppc_opcodes;
         handler = table[opc1(ctx.opcode)];
         if (is_indirect_opcode(handler)) {
@@ -3050,38 +3089,38 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
             }
         }
         /* Is opcode *REALLY* valid ? */
-        if ((ctx.opcode & handler->inval) != 0) {
-            if (loglevel > 0) {
                 if (handler->handler == &gen_invalid) {
+            if (loglevel > 0) {
                     fprintf(logfile, "invalid/unsupported opcode: "
-                            "%02x -%02x - %02x (%08x) %p\n",
+                        "%02x - %02x - %02x (%08x) 0x%08x %d\n",
                             opc1(ctx.opcode), opc2(ctx.opcode),
-                            opc3(ctx.opcode), ctx.opcode, ctx.nip - 1);
+                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
+            } else {
+                printf("invalid/unsupported opcode: "
+                       "%02x - %02x - %02x (%08x) 0x%08x %d\n",
+                       opc1(ctx.opcode), opc2(ctx.opcode),
+                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
+            }
                 } else {
+            if ((ctx.opcode & handler->inval) != 0) {
+                if (loglevel > 0) {
                     fprintf(logfile, "invalid bits: %08x for opcode: "
-                            "%02x -%02x - %02x (0x%08x) (%p)\n",
+                            "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
                             ctx.opcode & handler->inval, opc1(ctx.opcode),
                             opc2(ctx.opcode), opc3(ctx.opcode),
-                            ctx.opcode, ctx.nip - 1);
-                }
-            } else {
-                if (handler->handler == &gen_invalid) {
-                    printf("invalid/unsupported opcode: "
-                           "%02x -%02x - %02x (%08x) %p\n",
-                           opc1(ctx.opcode), opc2(ctx.opcode),
-                           opc3(ctx.opcode), ctx.opcode, ctx.nip - 1);
+                            ctx.opcode, ctx.nip - 4);
                 } else {
                     printf("invalid bits: %08x for opcode: "
-                           "%02x -%02x - %02x (0x%08x) (%p)\n",
+                           "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
                             ctx.opcode & handler->inval, opc1(ctx.opcode),
                             opc2(ctx.opcode), opc3(ctx.opcode),
-                           ctx.opcode, ctx.nip - 1);
+                           ctx.opcode, ctx.nip - 4);
             }
+                RET_INVAL(ctxp);
+                break;
             }
-            (*gen_invalid)(&ctx);
-        } else {
-            (*(handler->handler))(&ctx);
         }
+        (*(handler->handler))(&ctx);
         /* Check trace mode exceptions */
         if ((msr_be && ctx.exception == EXCP_BRANCH) ||
             /* Check in single step trace mode
@@ -3089,31 +3128,22 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
              * - rfi, trap or syscall
              * - first instruction of an exception handler
              */
-            (msr_se && ((uint32_t)ctx.nip < 0x100 ||
-                        (uint32_t)ctx.nip > 0xF00 ||
-                        ((uint32_t)ctx.nip & 0xFC) != 0x04) &&
+            (msr_se && (ctx.nip < 0x100 ||
+                        ctx.nip > 0xF00 ||
+                        (ctx.nip & 0xFC) != 0x04) &&
              ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
              ctx.exception != EXCP_TRAP)) {
-#if !defined(CONFIG_USER_ONLY)
-            gen_op_queue_exception(EXCP_TRACE);
-#endif
-            if (ctx.exception == EXCP_NONE) {
-                ctx.exception = EXCP_TRACE;
-    }
+            RET_EXCP(ctxp, EXCP_TRACE, 0);
         }
         /* if we reach a page boundary, stop generation */
-        if (((uint32_t)ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) {
-            if (ctx.exception == EXCP_NONE) {
-        gen_op_b((long)ctx.tb, (uint32_t)ctx.nip);
-                ctx.exception = EXCP_BRANCH;
-    }
+        if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) {
+            RET_EXCP(ctxp, EXCP_BRANCH, 0);
     }
     }
-    /* In case of branch, this has already been done *BEFORE* the branch */
-    if (ctx.exception != EXCP_BRANCH && ctx.exception != EXCP_RFI) {
-        gen_op_update_tb(ctx.tb_offset);
-        gen_op_update_decr(ctx.decr_offset);
-        gen_op_process_exceptions((uint32_t)ctx.nip);
+    if (ctx.exception == EXCP_NONE) {
+        gen_op_b((unsigned long)ctx.tb, ctx.nip);
+    } else if (ctx.exception != EXCP_BRANCH) {
+        gen_op_set_T0(0);
     }
 #if 1
     /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
@@ -3136,22 +3166,25 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
         }
 #endif
     } else {
-        tb->size = (uint32_t)ctx.nip - pc_start;
+        tb->size = ctx.nip - pc_start;
     }
-    env->access_type = ACCESS_INT;
 #ifdef DEBUG_DISAS
-    if (loglevel > 0) {
+    if (loglevel & CPU_LOG_TB_CPU) {
         fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
         cpu_ppc_dump_state(env, logfile, 0);
+    }
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
         fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
-       disas(logfile, (void *)pc_start, (uint32_t)ctx.nip - pc_start, 0, 0);
+       disas(logfile, (void *)pc_start, ctx.nip - pc_start, 0, 0);
         fprintf(logfile, "\n");
-
+    }
+    if (loglevel & CPU_LOG_TB_OP) {
         fprintf(logfile, "OP:\n");
         dump_ops(gen_opc_buf, gen_opparam_buf);
         fprintf(logfile, "\n");
     }
 #endif
+    env->access_type = ACCESS_INT;
 
     return 0;
 }