func: static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
  
                                        target_ulong eaddr, int rw, int type)
  
  {
  
      hwaddr hash;
  
      target_ulong vsid;
  
      int ds, pr, target_page_bits;
  
      int ret;
  
      target_ulong sr, pgidx;
  
  
  
      pr = msr_pr;
  
      ctx->eaddr = eaddr;
  
  
  
      sr = env->sr[eaddr >> 28];
  
      ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
  
                  ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
  
      ds = sr & 0x80000000 ? 1 : 0;
  
      ctx->nx = sr & 0x10000000 ? 1 : 0;
  
      vsid = sr & 0x00FFFFFF;
  
      target_page_bits = TARGET_PAGE_BITS;
  
      qemu_log_mask(CPU_LOG_MMU,
  
              "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
  
              " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
  
              " ir=%d dr=%d pr=%d %d t=%d\n",
  
              eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
  
              (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
  
      pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
  
      hash = vsid ^ pgidx;
  
      ctx->ptem = (vsid << 7) | (pgidx >> 10);
  
  
  
      qemu_log_mask(CPU_LOG_MMU,
  
              "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
  
              ctx->key, ds, ctx->nx, vsid);
  
      ret = -1;
  
      if (!ds) {
  
          /* Check if instruction fetch is allowed, if needed */
  
          if (type != ACCESS_CODE || ctx->nx == 0) {
  
              /* Page address translation */
  
              qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
  
                      " htab_mask " TARGET_FMT_plx
  
                      " hash " TARGET_FMT_plx "\n",
  
                      env->htab_base, env->htab_mask, hash);
  
              ctx->hash[0] = hash;
  
              ctx->hash[1] = ~hash;
  
  
  
              /* Initialize real address with an invalid value */
  
              ctx->raddr = (hwaddr)-1ULL;
  
              /* Software TLB search */
  
              ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
  
  #if defined(DUMP_PAGE_TABLES)
  
              if (qemu_loglevel_mask(CPU_LOG_MMU)) {
  
                  CPUState *cs = ENV_GET_CPU(env);
  
                  hwaddr curaddr;
  
                  uint32_t a0, a1, a2, a3;
  
  
  
                  qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
  
                           "\n", env->htab_base, env->htab_mask + 0x80);
  
                  for (curaddr = env->htab_base;
  
                       curaddr < (env->htab_base + env->htab_mask + 0x80);
  
                       curaddr += 16) {
  
                      a0 = ldl_phys(cs->as, curaddr);
  
                      a1 = ldl_phys(cs->as, curaddr + 4);
  
                      a2 = ldl_phys(cs->as, curaddr + 8);
  
                      a3 = ldl_phys(cs->as, curaddr + 12);
  
                      if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
  
                          qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
  
                                   curaddr, a0, a1, a2, a3);
  
                      }
  
                  }
  
              }
  
  #endif
  
          } else {
  
              qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
  
              ret = -3;
  
          }
  
      } else {
  
          target_ulong sr;
  
  
  
          qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
  
          /* Direct-store segment : absolutely *BUGGY* for now */
  
  
  
          /* Direct-store implies a 32-bit MMU.
  
           * Check the Segment Register's bus unit ID (BUID).
  
           */
  
          sr = env->sr[eaddr >> 28];
  
          if ((sr & 0x1FF00000) >> 20 == 0x07f) {
  
              /* Memory-forced I/O controller interface access */
  
              /* If T=1 and BUID=x'07F', the 601 performs a memory access
  
               * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
  
               */
  
              ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
  
              ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
  
              return 0;
  
          }
  
  
  
          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 :-)
  
               */
  
              ctx->raddr = eaddr;
  
              return 0;
  
          case ACCESS_EXT:
  
              /* eciwx or ecowx */
  
              return -4;
  
          default:
  
              qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
  
                            "address translation\n");
  
              return -4;
  
          }
  
          if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
  
              ctx->raddr = eaddr;
  
              ret = 2;
  
          } else {
  
              ret = -2;
  
          }
  
      }
  
  
  
      return ret;
  
  }
  