]> git.proxmox.com Git - qemu.git/blobdiff - target-ppc/op_helper.c
target-ppc: convert SLB/TLB instructions to TCG
[qemu.git] / target-ppc / op_helper.c
index 8c9b804716cfb42d0a9a12630a91b4b9b23cdd3e..a4dc41d0c45024731258662c6c4f599f66849f11 100644 (file)
@@ -2552,9 +2552,55 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
     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 @@ static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code)
                      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 @@ static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code)
                      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 @@ static always_inline int booke_page_size_to_tlb (target_ulong page_size)
 }
 
 /* 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_hi (void)
     }
 }
 
-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 @@ void do_4xx_tlbwe_lo (void)
 #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 @@ void do_440_tlbwe (int word)
 
 #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 @@ void do_440_tlbwe (int word)
             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 */