]> git.proxmox.com Git - qemu.git/blobdiff - target-ppc/op.c
target-ppc: convert crf related instructions to TCG
[qemu.git] / target-ppc / op.c
index f13f6f56769d65dcc7c0f6f6f4893c9acb879ab1..d9676ba81eef2c354b7ea1c82b4c1d3edf41ef0f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  PowerPC emulation micro-operations for qemu.
- * 
+ *
  *  Copyright (c) 2003-2007 Jocelyn Mayer
  *
  * This library is free software; you can redistribute it and/or
 
 #include "config.h"
 #include "exec.h"
+#include "host-utils.h"
+#include "helper_regs.h"
 #include "op_helper.h"
 
-/* XXX: this is to be suppressed */
-#define regs (env)
-
-#define FT0 (env->ft0)
-#define FT1 (env->ft1)
-#define FT2 (env->ft2)
-
-/* XXX: this is to be suppressed... */
-#define PPC_OP(name) void OPPROTO glue(op_, name)(void)
-
-#define REG 0
-#include "op_template.h"
-
-#define REG 1
-#include "op_template.h"
-
-#define REG 2
-#include "op_template.h"
-
-#define REG 3
-#include "op_template.h"
-
-#define REG 4
-#include "op_template.h"
-
-#define REG 5
-#include "op_template.h"
-
-#define REG 6
-#include "op_template.h"
-
-#define REG 7
-#include "op_template.h"
-
-#define REG 8
-#include "op_template.h"
-
-#define REG 9
-#include "op_template.h"
-
-#define REG 10
-#include "op_template.h"
-
-#define REG 11
-#include "op_template.h"
-
-#define REG 12
-#include "op_template.h"
-
-#define REG 13
-#include "op_template.h"
-
-#define REG 14
-#include "op_template.h"
-
-#define REG 15
-#include "op_template.h"
-
-#define REG 16
-#include "op_template.h"
-
-#define REG 17
-#include "op_template.h"
-
-#define REG 18
-#include "op_template.h"
-
-#define REG 19
-#include "op_template.h"
-
-#define REG 20
-#include "op_template.h"
-
-#define REG 21
-#include "op_template.h"
-
-#define REG 22
-#include "op_template.h"
-
-#define REG 23
-#include "op_template.h"
-
-#define REG 24
-#include "op_template.h"
-
-#define REG 25
-#include "op_template.h"
-
-#define REG 26
-#include "op_template.h"
-
-#define REG 27
-#include "op_template.h"
-
-#define REG 28
-#include "op_template.h"
-
-#define REG 29
-#include "op_template.h"
-
-#define REG 30
-#include "op_template.h"
-
-#define REG 31
-#include "op_template.h"
-
-/* PowerPC state maintenance operations */
-/* set_Rc0 */
-PPC_OP(set_Rc0)
-{
-    env->crf[0] = T0 | xer_ov;
-    RETURN();
-}
-
-/* Set Rc1 (for floating point arithmetic) */
-PPC_OP(set_Rc1)
-{
-    env->crf[1] = regs->fpscr[7];
-    RETURN();
-}
-
-/* Constants load */
-void OPPROTO op_reset_T0 (void)
-{
-    T0 = 0;
-    RETURN();
-}
-
-PPC_OP(set_T0)
-{
-    T0 = (uint32_t)PARAM1;
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_set_T0_64 (void)
-{
-    T0 = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
-    RETURN();
-}
-#endif
-
-PPC_OP(set_T1)
-{
-    T1 = (uint32_t)PARAM1;
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_set_T1_64 (void)
-{
-    T1 = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
-    RETURN();
-}
-#endif
-
-#if 0 // unused
-PPC_OP(set_T2)
-{
-    T2 = PARAM(1);
-    RETURN();
-}
-#endif
-
-void OPPROTO op_move_T1_T0 (void)
-{
-    T1 = T0;
-    RETURN();
-}
-
-void OPPROTO op_move_T2_T0 (void)
-{
-    T2 = T0;
-    RETURN();
-}
-
 /* Generate exceptions */
-PPC_OP(raise_exception_err)
-{
-    do_raise_exception_err(PARAM(1), PARAM(2));
-}
-
-PPC_OP(update_nip)
-{
-    env->nip = (uint32_t)PARAM1;
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_update_nip_64 (void)
+void OPPROTO op_raise_exception_err (void)
 {
-    env->nip = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
-    RETURN();
+    do_raise_exception_err(PARAM1, PARAM2);
 }
-#endif
 
-PPC_OP(debug)
+void OPPROTO op_debug (void)
 {
     do_raise_exception(EXCP_DEBUG);
 }
 
-PPC_OP(exit_tb)
-{
-    EXIT_TB();
-}
-
 /* Load/store special registers */
-PPC_OP(load_cr)
-{
-    do_load_cr();
-    RETURN();
-}
-
-PPC_OP(store_cr)
-{
-    do_store_cr(PARAM(1));
-    RETURN();
-}
-
-void OPPROTO op_load_cro (void)
-{
-    T0 = env->crf[PARAM1];
-    RETURN();
-}
-
-void OPPROTO op_store_cro (void)
+#if defined(TARGET_PPC64)
+void OPPROTO op_store_pri (void)
 {
-    env->crf[PARAM1] = T0;
+    do_store_pri(PARAM1);
     RETURN();
 }
+#endif
 
-PPC_OP(load_xer_cr)
+#if !defined(CONFIG_USER_ONLY)
+/* Segment registers load and store */
+void OPPROTO op_load_sr (void)
 {
-    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
+    T0 = env->sr[T1];
     RETURN();
 }
 
-PPC_OP(clear_xer_cr)
+void OPPROTO op_store_sr (void)
 {
-    xer_so = 0;
-    xer_ov = 0;
-    xer_ca = 0;
+    do_store_sr(env, T1, T0);
     RETURN();
 }
 
-PPC_OP(load_xer_bc)
+#if defined(TARGET_PPC64)
+void OPPROTO op_load_slb (void)
 {
-    T1 = xer_bc;
+    T0 = ppc_load_slb(env, T1);
     RETURN();
 }
 
-void OPPROTO op_store_xer_bc (void)
+void OPPROTO op_store_slb (void)
 {
-    xer_bc = T0;
+    ppc_store_slb(env, T1, T0);
     RETURN();
 }
+#endif /* defined(TARGET_PPC64) */
 
-PPC_OP(load_xer)
+void OPPROTO op_load_sdr1 (void)
 {
-    do_load_xer();
+    T0 = env->sdr1;
     RETURN();
 }
 
-PPC_OP(store_xer)
+void OPPROTO op_store_sdr1 (void)
 {
-    do_store_xer();
+    do_store_sdr1(env, T0);
     RETURN();
 }
 
-#if !defined(CONFIG_USER_ONLY)
-/* Segment registers load and store */
-PPC_OP(load_sr)
+#if defined (TARGET_PPC64)
+void OPPROTO op_load_asr (void)
 {
-    T0 = regs->sr[T1];
+    T0 = env->asr;
     RETURN();
 }
 
-PPC_OP(store_sr)
+void OPPROTO op_store_asr (void)
 {
-    do_store_sr(env, T1, T0);
+    ppc_store_asr(env, T0);
     RETURN();
 }
+#endif
 
-PPC_OP(load_sdr1)
+void OPPROTO op_load_msr (void)
 {
-    T0 = regs->sdr1;
+    T0 = env->msr;
     RETURN();
 }
 
-PPC_OP(store_sdr1)
+void OPPROTO op_store_msr (void)
 {
-    do_store_sdr1(env, T0);
+    do_store_msr();
     RETURN();
 }
 
 #if defined (TARGET_PPC64)
-void OPPROTO op_load_asr (void)
+void OPPROTO op_store_msr_32 (void)
 {
-    T0 = env->asr;
+    T0 = (env->msr & ~0xFFFFFFFFULL) | (T0 & 0xFFFFFFFF);
+    do_store_msr();
     RETURN();
 }
+#endif
 
-void OPPROTO op_store_asr (void)
+void OPPROTO op_update_riee (void)
 {
-    ppc_store_asr(env, T0);
+    /* We don't call do_store_msr here as we won't trigger
+     * any special case nor change hflags
+     */
+    T0 &= (1 << MSR_RI) | (1 << MSR_EE);
+    env->msr &= ~(1 << MSR_RI) | (1 << MSR_EE);
+    env->msr |= T0;
     RETURN();
 }
 #endif
 
-PPC_OP(load_msr)
+/* SPR */
+void OPPROTO op_load_spr (void)
 {
-    T0 = do_load_msr(env);
+    T0 = env->spr[PARAM1];
     RETURN();
 }
 
-PPC_OP(store_msr)
+void OPPROTO op_store_spr (void)
 {
-    do_store_msr(env, T0);
+    env->spr[PARAM1] = T0;
     RETURN();
 }
 
-#if defined (TARGET_PPC64)
-void OPPROTO op_store_msr_32 (void)
+void OPPROTO op_load_dump_spr (void)
 {
-    ppc_store_msr_32(env, T0);
+    T0 = ppc_load_dump_spr(PARAM1);
     RETURN();
 }
-#endif
-#endif
 
-/* SPR */
-PPC_OP(load_spr)
+void OPPROTO op_store_dump_spr (void)
 {
-    T0 = regs->spr[PARAM(1)];
+    ppc_store_dump_spr(PARAM1, T0);
     RETURN();
 }
 
-PPC_OP(store_spr)
+void OPPROTO op_mask_spr (void)
 {
-    regs->spr[PARAM(1)] = T0;
+    env->spr[PARAM1] &= ~T0;
     RETURN();
 }
 
-PPC_OP(load_lr)
+void OPPROTO op_load_tbl (void)
 {
-    T0 = regs->lr;
+    T0 = cpu_ppc_load_tbl(env);
     RETURN();
 }
 
-PPC_OP(store_lr)
+void OPPROTO op_load_tbu (void)
 {
-    regs->lr = T0;
+    T0 = cpu_ppc_load_tbu(env);
     RETURN();
 }
 
-PPC_OP(load_ctr)
+void OPPROTO op_load_atbl (void)
 {
-    T0 = regs->ctr;
+    T0 = cpu_ppc_load_atbl(env);
     RETURN();
 }
 
-PPC_OP(store_ctr)
+void OPPROTO op_load_atbu (void)
 {
-    regs->ctr = T0;
+    T0 = cpu_ppc_load_atbu(env);
     RETURN();
 }
 
-PPC_OP(load_tbl)
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_store_tbl (void)
 {
-    T0 = cpu_ppc_load_tbl(regs);
+    cpu_ppc_store_tbl(env, T0);
     RETURN();
 }
 
-PPC_OP(load_tbu)
+void OPPROTO op_store_tbu (void)
 {
-    T0 = cpu_ppc_load_tbu(regs);
+    cpu_ppc_store_tbu(env, T0);
     RETURN();
 }
 
-#if !defined(CONFIG_USER_ONLY)
-PPC_OP(store_tbl)
+void OPPROTO op_store_atbl (void)
 {
-    cpu_ppc_store_tbl(regs, T0);
+    cpu_ppc_store_atbl(env, T0);
     RETURN();
 }
 
-PPC_OP(store_tbu)
+void OPPROTO op_store_atbu (void)
 {
-    cpu_ppc_store_tbu(regs, T0);
+    cpu_ppc_store_atbu(env, T0);
     RETURN();
 }
 
-PPC_OP(load_decr)
+void OPPROTO op_load_decr (void)
 {
-    T0 = cpu_ppc_load_decr(regs);
+    T0 = cpu_ppc_load_decr(env);
     RETURN();
 }
 
-PPC_OP(store_decr)
+void OPPROTO op_store_decr (void)
 {
-    cpu_ppc_store_decr(regs, T0);
+    cpu_ppc_store_decr(env, T0);
     RETURN();
 }
 
-PPC_OP(load_ibat)
+void OPPROTO op_load_ibat (void)
 {
-    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
+    T0 = env->IBAT[PARAM1][PARAM2];
     RETURN();
 }
 
@@ -450,9 +247,9 @@ void OPPROTO op_store_ibatl (void)
     RETURN();
 }
 
-PPC_OP(load_dbat)
+void OPPROTO op_load_dbat (void)
 {
-    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
+    T0 = env->DBAT[PARAM1][PARAM2];
     RETURN();
 }
 
@@ -474,85 +271,86 @@ void OPPROTO op_store_dbatl (void)
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 /* FPSCR */
-PPC_OP(load_fpscr)
+#ifdef CONFIG_SOFTFLOAT
+void OPPROTO op_reset_fpstatus (void)
 {
-    do_load_fpscr();
+    env->fp_status.float_exception_flags = 0;
     RETURN();
 }
+#endif
 
-PPC_OP(store_fpscr)
+void OPPROTO op_compute_fprf (void)
 {
-    do_store_fpscr(PARAM1);
+    do_compute_fprf(PARAM1);
     RETURN();
 }
 
-PPC_OP(reset_scrfx)
+#ifdef CONFIG_SOFTFLOAT
+void OPPROTO op_float_check_status (void)
 {
-    regs->fpscr[7] &= ~0x8;
+    do_float_check_status();
     RETURN();
 }
-
-/* crf operations */
-PPC_OP(getbit_T0)
+#else
+void OPPROTO op_float_check_status (void)
 {
-    T0 = (T0 >> PARAM(1)) & 1;
+    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
+        (env->error_code & POWERPC_EXCP_FP)) {
+        /* Differred floating-point exception after target FPR update */
+        if (msr_fe0 != 0 || msr_fe1 != 0)
+            do_raise_exception_err(env->exception_index, env->error_code);
+    }
     RETURN();
 }
+#endif
 
-PPC_OP(getbit_T1)
+void OPPROTO op_load_fpscr_FT0 (void)
 {
-    T1 = (T1 >> PARAM(1)) & 1;
-    RETURN();
-}
+    /* The 32 MSB of the target fpr are undefined.
+     * They'll be zero...
+     */
+    CPU_DoubleU u;
 
-PPC_OP(setcrfbit)
-{
-    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
+    u.l.upper = 0;
+    u.l.lower = env->fpscr;
+    FT0 = u.d;
     RETURN();
 }
 
-/* Branch */
-#define EIP regs->nip
-
-PPC_OP(setlr)
+void OPPROTO op_fpscr_resetbit (void)
 {
-    regs->lr = (uint32_t)PARAM1;
+    env->fpscr &= PARAM1;
     RETURN();
 }
 
-#if defined (TARGET_PPC64)
-void OPPROTO op_setlr_64 (void)
+void OPPROTO op_fpscr_setbit (void)
 {
-    regs->lr = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
+    do_fpscr_setbit(PARAM1);
     RETURN();
 }
-#endif
 
-PPC_OP(goto_tb0)
+void OPPROTO op_store_fpscr (void)
 {
-    GOTO_TB(op_goto_tb0, PARAM1, 0);
-}
-
-PPC_OP(goto_tb1)
-{
-    GOTO_TB(op_goto_tb1, PARAM1, 1);
+    do_store_fpscr(PARAM1);
+    RETURN();
 }
 
-void OPPROTO op_b_T1 (void)
+/* Branch */
+void OPPROTO op_setlr (void)
 {
-    regs->nip = (uint32_t)(T1 & ~3);
+    env->lr = (uint32_t)PARAM1;
     RETURN();
 }
 
 #if defined (TARGET_PPC64)
-void OPPROTO op_b_T1_64 (void)
+void OPPROTO op_setlr_64 (void)
 {
-    regs->nip = (uint64_t)(T1 & ~3);
+    env->lr = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
     RETURN();
 }
 #endif
 
-PPC_OP(jz_T0)
+void OPPROTO op_jz_T0 (void)
 {
     if (!T0)
         GOTO_LABEL_PARAM(1);
@@ -562,9 +360,9 @@ PPC_OP(jz_T0)
 void OPPROTO op_btest_T1 (void)
 {
     if (T0) {
-        regs->nip = (uint32_t)(T1 & ~3);
+        env->nip = (uint32_t)(T1 & ~3);
     } else {
-        regs->nip = (uint32_t)PARAM1;
+        env->nip = (uint32_t)PARAM1;
     }
     RETURN();
 }
@@ -573,159 +371,155 @@ void OPPROTO op_btest_T1 (void)
 void OPPROTO op_btest_T1_64 (void)
 {
     if (T0) {
-        regs->nip = (uint64_t)(T1 & ~3);
+        env->nip = (uint64_t)(T1 & ~3);
     } else {
-        regs->nip = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
+        env->nip = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
     }
     RETURN();
 }
 #endif
 
-PPC_OP(movl_T1_ctr)
+void OPPROTO op_movl_T1_ctr (void)
 {
-    T1 = regs->ctr;
+    T1 = env->ctr;
     RETURN();
 }
 
-PPC_OP(movl_T1_lr)
+void OPPROTO op_movl_T1_lr (void)
 {
-    T1 = regs->lr;
+    T1 = env->lr;
     RETURN();
 }
 
 /* tests with result in T0 */
 void OPPROTO op_test_ctr (void)
 {
-    T0 = (uint32_t)regs->ctr;
+    T0 = (uint32_t)env->ctr;
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_test_ctr_64 (void)
 {
-    T0 = (uint64_t)regs->ctr;
+    T0 = (uint64_t)env->ctr;
     RETURN();
 }
 #endif
 
 void OPPROTO op_test_ctr_true (void)
 {
-    T0 = ((uint32_t)regs->ctr != 0 && (T0 & PARAM1) != 0);
+    T0 = ((uint32_t)env->ctr != 0 && (T0 & PARAM1) != 0);
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_test_ctr_true_64 (void)
 {
-    T0 = ((uint64_t)regs->ctr != 0 && (T0 & PARAM1) != 0);
+    T0 = ((uint64_t)env->ctr != 0 && (T0 & PARAM1) != 0);
     RETURN();
 }
 #endif
 
 void OPPROTO op_test_ctr_false (void)
 {
-    T0 = ((uint32_t)regs->ctr != 0 && (T0 & PARAM1) == 0);
+    T0 = ((uint32_t)env->ctr != 0 && (T0 & PARAM1) == 0);
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_test_ctr_false_64 (void)
 {
-    T0 = ((uint64_t)regs->ctr != 0 && (T0 & PARAM1) == 0);
+    T0 = ((uint64_t)env->ctr != 0 && (T0 & PARAM1) == 0);
     RETURN();
 }
 #endif
 
 void OPPROTO op_test_ctrz (void)
 {
-    T0 = ((uint32_t)regs->ctr == 0);
+    T0 = ((uint32_t)env->ctr == 0);
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_test_ctrz_64 (void)
 {
-    T0 = ((uint64_t)regs->ctr == 0);
+    T0 = ((uint64_t)env->ctr == 0);
     RETURN();
 }
 #endif
 
 void OPPROTO op_test_ctrz_true (void)
 {
-    T0 = ((uint32_t)regs->ctr == 0 && (T0 & PARAM1) != 0);
+    T0 = ((uint32_t)env->ctr == 0 && (T0 & PARAM1) != 0);
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_test_ctrz_true_64 (void)
 {
-    T0 = ((uint64_t)regs->ctr == 0 && (T0 & PARAM1) != 0);
+    T0 = ((uint64_t)env->ctr == 0 && (T0 & PARAM1) != 0);
     RETURN();
 }
 #endif
 
 void OPPROTO op_test_ctrz_false (void)
 {
-    T0 = ((uint32_t)regs->ctr == 0 && (T0 & PARAM1) == 0);
+    T0 = ((uint32_t)env->ctr == 0 && (T0 & PARAM1) == 0);
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_test_ctrz_false_64 (void)
 {
-    T0 = ((uint64_t)regs->ctr == 0 && (T0 & PARAM1) == 0);
+    T0 = ((uint64_t)env->ctr == 0 && (T0 & PARAM1) == 0);
     RETURN();
 }
 #endif
 
-PPC_OP(test_true)
+void OPPROTO op_test_true (void)
 {
-    T0 = (T0 & PARAM(1));
+    T0 = (T0 & PARAM1);
     RETURN();
 }
 
-PPC_OP(test_false)
+void OPPROTO op_test_false (void)
 {
-    T0 = ((T0 & PARAM(1)) == 0);
+    T0 = ((T0 & PARAM1) == 0);
     RETURN();
 }
 
 /* CTR maintenance */
-PPC_OP(dec_ctr)
+void OPPROTO op_dec_ctr (void)
 {
-    regs->ctr--;
+    env->ctr--;
     RETURN();
 }
 
 /***                           Integer arithmetic                          ***/
 /* add */
-PPC_OP(add)
-{
-    T0 += T1;
-    RETURN();
-}
-
 void OPPROTO op_check_addo (void)
 {
-    if (likely(!(((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
-                 ((uint32_t)T2 ^ (uint32_t)T0) & (1UL << 31)))) {
-        xer_ov = 0;
+    int ov = (((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
+              ((uint32_t)T2 ^ (uint32_t)T0)) >> 31;
+    if (ov) {
+        env->xer |= (1 << XER_OV) | (1 << XER_SO);
     } else {
-        xer_so = 1;
-        xer_ov = 1;
+        env->xer &= ~(1 << XER_OV);
     }
+    RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_check_addo_64 (void)
 {
-    if (likely(!(((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
-                 ((uint64_t)T2 ^ (uint64_t)T0) & (1ULL << 63)))) {
-        xer_ov = 0;
+    int ov = (((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
+              ((uint64_t)T2 ^ (uint64_t)T0)) >> 63;
+    if (ov) {
+        env->xer |= (1 << XER_OV) | (1 << XER_SO);
     } else {
-        xer_so = 1;
-        xer_ov = 1;
+        env->xer &= ~(1 << XER_OV);
     }
+    RETURN();
 }
 #endif
 
@@ -733,9 +527,9 @@ void OPPROTO op_check_addo_64 (void)
 void OPPROTO op_check_addc (void)
 {
     if (likely((uint32_t)T0 >= (uint32_t)T2)) {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     } else {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     }
     RETURN();
 }
@@ -744,9 +538,9 @@ void OPPROTO op_check_addc (void)
 void OPPROTO op_check_addc_64 (void)
 {
     if (likely((uint64_t)T0 >= (uint64_t)T2)) {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     } else {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     }
     RETURN();
 }
@@ -767,19 +561,12 @@ void OPPROTO op_adde_64 (void)
 }
 #endif
 
-/* add immediate */
-PPC_OP(addi)
-{
-    T0 += PARAM(1);
-    RETURN();
-}
-
 /* add to minus one extended */
 void OPPROTO op_add_me (void)
 {
     T0 += xer_ca + (-1);
     if (likely((uint32_t)T1 != 0))
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     RETURN();
 }
 
@@ -788,7 +575,7 @@ void OPPROTO op_add_me_64 (void)
 {
     T0 += xer_ca + (-1);
     if (likely((uint64_t)T1 != 0))
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     RETURN();
 }
 #endif
@@ -815,9 +602,9 @@ void OPPROTO op_add_ze (void)
 /* divide word */
 void OPPROTO op_divw (void)
 {
-    if (unlikely(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
+    if (unlikely(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
                  (int32_t)T1 == 0)) {
-        T0 = (int32_t)((-1) * ((uint32_t)T0 >> 31));
+        T0 = (int32_t)(UINT32_MAX * ((uint32_t)T0 >> 31));
     } else {
         T0 = (int32_t)T0 / (int32_t)T1;
     }
@@ -827,9 +614,9 @@ void OPPROTO op_divw (void)
 #if defined(TARGET_PPC64)
 void OPPROTO op_divd (void)
 {
-    if (unlikely(((int64_t)T0 == INT64_MIN && (int64_t)T1 == -1) ||
+    if (unlikely(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) ||
                  (int64_t)T1 == 0)) {
-        T0 = (int64_t)((-1ULL) * ((uint64_t)T0 >> 63));
+        T0 = (int64_t)(UINT64_MAX * ((uint64_t)T0 >> 63));
     } else {
         T0 = (int64_t)T0 / (int64_t)T1;
     }
@@ -900,7 +687,7 @@ void OPPROTO op_mulhd (void)
 {
     uint64_t tl, th;
 
-    do_imul64(&tl, &th);
+    muls64(&tl, &th, T0, T1);
     T0 = th;
     RETURN();
 }
@@ -918,23 +705,27 @@ void OPPROTO op_mulhdu (void)
 {
     uint64_t tl, th;
 
-    do_mul64(&tl, &th);
+    mulu64(&tl, &th, T0, T1);
     T0 = th;
     RETURN();
 }
 #endif
 
 /* multiply low immediate */
-PPC_OP(mulli)
+void OPPROTO op_mulli (void)
 {
     T0 = ((int32_t)T0 * (int32_t)PARAM1);
     RETURN();
 }
 
 /* multiply low word */
-PPC_OP(mullw)
+void OPPROTO op_mullw (void)
 {
+#if defined(TARGET_PPC64)
+    T0 = (int64_t)(int32_t)T0 * (int64_t)(int32_t)T1;
+#else
     T0 = (int32_t)(T0 * T1);
+#endif
     RETURN();
 }
 
@@ -993,46 +784,13 @@ void OPPROTO op_nego_64 (void)
 }
 #endif
 
-/* substract from */
-PPC_OP(subf)
-{
-    T0 = T1 - T0;
-    RETURN();
-}
-
-void OPPROTO op_check_subfo (void)
-{
-    if (likely(!(((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
-                 ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_so = 1;
-        xer_ov = 1;
-    }
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_check_subfo_64 (void)
-{
-    if (likely(!(((uint64_t)(~T2) ^ (uint64_t)T1 ^ UINT64_MAX) &
-                 ((uint64_t)(~T2) ^ (uint64_t)T0) & (1ULL << 63)))) {
-        xer_ov = 0;
-    } else {
-        xer_so = 1;
-        xer_ov = 1;
-    }
-    RETURN();
-}
-#endif
-
-/* substract from carrying */
+/* subtract from carrying */
 void OPPROTO op_check_subfc (void)
 {
     if (likely((uint32_t)T0 > (uint32_t)T1)) {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     } else {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     }
     RETURN();
 }
@@ -1041,15 +799,15 @@ void OPPROTO op_check_subfc (void)
 void OPPROTO op_check_subfc_64 (void)
 {
     if (likely((uint64_t)T0 > (uint64_t)T1)) {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     } else {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     }
     RETURN();
 }
 #endif
 
-/* substract from extended */
+/* subtract from extended */
 void OPPROTO op_subfe (void)
 {
     do_subfe();
@@ -1064,14 +822,14 @@ void OPPROTO op_subfe_64 (void)
 }
 #endif
 
-/* substract from immediate carrying */
+/* subtract from immediate carrying */
 void OPPROTO op_subfic (void)
 {
-    T0 = PARAM1 + ~T0 + 1;
+    T0 = (int32_t)PARAM1 + ~T0 + 1;
     if ((uint32_t)T0 <= (uint32_t)PARAM1) {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     } else {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     }
     RETURN();
 }
@@ -1079,22 +837,22 @@ void OPPROTO op_subfic (void)
 #if defined(TARGET_PPC64)
 void OPPROTO op_subfic_64 (void)
 {
-    T0 = PARAM1 + ~T0 + 1;
+    T0 = (int64_t)PARAM1 + ~T0 + 1;
     if ((uint64_t)T0 <= (uint64_t)PARAM1) {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     } else {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     }
     RETURN();
 }
 #endif
 
-/* substract from minus one extended */
+/* subtract from minus one extended */
 void OPPROTO op_subfme (void)
 {
     T0 = ~T0 + xer_ca - 1;
-    if (likely((uint32_t)T0 != (uint32_t)-1))
-        xer_ca = 1;
+    if (likely((uint32_t)T0 != UINT32_MAX))
+        env->xer |= (1 << XER_CA);
     RETURN();
 }
 
@@ -1102,8 +860,8 @@ void OPPROTO op_subfme (void)
 void OPPROTO op_subfme_64 (void)
 {
     T0 = ~T0 + xer_ca - 1;
-    if (likely((uint64_t)T0 != (uint64_t)-1))
-        xer_ca = 1;
+    if (likely((uint64_t)T0 != UINT64_MAX))
+        env->xer |= (1 << XER_CA);
     RETURN();
 }
 #endif
@@ -1122,15 +880,15 @@ void OPPROTO op_subfmeo_64 (void)
 }
 #endif
 
-/* substract from zero extended */
+/* subtract from zero extended */
 void OPPROTO op_subfze (void)
 {
     T1 = ~T0;
     T0 = T1 + xer_ca;
     if ((uint32_t)T0 < (uint32_t)T1) {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     } else {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     }
     RETURN();
 }
@@ -1141,9 +899,9 @@ void OPPROTO op_subfze_64 (void)
     T1 = ~T0;
     T0 = T1 + xer_ca;
     if ((uint64_t)T0 < (uint64_t)T1) {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     } else {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     }
     RETURN();
 }
@@ -1163,124 +921,6 @@ void OPPROTO op_subfzeo_64 (void)
 }
 #endif
 
-/***                           Integer comparison                          ***/
-/* compare */
-void OPPROTO op_cmp (void)
-{
-    if ((int32_t)T0 < (int32_t)T1) {
-        T0 = 0x08;
-    } else if ((int32_t)T0 > (int32_t)T1) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_cmp_64 (void)
-{
-    if ((int64_t)T0 < (int64_t)T1) {
-        T0 = 0x08;
-    } else if ((int64_t)T0 > (int64_t)T1) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-#endif
-
-/* compare immediate */
-void OPPROTO op_cmpi (void)
-{
-    if ((int32_t)T0 < (int32_t)PARAM1) {
-        T0 = 0x08;
-    } else if ((int32_t)T0 > (int32_t)PARAM1) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_cmpi_64 (void)
-{
-    if ((int64_t)T0 < (int64_t)((int32_t)PARAM1)) {
-        T0 = 0x08;
-    } else if ((int64_t)T0 > (int64_t)((int32_t)PARAM1)) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-#endif
-
-/* compare logical */
-void OPPROTO op_cmpl (void)
-{
-    if ((uint32_t)T0 < (uint32_t)T1) {
-        T0 = 0x08;
-    } else if ((uint32_t)T0 > (uint32_t)T1) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_cmpl_64 (void)
-{
-    if ((uint64_t)T0 < (uint64_t)T1) {
-        T0 = 0x08;
-    } else if ((uint64_t)T0 > (uint64_t)T1) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-#endif
-
-/* compare logical immediate */
-void OPPROTO op_cmpli (void)
-{
-    if ((uint32_t)T0 < (uint32_t)PARAM1) {
-        T0 = 0x08;
-    } else if ((uint32_t)T0 > (uint32_t)PARAM1) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_cmpli_64 (void)
-{
-    if ((uint64_t)T0 < (uint64_t)PARAM1) {
-        T0 = 0x08;
-    } else if ((uint64_t)T0 > (uint64_t)PARAM1) {
-        T0 = 0x04;
-    } else {
-        T0 = 0x02;
-    }
-    RETURN();
-}
-#endif
-
-void OPPROTO op_isel (void)
-{
-    if (T0)
-        T0 = T1;
-    else
-        T0 = T2;
-    RETURN();
-}
-
 void OPPROTO op_popcntb (void)
 {
     do_popcntb();
@@ -1297,49 +937,36 @@ void OPPROTO op_popcntb_64 (void)
 
 /***                            Integer logical                            ***/
 /* and */
-PPC_OP(and)
+void OPPROTO op_and (void)
 {
     T0 &= T1;
     RETURN();
 }
 
 /* andc */
-PPC_OP(andc)
+void OPPROTO op_andc (void)
 {
     T0 &= ~T1;
     RETURN();
 }
 
-/* andi. */
-void OPPROTO op_andi_T0 (void)
-{
-    T0 &= PARAM(1);
-    RETURN();
-}
-
-void OPPROTO op_andi_T1 (void)
-{
-    T1 &= PARAM1;
-    RETURN();
-}
-
 /* count leading zero */
 void OPPROTO op_cntlzw (void)
 {
-    T0 = _do_cntlzw(T0);
+    do_cntlzw();
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_cntlzd (void)
 {
-    T0 = _do_cntlzd(T0);
+    do_cntlzd();
     RETURN();
 }
 #endif
 
 /* eqv */
-PPC_OP(eqv)
+void OPPROTO op_eqv (void)
 {
     T0 = ~(T0 ^ T1);
     RETURN();
@@ -1376,51 +1003,51 @@ void OPPROTO op_extsw (void)
 #endif
 
 /* nand */
-PPC_OP(nand)
+void OPPROTO op_nand (void)
 {
     T0 = ~(T0 & T1);
     RETURN();
 }
 
 /* nor */
-PPC_OP(nor)
+void OPPROTO op_nor (void)
 {
     T0 = ~(T0 | T1);
     RETURN();
 }
 
 /* or */
-PPC_OP(or)
+void OPPROTO op_or (void)
 {
     T0 |= T1;
     RETURN();
 }
 
 /* orc */
-PPC_OP(orc)
+void OPPROTO op_orc (void)
 {
     T0 |= ~T1;
     RETURN();
 }
 
 /* ori */
-PPC_OP(ori)
+void OPPROTO op_ori (void)
 {
-    T0 |= PARAM(1);
+    T0 |= (uint32_t)PARAM1;
     RETURN();
 }
 
 /* xor */
-PPC_OP(xor)
+void OPPROTO op_xor (void)
 {
     T0 ^= T1;
     RETURN();
 }
 
 /* xori */
-PPC_OP(xori)
+void OPPROTO op_xori (void)
 {
-    T0 ^= PARAM(1);
+    T0 ^= (uint32_t)PARAM1;
     RETURN();
 }
 
@@ -1437,6 +1064,20 @@ void OPPROTO op_rotli32_T0 (void)
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_rotl64_T0_T1 (void)
+{
+    T0 = rotl64(T0, T1 & 0x3F);
+    RETURN();
+}
+
+void OPPROTO op_rotli64_T0 (void)
+{
+    T0 = rotl64(T0, PARAM1);
+    RETURN();
+}
+#endif
+
 /***                             Integer shift                             ***/
 /* shift left word */
 void OPPROTO op_slw (void)
@@ -1483,9 +1124,9 @@ void OPPROTO op_srawi (void)
 
     T0 = (int32_t)T0 >> PARAM1;
     if ((int32_t)T1 < 0 && (T1 & mask) != 0) {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     } else {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     }
     RETURN();
 }
@@ -1497,9 +1138,9 @@ void OPPROTO op_sradi (void)
 
     T0 = (int64_t)T0 >> PARAM1;
     if ((int64_t)T1 < 0 && ((uint64_t)T1 & mask) != 0) {
-        xer_ca = 1;
+        env->xer |= (1 << XER_CA);
     } else {
-        xer_ca = 0;
+        env->xer &= ~(1 << XER_CA);
     }
     RETURN();
 }
@@ -1584,56 +1225,79 @@ void OPPROTO op_srli_T1_64 (void)
 
 /***                       Floating-Point arithmetic                       ***/
 /* fadd - fadd. */
-PPC_OP(fadd)
+void OPPROTO op_fadd (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fadd();
+#else
     FT0 = float64_add(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fsub - fsub. */
-PPC_OP(fsub)
+void OPPROTO op_fsub (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fsub();
+#else
     FT0 = float64_sub(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fmul - fmul. */
-PPC_OP(fmul)
+void OPPROTO op_fmul (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fmul();
+#else
     FT0 = float64_mul(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fdiv - fdiv. */
-PPC_OP(fdiv)
+void OPPROTO op_fdiv (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fdiv();
+#else
     FT0 = float64_div(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fsqrt - fsqrt. */
-PPC_OP(fsqrt)
+void OPPROTO op_fsqrt (void)
 {
     do_fsqrt();
     RETURN();
 }
 
+/* fre - fre. */
+void OPPROTO op_fre (void)
+{
+    do_fre();
+    RETURN();
+}
+
 /* fres - fres. */
-PPC_OP(fres)
+void OPPROTO op_fres (void)
 {
     do_fres();
     RETURN();
 }
 
 /* frsqrte  - frsqrte. */
-PPC_OP(frsqrte)
+void OPPROTO op_frsqrte (void)
 {
     do_frsqrte();
     RETURN();
 }
 
 /* fsel - fsel. */
-PPC_OP(fsel)
+void OPPROTO op_fsel (void)
 {
     do_fsel();
     RETURN();
@@ -1641,30 +1305,38 @@ PPC_OP(fsel)
 
 /***                     Floating-Point multiply-and-add                   ***/
 /* fmadd - fmadd. */
-PPC_OP(fmadd)
+void OPPROTO op_fmadd (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fmadd();
+#else
     FT0 = float64_mul(FT0, FT1, &env->fp_status);
     FT0 = float64_add(FT0, FT2, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fmsub - fmsub. */
-PPC_OP(fmsub)
+void OPPROTO op_fmsub (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fmsub();
+#else
     FT0 = float64_mul(FT0, FT1, &env->fp_status);
     FT0 = float64_sub(FT0, FT2, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
-PPC_OP(fnmadd)
+void OPPROTO op_fnmadd (void)
 {
     do_fnmadd();
     RETURN();
 }
 
 /* fnmsub - fnmsub. */
-PPC_OP(fnmsub)
+void OPPROTO op_fnmsub (void)
 {
     do_fnmsub();
     RETURN();
@@ -1672,51 +1344,87 @@ PPC_OP(fnmsub)
 
 /***                     Floating-Point round & convert                    ***/
 /* frsp - frsp. */
-PPC_OP(frsp)
+void OPPROTO op_frsp (void)
 {
+#if USE_PRECISE_EMULATION
+    do_frsp();
+#else
     FT0 = float64_to_float32(FT0, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fctiw - fctiw. */
-PPC_OP(fctiw)
+void OPPROTO op_fctiw (void)
 {
     do_fctiw();
     RETURN();
 }
 
 /* fctiwz - fctiwz. */
-PPC_OP(fctiwz)
+void OPPROTO op_fctiwz (void)
 {
     do_fctiwz();
     RETURN();
 }
 
-/***                         Floating-Point compare                        ***/
-/* fcmpu */
-PPC_OP(fcmpu)
+#if defined(TARGET_PPC64)
+/* fcfid - fcfid. */
+void OPPROTO op_fcfid (void)
+{
+    do_fcfid();
+    RETURN();
+}
+
+/* fctid - fctid. */
+void OPPROTO op_fctid (void)
+{
+    do_fctid();
+    RETURN();
+}
+
+/* fctidz - fctidz. */
+void OPPROTO op_fctidz (void)
+{
+    do_fctidz();
+    RETURN();
+}
+#endif
+
+void OPPROTO op_frin (void)
+{
+    do_frin();
+    RETURN();
+}
+
+void OPPROTO op_friz (void)
 {
-    do_fcmpu();
+    do_friz();
     RETURN();
 }
 
-/* fcmpo */
-PPC_OP(fcmpo)
+void OPPROTO op_frip (void)
 {
-    do_fcmpo();
+    do_frip();
+    RETURN();
+}
+
+void OPPROTO op_frim (void)
+{
+    do_frim();
     RETURN();
 }
 
 /***                         Floating-point move                           ***/
 /* fabs */
-PPC_OP(fabs)
+void OPPROTO op_fabs (void)
 {
     FT0 = float64_abs(FT0);
     RETURN();
 }
 
 /* fnabs */
-PPC_OP(fnabs)
+void OPPROTO op_fnabs (void)
 {
     FT0 = float64_abs(FT0);
     FT0 = float64_chs(FT0);
@@ -1724,7 +1432,7 @@ PPC_OP(fnabs)
 }
 
 /* fneg */
-PPC_OP(fneg)
+void OPPROTO op_fneg (void)
 {
     FT0 = float64_chs(FT0);
     RETURN();
@@ -1741,13 +1449,16 @@ PPC_OP(fneg)
 #define MEMSUFFIX _kernel
 #include "op_helper.h"
 #include "op_mem.h"
+#define MEMSUFFIX _hypv
+#include "op_helper.h"
+#include "op_mem.h"
 #endif
 
 /* Special op to check and maybe clear reservation */
 void OPPROTO op_check_reservation (void)
 {
     if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
-        env->reserve = -1;
+        env->reserve = (target_ulong)-1ULL;
     RETURN();
 }
 
@@ -1755,11 +1466,17 @@ void OPPROTO op_check_reservation (void)
 void OPPROTO op_check_reservation_64 (void)
 {
     if ((uint64_t)env->reserve == (uint64_t)(T0 & ~0x00000003))
-        env->reserve = -1;
+        env->reserve = (target_ulong)-1ULL;
     RETURN();
 }
 #endif
 
+void OPPROTO op_wait (void)
+{
+    env->halted = 1;
+    RETURN();
+}
+
 /* Return from interrupt */
 #if !defined(CONFIG_USER_ONLY)
 void OPPROTO op_rfi (void)
@@ -1769,12 +1486,33 @@ void OPPROTO op_rfi (void)
 }
 
 #if defined(TARGET_PPC64)
-void OPPROTO op_rfi_32 (void)
+void OPPROTO op_rfid (void)
 {
-    do_rfi_32();
+    do_rfid();
+    RETURN();
+}
+
+void OPPROTO op_hrfid (void)
+{
+    do_hrfid();
     RETURN();
 }
 #endif
+
+/* Exception vectors */
+void OPPROTO op_store_excp_prefix (void)
+{
+    T0 &= env->ivpr_mask;
+    env->excp_prefix = T0;
+    RETURN();
+}
+
+void OPPROTO op_store_excp_vector (void)
+{
+    T0 &= env->ivor_mask;
+    env->excp_vectors[PARAM1] = T0;
+    RETURN();
+}
 #endif
 
 /* Trap word */
@@ -1794,23 +1532,23 @@ void OPPROTO op_td (void)
 
 #if !defined(CONFIG_USER_ONLY)
 /* tlbia */
-PPC_OP(tlbia)
+void OPPROTO op_tlbia (void)
 {
-    do_tlbia();
+    ppc_tlb_invalidate_all(env);
     RETURN();
 }
 
 /* tlbie */
 void OPPROTO op_tlbie (void)
 {
-    do_tlbie();
+    ppc_tlb_invalidate_one(env, (uint32_t)T0);
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_tlbie_64 (void)
 {
-    do_tlbie_64();
+    ppc_tlb_invalidate_one(env, T0);
     RETURN();
 }
 #endif
@@ -1818,20 +1556,26 @@ void OPPROTO op_tlbie_64 (void)
 #if defined(TARGET_PPC64)
 void OPPROTO op_slbia (void)
 {
-    do_slbia();
+    ppc_slb_invalidate_all(env);
     RETURN();
 }
 
 void OPPROTO op_slbie (void)
 {
-    do_slbie();
+    ppc_slb_invalidate_one(env, (uint32_t)T0);
+    RETURN();
+}
+
+void OPPROTO op_slbie_64 (void)
+{
+    ppc_slb_invalidate_one(env, T0);
     RETURN();
 }
 #endif
 #endif
 
-/* PowerPC 602/603/755 software TLB load instructions */
 #if !defined(CONFIG_USER_ONLY)
+/* PowerPC 602/603/755 software TLB load instructions */
 void OPPROTO op_6xx_tlbld (void)
 {
     do_load_6xx_tlb(0);
@@ -1843,6 +1587,19 @@ void OPPROTO op_6xx_tlbli (void)
     do_load_6xx_tlb(1);
     RETURN();
 }
+
+/* PowerPC 74xx software TLB load instructions */
+void OPPROTO op_74xx_tlbld (void)
+{
+    do_load_74xx_tlb(0);
+    RETURN();
+}
+
+void OPPROTO op_74xx_tlbli (void)
+{
+    do_load_74xx_tlb(1);
+    RETURN();
+}
 #endif
 
 /* 601 specific */
@@ -1871,30 +1628,27 @@ void OPPROTO op_store_601_rtcu (void)
     RETURN();
 }
 
+void OPPROTO op_store_hid0_601 (void)
+{
+    do_store_hid0_601();
+    RETURN();
+}
+
 void OPPROTO op_load_601_bat (void)
 {
     T0 = env->IBAT[PARAM1][PARAM2];
     RETURN();
 }
-#endif /* !defined(CONFIG_USER_ONLY) */
 
-/* 601 unified BATs store.
- * To avoid using specific MMU code for 601, we store BATs in
- * IBAT and DBAT simultaneously, then emulate unified BATs.
- */
-#if !defined(CONFIG_USER_ONLY)
 void OPPROTO op_store_601_batl (void)
 {
-    int nr = PARAM1;
-
-    env->IBAT[1][nr] = T0;
-    env->DBAT[1][nr] = T0;
+    do_store_ibatl_601(env, PARAM1, T0);
     RETURN();
 }
 
 void OPPROTO op_store_601_batu (void)
 {
-    do_store_601_batu(PARAM1);
+    do_store_ibatu_601(env, PARAM1, T0);
     RETURN();
 }
 #endif /* !defined(CONFIG_USER_ONLY) */
@@ -1903,9 +1657,9 @@ void OPPROTO op_store_601_batu (void)
 /* XXX: those micro-ops need tests ! */
 void OPPROTO op_POWER_abs (void)
 {
-    if (T0 == INT32_MIN)
+    if ((int32_t)T0 == INT32_MIN)
         T0 = INT32_MAX;
-    else if (T0 < 0)
+    else if ((int32_t)T0 < 0)
         T0 = -T0;
     RETURN();
 }
@@ -2007,7 +1761,7 @@ void OPPROTO op_POWER_nabso (void)
     /* nabs never overflows */
     if (T0 > 0)
         T0 = -T0;
-    xer_ov = 0;
+    env->xer &= ~(1 << XER_OV);
     RETURN();
 }
 
@@ -2015,7 +1769,7 @@ void OPPROTO op_POWER_nabso (void)
 void OPPROTO op_POWER_rlmi (void)
 {
     T0 = rotl32(T0, T2) & PARAM1;
-    T0 |= T1 & PARAM2;
+    T0 |= T1 & (uint32_t)PARAM2;
     RETURN();
 }
 
@@ -2048,7 +1802,7 @@ void OPPROTO op_POWER_sleq (void)
 
 void OPPROTO op_POWER_sllq (void)
 {
-    uint32_t msk = -1;
+    uint32_t msk = UINT32_MAX;
 
     msk = msk << (T1 & 0x1FUL);
     if (T1 & 0x20UL)
@@ -2061,7 +1815,7 @@ void OPPROTO op_POWER_sllq (void)
 
 void OPPROTO op_POWER_slq (void)
 {
-    uint32_t msk = -1, tmp;
+    uint32_t msk = UINT32_MAX, tmp;
 
     msk = msk << (T1 & 0x1FUL);
     if (T1 & 0x20UL)
@@ -2077,7 +1831,7 @@ void OPPROTO op_POWER_sraq (void)
 {
     env->spr[SPR_MQ] = rotl32(T0, 32 - (T1 & 0x1FUL));
     if (T1 & 0x20UL)
-        T0 = -1L;
+        T0 = UINT32_MAX;
     else
         T0 = (int32_t)T0 >> T1;
     RETURN();
@@ -2212,12 +1966,6 @@ void OPPROTO op_405_mullhwu (void)
     RETURN();
 }
 
-void OPPROTO op_405_check_ov (void)
-{
-    do_405_check_ov();
-    RETURN();
-}
-
 void OPPROTO op_405_check_sat (void)
 {
     do_405_check_sat();
@@ -2227,10 +1975,9 @@ void OPPROTO op_405_check_sat (void)
 void OPPROTO op_405_check_ovu (void)
 {
     if (likely(T0 >= T2)) {
-        xer_ov = 0;
+        env->xer &= ~(1 << XER_OV);
     } else {
-        xer_ov = 1;
-        xer_so = 1;
+        env->xer |= (1 << XER_OV) | (1 << XER_SO);
     }
     RETURN();
 }
@@ -2239,36 +1986,88 @@ void OPPROTO op_405_check_satu (void)
 {
     if (unlikely(T0 < T2)) {
         /* Saturate result */
-        T0 = -1;
+        T0 = UINT32_MAX;
     }
     RETURN();
 }
 
-#if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_4xx_load_dcr (void)
+void OPPROTO op_load_dcr (void)
 {
-    do_4xx_load_dcr(PARAM1);
+    do_load_dcr();
     RETURN();
 }
 
-void OPPROTO op_4xx_store_dcr (void)
+void OPPROTO op_store_dcr (void)
 {
-    do_4xx_store_dcr(PARAM1);
+    do_store_dcr();
     RETURN();
 }
 
+#if !defined(CONFIG_USER_ONLY)
 /* Return from critical interrupt :
  * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
  */
-void OPPROTO op_4xx_rfci (void)
+void OPPROTO op_40x_rfci (void)
+{
+    do_40x_rfci();
+    RETURN();
+}
+
+void OPPROTO op_rfci (void)
+{
+    do_rfci();
+    RETURN();
+}
+
+void OPPROTO op_rfdi (void)
+{
+    do_rfdi();
+    RETURN();
+}
+
+void OPPROTO op_rfmci (void)
+{
+    do_rfmci();
+    RETURN();
+}
+
+void OPPROTO op_wrte (void)
+{
+    /* We don't call do_store_msr here as we won't trigger
+     * any special case nor change hflags
+     */
+    T0 &= 1 << MSR_EE;
+    env->msr &= ~(1 << MSR_EE);
+    env->msr |= T0;
+    RETURN();
+}
+
+void OPPROTO op_440_tlbre (void)
+{
+    do_440_tlbre(PARAM1);
+    RETURN();
+}
+
+void OPPROTO op_440_tlbsx (void)
 {
-    do_4xx_rfci();
+    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
     RETURN();
 }
 
-void OPPROTO op_4xx_wrte (void)
+void OPPROTO op_4xx_tlbsx_check (void)
 {
-    msr_ee = T0 >> 16;
+    int tmp;
+
+    tmp = xer_so;
+    if ((int)T0 != -1)
+        tmp |= 0x02;
+    env->crf[0] = tmp;
+    RETURN();
+}
+
+void OPPROTO op_440_tlbwe (void)
+{
+    do_440_tlbwe(PARAM1);
     RETURN();
 }
 
@@ -2286,13 +2085,7 @@ void OPPROTO op_4xx_tlbre_hi (void)
 
 void OPPROTO op_4xx_tlbsx (void)
 {
-    do_4xx_tlbsx();
-    RETURN();
-}
-
-void OPPROTO op_4xx_tlbsx_ (void)
-{
-    do_4xx_tlbsx_();
+    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
     RETURN();
 }
 
@@ -2359,6 +2152,18 @@ void OPPROTO op_store_40x_pit (void)
     RETURN();
 }
 
+void OPPROTO op_store_40x_dbcr0 (void)
+{
+    store_40x_dbcr0(env, T0);
+    RETURN();
+}
+
+void OPPROTO op_store_40x_sler (void)
+{
+    store_40x_sler(env, T0);
+    RETURN();
+}
+
 void OPPROTO op_store_booke_tcr (void)
 {
     store_booke_tcr(env, T0);
@@ -2370,14 +2175,13 @@ void OPPROTO op_store_booke_tsr (void)
     store_booke_tsr(env, T0);
     RETURN();
 }
-
 #endif /* !defined(CONFIG_USER_ONLY) */
 
-#if defined(TARGET_PPCSPE)
 /* SPE extension */
 void OPPROTO op_splatw_T1_64 (void)
 {
     T1_64 = (T1_64 << 32) | (T1_64 & 0x00000000FFFFFFFFULL);
+    RETURN();
 }
 
 void OPPROTO op_splatwi_T0_64 (void)
@@ -2385,6 +2189,7 @@ void OPPROTO op_splatwi_T0_64 (void)
     uint64_t tmp = PARAM1;
 
     T0_64 = (tmp << 32) | tmp;
+    RETURN();
 }
 
 void OPPROTO op_splatwi_T1_64 (void)
@@ -2392,6 +2197,7 @@ void OPPROTO op_splatwi_T1_64 (void)
     uint64_t tmp = PARAM1;
 
     T1_64 = (tmp << 32) | tmp;
+    RETURN();
 }
 
 void OPPROTO op_extsh_T1_64 (void)
@@ -2486,54 +2292,6 @@ void OPPROTO op_evcntlsw (void)
     RETURN();
 }
 
-void OPPROTO op_evand (void)
-{
-    T0_64 &= T1_64;
-    RETURN();
-}
-
-void OPPROTO op_evandc (void)
-{
-    T0_64 &= ~T1_64;
-    RETURN();
-}
-
-void OPPROTO op_evor (void)
-{
-    T0_64 |= T1_64;
-    RETURN();
-}
-
-void OPPROTO op_evxor (void)
-{
-    T0_64 ^= T1_64;
-    RETURN();
-}
-
-void OPPROTO op_eveqv (void)
-{
-    T0_64 = ~(T0_64 ^ T1_64);
-    RETURN();
-}
-
-void OPPROTO op_evnor (void)
-{
-    T0_64 = ~(T0_64 | T1_64);
-    RETURN();
-}
-
-void OPPROTO op_evorc (void)
-{
-    T0_64 |= ~T1_64;
-    RETURN();
-}
-
-void OPPROTO op_evnand (void)
-{
-    T0_64 = ~(T0_64 & T1_64);
-    RETURN();
-}
-
 void OPPROTO op_evsrws (void)
 {
     do_evsrws();
@@ -2896,27 +2654,21 @@ void OPPROTO op_efststeq (void)
 
 void OPPROTO op_efdsub (void)
 {
-    union {
-        uint64_t u;
-        float64 f;
-    } u1, u2;
-    u1.u = T0_64;
-    u2.u = T1_64;
-    u1.f = float64_sub(u1.f, u2.f, &env->spe_status);
-    T0_64 = u1.u;
+    CPU_DoubleU u1, u2;
+    u1.ll = T0_64;
+    u2.ll = T1_64;
+    u1.d = float64_sub(u1.d, u2.d, &env->spe_status);
+    T0_64 = u1.ll;
     RETURN();
 }
 
 void OPPROTO op_efdadd (void)
 {
-    union {
-        uint64_t u;
-        float64 f;
-    } u1, u2;
-    u1.u = T0_64;
-    u2.u = T1_64;
-    u1.f = float64_add(u1.f, u2.f, &env->spe_status);
-    T0_64 = u1.u;
+    CPU_DoubleU u1, u2;
+    u1.ll = T0_64;
+    u2.ll = T1_64;
+    u1.d = float64_add(u1.d, u2.d, &env->spe_status);
+    T0_64 = u1.ll;
     RETURN();
 }
 
@@ -2952,27 +2704,21 @@ void OPPROTO op_efdneg (void)
 
 void OPPROTO op_efddiv (void)
 {
-    union {
-        uint64_t u;
-        float64 f;
-    } u1, u2;
-    u1.u = T0_64;
-    u2.u = T1_64;
-    u1.f = float64_div(u1.f, u2.f, &env->spe_status);
-    T0_64 = u1.u;
+    CPU_DoubleU u1, u2;
+    u1.ll = T0_64;
+    u2.ll = T1_64;
+    u1.d = float64_div(u1.d, u2.d, &env->spe_status);
+    T0_64 = u1.ll;
     RETURN();
 }
 
 void OPPROTO op_efdmul (void)
 {
-    union {
-        uint64_t u;
-        float64 f;
-    } u1, u2;
-    u1.u = T0_64;
-    u2.u = T1_64;
-    u1.f = float64_mul(u1.f, u2.f, &env->spe_status);
-    T0_64 = u1.u;
+    CPU_DoubleU u1, u2;
+    u1.ll = T0_64;
+    u2.ll = T1_64;
+    u1.d = float64_mul(u1.d, u2.d, &env->spe_status);
+    T0_64 = u1.ll;
     RETURN();
 }
 
@@ -3089,4 +2835,3 @@ void OPPROTO op_efdtsteq (void)
     T0 = _do_efdtsteq(T0_64, T1_64);
     RETURN();
 }
-#endif /* defined(TARGET_PPCSPE) */