+ sr = env->sr[virtual >> 28];
+#if defined (DEBUG_MMU)
+ if (loglevel > 0) {
+ fprintf(logfile, "Check segment v=0x%08x %d 0x%08x nip=0x%08x "
+ "lr=0x%08x ir=%d dr=%d pr=%d %d t=%d\n",
+ virtual, virtual >> 28, sr, env->nip,
+ env->lr, msr_ir, msr_dr, msr_pr, rw, type);
+ }
+#endif
+ key = (((sr & 0x20000000) && msr_pr == 1) ||
+ ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
+ if ((sr & 0x80000000) == 0) {
+#if defined (DEBUG_MMU)
+ if (loglevel > 0)
+ fprintf(logfile, "pte segment: key=%d n=0x%08x\n",
+ key, sr & 0x10000000);
+#endif
+ /* Check if instruction fetch is allowed, if needed */
+ if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
+ /* Page address translation */
+ vsid = sr & 0x00FFFFFF;
+ pgidx = (virtual >> 12) & 0xFFFF;
+ sdr = env->sdr1;
+ hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
+ mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
+ pg_addr = get_pgaddr(sdr, hash, mask);
+ ptem = (vsid << 7) | (pgidx >> 10);
+#if defined (DEBUG_MMU)
+ if (loglevel > 0) {
+ fprintf(logfile, "0 sdr1=0x%08x vsid=0x%06x api=0x%04x "
+ "hash=0x%07x pg_addr=0x%08x\n", sdr, vsid, pgidx, hash,
+ pg_addr);
+ }
+#endif
+ /* Primary table lookup */
+ ret = find_pte(real, prot, pg_addr, ptem, 0, key, rw);
+ if (ret < 0) {
+ /* Secondary table lookup */
+ hash = (~hash) & 0x01FFFFC0;
+ pg_addr = get_pgaddr(sdr, hash, mask);
+#if defined (DEBUG_MMU)
+ if (virtual != 0xEFFFFFFF && loglevel > 0) {
+ fprintf(logfile, "1 sdr1=0x%08x vsid=0x%06x api=0x%04x "
+ "hash=0x%05x pg_addr=0x%08x\n", sdr, vsid, pgidx,
+ hash, pg_addr);
+ }
+#endif
+ ret2 = find_pte(real, prot, pg_addr, ptem, 1, key, rw);
+ if (ret2 != -1)
+ ret = ret2;
+ }
+ } else {
+#if defined (DEBUG_MMU)
+ if (loglevel > 0)
+ fprintf(logfile, "No access allowed\n");
+#endif
+ ret = -3;
+ }
+ } else {
+#if defined (DEBUG_MMU)
+ if (loglevel > 0)
+ fprintf(logfile, "direct store...\n");
+#endif
+ /* Direct-store segment : absolutely *BUGGY* for now */
+ switch (type) {
+ case ACCESS_INT:
+ /* Integer load/store : only access allowed */
+ break;
+ case ACCESS_CODE:
+ /* No code fetch is allowed in direct-store areas */
+ return -4;
+ case ACCESS_FLOAT:
+ /* Floating point load/store */
+ return -4;
+ case ACCESS_RES:
+ /* lwarx, ldarx or srwcx. */
+ return -4;
+ case ACCESS_CACHE:
+ /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
+ /* Should make the instruction do no-op.
+ * As it already do no-op, it's quite easy :-)
+ */
+ *real = virtual;
+ return 0;
+ case ACCESS_EXT:
+ /* eciwx or ecowx */
+ return -4;
+ default:
+ if (logfile) {
+ fprintf(logfile, "ERROR: instruction should not need "
+ "address translation\n");
+ }
+ printf("ERROR: instruction should not need "
+ "address translation\n");
+ return -4;
+ }
+ if ((rw == 1 || key != 1) && (rw == 0 || key != 0)) {
+ *real = virtual;
+ ret = 2;
+ } else {
+ ret = -2;
+ }
+ }
+
+ return ret;