target-ppc: convert SLB/TLB instructions to TCG

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5895 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 8f7309b..3911f28 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -582,7 +582,7 @@
 #endif
     /* segment registers */
     target_ulong sdr1;
-    target_ulong sr[16];
+    target_ulong sr[32];
     /* BATs */
     int nb_BATs;
     target_ulong DBAT[2][8];
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 15ff5cc..2678dd6 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2110,13 +2110,6 @@
     }
 }
 
-#if 0 // Unused
-target_ulong do_load_sr (CPUPPCState *env, int srnum)
-{
-    return env->sr[srnum];
-}
-#endif
-
 void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
 {
 #if defined (DEBUG_MMU)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 1e2bd57..5b26078 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -163,10 +163,28 @@
 DEF_HELPER_2(efdcmpeq, i32, i64, i64)
 
 #if !defined(CONFIG_USER_ONLY)
-DEF_HELPER_1(load_6xx_tlbd, void, tl)
-DEF_HELPER_1(load_6xx_tlbi, void, tl)
-DEF_HELPER_1(load_74xx_tlbd, void, tl)
-DEF_HELPER_1(load_74xx_tlbi, void, tl)
+DEF_HELPER_1(4xx_tlbre_hi, tl, tl)
+DEF_HELPER_1(4xx_tlbre_lo, tl, tl)
+DEF_HELPER_2(4xx_tlbwe_hi, void, tl, tl)
+DEF_HELPER_2(4xx_tlbwe_lo, void, tl, tl)
+DEF_HELPER_1(4xx_tlbsx, tl, tl)
+DEF_HELPER_2(440_tlbre, tl, i32, tl)
+DEF_HELPER_3(440_tlbwe, void, i32, tl, tl)
+DEF_HELPER_1(440_tlbsx, tl, tl)
+DEF_HELPER_1(6xx_tlbd, void, tl)
+DEF_HELPER_1(6xx_tlbi, void, tl)
+DEF_HELPER_1(74xx_tlbd, void, tl)
+DEF_HELPER_1(74xx_tlbi, void, tl)
+DEF_HELPER_0(tlbia, void)
+DEF_HELPER_1(tlbie, void, tl)
+#if defined(TARGET_PPC64)
+DEF_HELPER_1(load_slb, tl, tl)
+DEF_HELPER_2(store_slb, void, tl, tl)
+DEF_HELPER_0(slbia, void)
+DEF_HELPER_1(slbie, void, tl)
+#endif
+DEF_HELPER_1(load_sr, tl, tl);
+DEF_HELPER_2(store_sr, void, tl, tl);
 
 DEF_HELPER_1(602_mfrom, tl, tl)
 #endif
diff --git a/target-ppc/op.c b/target-ppc/op.c
index 4a54678..868db83 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -27,33 +27,6 @@
 #include "op_helper.h"
 
 #if !defined(CONFIG_USER_ONLY)
-/* Segment registers load and store */
-void OPPROTO op_load_sr (void)
-{
-    T0 = env->sr[T1];
-    RETURN();
-}
-
-void OPPROTO op_store_sr (void)
-{
-    do_store_sr(env, T1, T0);
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_load_slb (void)
-{
-    T0 = ppc_load_slb(env, T1);
-    RETURN();
-}
-
-void OPPROTO op_store_slb (void)
-{
-    ppc_store_slb(env, T1, T0);
-    RETURN();
-}
-#endif /* defined(TARGET_PPC64) */
-
 void OPPROTO op_load_sdr1 (void)
 {
     T0 = env->sdr1;
@@ -218,13 +191,6 @@
 }
 #endif /* !defined(CONFIG_USER_ONLY) */
 
-/***                             Integer shift                             ***/
-void OPPROTO op_srli_T1 (void)
-{
-    T1 = (uint32_t)T1 >> PARAM1;
-    RETURN();
-}
-
 /* Return from interrupt */
 #if !defined(CONFIG_USER_ONLY)
 /* Exception vectors */
@@ -243,50 +209,6 @@
 }
 #endif
 
-#if !defined(CONFIG_USER_ONLY)
-/* tlbia */
-void OPPROTO op_tlbia (void)
-{
-    ppc_tlb_invalidate_all(env);
-    RETURN();
-}
-
-/* tlbie */
-void OPPROTO op_tlbie (void)
-{
-    ppc_tlb_invalidate_one(env, (uint32_t)T0);
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_tlbie_64 (void)
-{
-    ppc_tlb_invalidate_one(env, T0);
-    RETURN();
-}
-#endif
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_slbia (void)
-{
-    ppc_slb_invalidate_all(env);
-    RETURN();
-}
-
-void OPPROTO op_slbie (void)
-{
-    ppc_slb_invalidate_one(env, (uint32_t)T0);
-    RETURN();
-}
-
-void OPPROTO op_slbie_64 (void)
-{
-    ppc_slb_invalidate_one(env, T0);
-    RETURN();
-}
-#endif
-#endif
-
 /* 601 specific */
 void OPPROTO op_load_601_rtcl (void)
 {
@@ -338,78 +260,6 @@
 }
 #endif /* !defined(CONFIG_USER_ONLY) */
 
-/* POWER instructions not implemented in PowerPC 601 */
-#if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_POWER_mfsri (void)
-{
-    T1 = T0 >> 28;
-    T0 = env->sr[T1];
-    RETURN();
-}
-#endif
-
-/* PowerPC 4xx specific micro-ops */
-#if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_440_tlbre (void)
-{
-    do_440_tlbre(PARAM1);
-    RETURN();
-}
-
-void OPPROTO op_440_tlbsx (void)
-{
-    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
-    RETURN();
-}
-
-void OPPROTO op_4xx_tlbsx_check (void)
-{
-    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();
-}
-
-void OPPROTO op_4xx_tlbre_lo (void)
-{
-    do_4xx_tlbre_lo();
-    RETURN();
-}
-
-void OPPROTO op_4xx_tlbre_hi (void)
-{
-    do_4xx_tlbre_hi();
-    RETURN();
-}
-
-void OPPROTO op_4xx_tlbsx (void)
-{
-    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
-    RETURN();
-}
-
-void OPPROTO op_4xx_tlbwe_lo (void)
-{
-    do_4xx_tlbwe_lo();
-    RETURN();
-}
-
-void OPPROTO op_4xx_tlbwe_hi (void)
-{
-    do_4xx_tlbwe_hi();
-    RETURN();
-}
-#endif
-
 /* SPR micro-ops */
 /* 440 specific */
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 8c9b804..a4dc41d 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -2552,9 +2552,55 @@
     env = saved_env;
 }
 
+/* Segment registers load and store */
+target_ulong helper_load_sr (target_ulong sr_num)
+{
+    return env->sr[sr_num];
+}
+
+void helper_store_sr (target_ulong sr_num, target_ulong val)
+{
+    do_store_sr(env, sr_num, val);
+}
+
+/* SLB management */
+#if defined(TARGET_PPC64)
+target_ulong helper_load_slb (target_ulong slb_nr)
+{
+    return ppc_load_slb(env, slb_nr);
+}
+
+void helper_store_slb (target_ulong slb_nr, target_ulong rs)
+{
+    ppc_store_slb(env, slb_nr, rs);
+}
+
+void helper_slbia (void)
+{
+    ppc_slb_invalidate_all(env);
+}
+
+void helper_slbie (target_ulong addr)
+{
+    ppc_slb_invalidate_one(env, addr);
+}
+
+#endif /* defined(TARGET_PPC64) */
+
+/* TLB management */
+void helper_tlbia (void)
+{
+    ppc_tlb_invalidate_all(env);
+}
+
+void helper_tlbie (target_ulong addr)
+{
+    ppc_tlb_invalidate_one(env, addr);
+}
+
 /* Software driven TLBs management */
 /* PowerPC 602/603 software TLB load instructions helpers */
-static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code)
+static void do_6xx_tlb (target_ulong new_EPN, int is_code)
 {
     target_ulong RPN, CMP, EPN;
     int way;
@@ -2580,18 +2626,18 @@
                      way, is_code, CMP, RPN);
 }
 
