target-ppc: Disentangle pte_check()

Currently support for both 32-bit and 64-bit hash MMUs share an
implementation of pte_check.  But there are enough differences that this
means the shared function has several very ugly conditionals on "is_64b".

This patch cleans things up by separating out the 64-bit version
(putting it into mmu-hash64.c) and the 32-bit hash version (putting it
in mmu-hash32.c).  Another copy remains in mmu_helper.c, which is used
for the 6xx software loaded TLB paths.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index a72e7c1..9c0de1b 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -23,8 +23,17 @@
 #include "kvm_ppc.h"
 #include "mmu-hash64.h"
 
+//#define DEBUG_MMU
 //#define DEBUG_SLB
 
+#ifdef DEBUG_MMU
+#  define LOG_MMU(...) qemu_log(__VA_ARGS__)
+#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
+#else
+#  define LOG_MMU(...) do { } while (0)
+#  define LOG_MMU_STATE(...) do { } while (0)
+#endif
+
 #ifdef DEBUG_SLB
 #  define LOG_SLB(...) qemu_log(__VA_ARGS__)
 #else
@@ -209,3 +218,59 @@
     }
     return rt;
 }
+
+/*
+ * 64-bit hash table MMU handling
+ */
+
+#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
+#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
+
+static inline int pte64_is_valid(target_ulong pte0)
+{
+    return pte0 & 0x0000000000000001ULL ? 1 : 0;
+}
+
+int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
+                target_ulong pte1, int h, int rw, int type)
+{
+    target_ulong ptem, mmask;
+    int access, ret, pteh, ptev, pp;
+
+    ret = -1;
+    /* Check validity and table match */
+    ptev = pte64_is_valid(pte0);
+    pteh = (pte0 >> 1) & 1;
+    if (ptev && h == pteh) {
+        /* Check vsid & api */
+        ptem = pte0 & PTE64_PTEM_MASK;
+        mmask = PTE64_CHECK_MASK;
+        pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
+        ctx->nx  = (pte1 >> 2) & 1; /* No execute bit */
+        ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
+        if (ptem == ctx->ptem) {
+            if (ctx->raddr != (hwaddr)-1ULL) {
+                /* all matches should have equal RPN, WIMG & PP */
+                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
+                    qemu_log("Bad RPN/WIMG/PP\n");
+                    return -3;
+                }
+            }
+            /* Compute access rights */
+            access = pp_check(ctx->key, pp, ctx->nx);
+            /* Keep the matching PTE informations */
+            ctx->raddr = pte1;
+            ctx->prot = access;
+            ret = check_prot(ctx->prot, rw, type);
+            if (ret == 0) {
+                /* Access granted */
+                LOG_MMU("PTE access granted !\n");
+            } else {
+                /* Access right violation */
+                LOG_MMU("PTE access rejected\n");
+            }
+        }
+    }
+
+    return ret;
+}