-void helper_load_6xx_tlbd (target_ulong EPN)
+void helper_6xx_tlbd (target_ulong EPN)
 {
-    helper_load_6xx_tlb(EPN, 0);
+    do_6xx_tlb(EPN, 0);
 }
 
-void helper_load_6xx_tlbi (target_ulong EPN)
+void helper_6xx_tlbi (target_ulong EPN)
 {
-    helper_load_6xx_tlb(EPN, 1);
+    do_6xx_tlb(EPN, 1);
 }
 
 /* PowerPC 74xx software TLB load instructions helpers */
-static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code)
+static void do_74xx_tlb (target_ulong new_EPN, int is_code)
 {
     target_ulong RPN, CMP, EPN;
     int way;
@@ -2612,14 +2658,14 @@
                      way, is_code, CMP, RPN);
 }
 
-void helper_load_74xx_tlbd (target_ulong EPN)
+void helper_74xx_tlbd (target_ulong EPN)
 {
-    helper_load_74xx_tlb(EPN, 0);
+    do_74xx_tlb(EPN, 0);
 }
 
-void helper_load_74xx_tlbi (target_ulong EPN)
+void helper_74xx_tlbi (target_ulong EPN)
 {
-    helper_load_74xx_tlb(EPN, 1);
+    do_74xx_tlb(EPN, 1);
 }
 
 static always_inline target_ulong booke_tlb_to_page_size (int size)
@@ -2691,81 +2737,85 @@
 }
 
 /* Helpers for 4xx TLB management */
-void do_4xx_tlbre_lo (void)
+target_ulong helper_4xx_tlbre_lo (target_ulong entry)
 {
     ppcemb_tlb_t *tlb;
+    target_ulong ret;
     int size;
 
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->EPN;
+    entry &= 0x3F;
+    tlb = &env->tlb[entry].tlbe;
+    ret = tlb->EPN;
     if (tlb->prot & PAGE_VALID)
-        T0 |= 0x400;
+        ret |= 0x400;
     size = booke_page_size_to_tlb(tlb->size);
     if (size < 0 || size > 0x7)
         size = 1;
-    T0 |= size << 7;
+    ret |= size << 7;
     env->spr[SPR_40x_PID] = tlb->PID;
+    return ret;
 }
 
-void do_4xx_tlbre_hi (void)
+target_ulong helper_4xx_tlbre_hi (target_ulong entry)
 {
     ppcemb_tlb_t *tlb;
+    target_ulong ret;
 
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->RPN;
+    entry &= 0x3F;
+    tlb = &env->tlb[entry].tlbe;
+    ret = tlb->RPN;
     if (tlb->prot & PAGE_EXEC)
-        T0 |= 0x200;
+        ret |= 0x200;
     if (tlb->prot & PAGE_WRITE)
-        T0 |= 0x100;
+        ret |= 0x100;
+    return ret;
 }
 
-void do_4xx_tlbwe_hi (void)
+void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
 {
     ppcemb_tlb_t *tlb;
     target_ulong page, end;
 
 #if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
-        fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
+        fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val);
     }
 #endif
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
+    entry &= 0x3F;
+    tlb = &env->tlb[entry].tlbe;
     /* Invalidate previous TLB (if it's valid) */
     if (tlb->prot & PAGE_VALID) {
         end = tlb->EPN + tlb->size;
 #if defined (DEBUG_SOFTWARE_TLB)
         if (loglevel != 0) {
             fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
-                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
+                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
         }
 #endif
         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
             tlb_flush_page(env, page);
     }
-    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
+    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
     /* We cannot handle TLB size < TARGET_PAGE_SIZE.
      * If this ever occurs, one should use the ppcemb target instead
      * of the ppc or ppc64 one
      */
-    if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
+    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
         cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
                   "are not supported (%d)\n",
-                  tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
+                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
     }
-    tlb->EPN = T1 & ~(tlb->size - 1);
-    if (T1 & 0x40)
+    tlb->EPN = val & ~(tlb->size - 1);
+    if (val & 0x40)
         tlb->prot |= PAGE_VALID;
     else
         tlb->prot &= ~PAGE_VALID;
-    if (T1 & 0x20) {
+    if (val & 0x20) {
         /* XXX: TO BE FIXED */
         cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
     }
     tlb->PID = env->spr[SPR_40x_PID]; /* PID */
-    tlb->attr = T1 & 0xFF;
+    tlb->attr = val & 0xFF;
 #if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
         fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
@@ -2791,28 +2841,28 @@
     }
 }
 
-void do_4xx_tlbwe_lo (void)
+void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
 {
     ppcemb_tlb_t *tlb;
 
 #if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
-        fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
+        fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val);
     }
 #endif
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    tlb->RPN = T1 & 0xFFFFFC00;
+    entry &= 0x3F;
+    tlb = &env->tlb[entry].tlbe;
+    tlb->RPN = val & 0xFFFFFC00;
     tlb->prot = PAGE_READ;
-    if (T1 & 0x200)
+    if (val & 0x200)
         tlb->prot |= PAGE_EXEC;
-    if (T1 & 0x100)
+    if (val & 0x100)
         tlb->prot |= PAGE_WRITE;
 #if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
         fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
                 " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
-                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
+                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
                 tlb->prot & PAGE_READ ? 'r' : '-',
                 tlb->prot & PAGE_WRITE ? 'w' : '-',
                 tlb->prot & PAGE_EXEC ? 'x' : '-',
@@ -2821,8 +2871,13 @@
 #endif
 }
 
+target_ulong helper_4xx_tlbsx (target_ulong address)
+{
+    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
+}
+
 /* PowerPC 440 TLB management */
-void do_440_tlbwe (int word)
+void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
 {
     ppcemb_tlb_t *tlb;
     target_ulong EPN, RPN, size;
@@ -2830,28 +2885,28 @@
 
 #if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
-        fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n",
-                __func__, word, T0, T1);
+        fprintf(logfile, "%s word %d entry " TDX " value " TDX "\n",
+                __func__, word, entry, value);
     }
 #endif
     do_flush_tlbs = 0;
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
+    entry &= 0x3F;
+    tlb = &env->tlb[entry].tlbe;
     switch (word) {
     default:
         /* Just here to please gcc */
     case 0:
-        EPN = T1 & 0xFFFFFC00;
+        EPN = value & 0xFFFFFC00;
         if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
             do_flush_tlbs = 1;
         tlb->EPN = EPN;
-        size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
+        size = booke_tlb_to_page_size((value >> 4) & 0xF);
         if ((tlb->prot & PAGE_VALID) && tlb->size < size)
             do_flush_tlbs = 1;
         tlb->size = size;
         tlb->attr &= ~0x1;
-        tlb->attr |= (T1 >> 8) & 1;
-        if (T1 & 0x200) {
+        tlb->attr |= (value >> 8) & 1;
+        if (value & 0x200) {
             tlb->prot |= PAGE_VALID;
         } else {
             if (tlb->prot & PAGE_VALID) {
@@ -2864,71 +2919,79 @@
             tlb_flush(env, 1);
         break;
     case 1:
-        RPN = T1 & 0xFFFFFC0F;
+        RPN = value & 0xFFFFFC0F;
         if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
             tlb_flush(env, 1);
         tlb->RPN = RPN;
         break;
     case 2:
-        tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
+        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
         tlb->prot = tlb->prot & PAGE_VALID;
-        if (T1 & 0x1)
+        if (value & 0x1)
             tlb->prot |= PAGE_READ << 4;
-        if (T1 & 0x2)
+        if (value & 0x2)
             tlb->prot |= PAGE_WRITE << 4;
-        if (T1 & 0x4)
+        if (value & 0x4)
             tlb->prot |= PAGE_EXEC << 4;
-        if (T1 & 0x8)
+        if (value & 0x8)
             tlb->prot |= PAGE_READ;
-        if (T1 & 0x10)
+        if (value & 0x10)
             tlb->prot |= PAGE_WRITE;
-        if (T1 & 0x20)
+        if (value & 0x20)
             tlb->prot |= PAGE_EXEC;
         break;
     }
 }
 
-void do_440_tlbre (int word)
+target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
 {
     ppcemb_tlb_t *tlb;
+    target_ulong ret;
     int size;
 
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
+    entry &= 0x3F;
+    tlb = &env->tlb[entry].tlbe;
     switch (word) {
     default:
         /* Just here to please gcc */
     case 0:
-        T0 = tlb->EPN;
+        ret = tlb->EPN;
         size = booke_page_size_to_tlb(tlb->size);
         if (size < 0 || size > 0xF)
             size = 1;
-        T0 |= size << 4;
+        ret |= size << 4;
         if (tlb->attr & 0x1)
-            T0 |= 0x100;
+            ret |= 0x100;
         if (tlb->prot & PAGE_VALID)
-            T0 |= 0x200;
+            ret |= 0x200;
         env->spr[SPR_440_MMUCR] &= ~0x000000FF;
         env->spr[SPR_440_MMUCR] |= tlb->PID;
         break;
     case 1:
-        T0 = tlb->RPN;
+        ret = tlb->RPN;
         break;
     case 2:
-        T0 = tlb->attr & ~0x1;
+        ret = tlb->attr & ~0x1;
         if (tlb->prot & (PAGE_READ << 4))
-            T0 |= 0x1;
+            ret |= 0x1;
         if (tlb->prot & (PAGE_WRITE << 4))
-            T0 |= 0x2;
+            ret |= 0x2;
         if (tlb->prot & (PAGE_EXEC << 4))
-            T0 |= 0x4;
+            ret |= 0x4;
         if (tlb->prot & PAGE_READ)
-            T0 |= 0x8;
+            ret |= 0x8;
         if (tlb->prot & PAGE_WRITE)
-            T0 |= 0x10;
+            ret |= 0x10;
         if (tlb->prot & PAGE_EXEC)
-            T0 |= 0x20;
+            ret |= 0x20;
         break;
     }
+    return ret;
 }
+
+target_ulong helper_440_tlbsx (target_ulong address)
+{
+    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
+}
+
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h
index 098695e..1de35a1 100644
--- a/target-ppc/op_helper.h
+++ b/target-ppc/op_helper.h
@@ -34,20 +34,6 @@
 void do_store_hid0_601 (void);
 #endif
 
-/* PowerPC 440 specific helpers */
-#if !defined(CONFIG_USER_ONLY)
-void do_440_tlbre (int word);
-void do_440_tlbwe (int word);
-#endif
-
-/* PowerPC 4xx specific helpers */
-#if !defined(CONFIG_USER_ONLY)
-void do_4xx_tlbre_lo (void);
-void do_4xx_tlbre_hi (void);
-void do_4xx_tlbwe_lo (void);
-void do_4xx_tlbwe_hi (void);
-#endif
-
 /* PowerPC 403 specific helpers */
 #if !defined(CONFIG_USER_ONLY)
 void do_load_403_pb (int num);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8a96afe..e486c23 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -4208,13 +4208,14 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
-    gen_op_load_sr();
-    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+    t0 = tcg_const_tl(SR(ctx->opcode));
+    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -4224,14 +4225,16 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
-    gen_op_srli_T1(28);
-    gen_op_load_sr();
-    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+    t0 = tcg_temp_new();
+    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
+    tcg_gen_andi_tl(t0, t0, 0xF);
+    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -4241,13 +4244,14 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
-    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
-    gen_op_store_sr();
+    t0 = tcg_const_tl(SR(ctx->opcode));
+    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -4257,14 +4261,16 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
-    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
-    gen_op_srli_T1(28);
-    gen_op_store_sr();
+    t0 = tcg_temp_new();
+    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
+    tcg_gen_andi_tl(t0, t0, 0xF);
+    gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -4276,13 +4282,14 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
-    gen_op_load_slb();
-    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+    t0 = tcg_const_tl(SR(ctx->opcode));
+    gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -4293,14 +4300,16 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
-    gen_op_srli_T1(28);
-    gen_op_load_slb();
-    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+    t0 = tcg_temp_new();
+    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
+    tcg_gen_andi_tl(t0, t0, 0xF);
+    gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -4310,13 +4319,14 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
-    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
-    gen_op_store_slb();
+    t0 = tcg_const_tl(SR(ctx->opcode));
+    gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -4327,14 +4337,16 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVREG(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
-    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
-    gen_op_srli_T1(28);
-    gen_op_store_slb();
+    t0 = tcg_temp_new();
+    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
+    tcg_gen_andi_tl(t0, t0, 0xF);
+    gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
+    tcg_temp_free(t0);
 #endif
 }
 #endif /* defined(TARGET_PPC64) */
@@ -4351,7 +4363,7 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_tlbia();
+    gen_helper_tlbia();
 #endif
 }
 
@@ -4365,13 +4377,15 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
 #if defined(TARGET_PPC64)
-    if (ctx->sf_mode)
-        gen_op_tlbie_64();
-    else
+    if (!ctx->sf_mode) {
+        TCGv t0 = tcg_temp_new();
+        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
+        gen_helper_tlbie(t0);
+        tcg_temp_free(t0);
+    } else
 #endif
-        gen_op_tlbie();
+        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
 #endif
 }
 
@@ -4403,7 +4417,7 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_op_slbia();
+    gen_helper_slbia();
 #endif
 }
 
@@ -4417,8 +4431,7 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
-    gen_op_slbie();
+    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
 #endif
 }
 #endif
@@ -5129,7 +5142,7 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_helper_load_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
+    gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
 #endif
 }
 
@@ -5143,7 +5156,7 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_helper_load_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
+    gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
 #endif
 }
 
@@ -5158,7 +5171,7 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_helper_load_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
+    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
 #endif
 }
 
@@ -5172,7 +5185,7 @@
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_helper_load_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
+    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
 #endif
 }
 
@@ -5208,18 +5221,21 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVOPC(ctx);
 #else
+    int ra = rA(ctx->opcode);
+    int rd = rD(ctx->opcode);
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    int ra = rA(ctx->opcode);
-    int rd = rD(ctx->opcode);
-
-    gen_addr_reg_index(cpu_T[0], ctx);
-    gen_op_POWER_mfsri();
-    tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
+    t0 = tcg_temp_new();
+    gen_addr_reg_index(t0, ctx);
+    tcg_gen_shri_tl(t0, t0, 28);
+    tcg_gen_andi_tl(t0, t0, 0xF);
+    gen_helper_load_sr(cpu_gpr[rd], t0);
+    tcg_temp_free(t0);
     if (ra != 0 && ra != rd)
-        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
+        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
 #endif
 }
 
@@ -5389,18 +5405,18 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVOPC(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_addr_reg_index(cpu_T[0], ctx);
-    /* Use the same micro-ops as for tlbie */
+    gen_addr_reg_index(t0, ctx);
 #if defined(TARGET_PPC64)
-    if (ctx->sf_mode)
-        gen_op_tlbie_64();
-    else
+    if (!ctx->sf_mode)
+        tcg_gen_ext32u_tl(t0, t0);
 #endif
-        gen_op_tlbie();
+    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
+    tcg_temp_free(t0);
 #endif
 }
 
@@ -5861,14 +5877,10 @@
     }
     switch (rB(ctx->opcode)) {
     case 0:
-        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
-        gen_op_4xx_tlbre_hi();
-        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
         break;
     case 1:
-        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
-        gen_op_4xx_tlbre_lo();
-        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
         break;
     default:
         GEN_EXCP_INVAL(ctx);
@@ -5883,15 +5895,24 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVOPC(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_addr_reg_index(cpu_T[0], ctx);
-    gen_op_4xx_tlbsx();
-    if (Rc(ctx->opcode))
-        gen_op_4xx_tlbsx_check();
-    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+    t0 = tcg_temp_new();
+    gen_addr_reg_index(t0, ctx);
+    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
+    tcg_temp_free(t0);
+    if (Rc(ctx->opcode)) {
+        int l1 = gen_new_label();
+        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
+        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
+        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
+        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
+        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
+        gen_set_label(l1);
+    }
 #endif
 }
 
@@ -5907,14 +5928,10 @@
     }
     switch (rB(ctx->opcode)) {
     case 0:
-        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
-        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
-        gen_op_4xx_tlbwe_hi();
+        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
         break;
     case 1:
-        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
-        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
-        gen_op_4xx_tlbwe_lo();
+        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
         break;
     default:
         GEN_EXCP_INVAL(ctx);
@@ -5938,9 +5955,11 @@
     case 0:
     case 1:
     case 2:
-        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
-        gen_op_440_tlbre(rB(ctx->opcode));
-        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+        {
+            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
+            gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+            tcg_temp_free_i32(t0);
+        }
         break;
     default:
         GEN_EXCP_INVAL(ctx);
@@ -5955,15 +5974,24 @@
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVOPC(ctx);
 #else
+    TCGv t0;
     if (unlikely(!ctx->supervisor)) {
         GEN_EXCP_PRIVOPC(ctx);
         return;
     }
-    gen_addr_reg_index(cpu_T[0], ctx);
-    gen_op_440_tlbsx();
-    if (Rc(ctx->opcode))
-        gen_op_4xx_tlbsx_check();
-    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
+    t0 = tcg_temp_new();
+    gen_addr_reg_index(t0, ctx);
+    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
+    tcg_temp_free(t0);
+    if (Rc(ctx->opcode)) {
+        int l1 = gen_new_label();
+        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
+        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
+        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
+        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
+        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
+        gen_set_label(l1);
+    }
 #endif
 }
 
@@ -5981,9 +6009,11 @@
     case 0:
     case 1:
     case 2:
-        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
-        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
-        gen_op_440_tlbwe(rB(ctx->opcode));
+        {
+            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
+            gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
+            tcg_temp_free_i32(t0);
+        }
         break;
     default:
         GEN_EXCP_INVAL(ctx);