+/*****************************************************************************/
+/* BATs management */
+#if !defined(FLUSH_ALL_TLBS)
+static inline void do_invalidate_BAT (CPUPPCState *env,
+ target_ulong BATu, target_ulong mask)
+{
+ target_ulong base, end, page;
+ base = BATu & ~0x0001FFFF;
+ end = base + mask + 0x00020000;
+#if defined (DEBUG_BATS)
+ if (loglevel != 0)
+ fprintf(logfile, "Flush BAT from %08x to %08x (%08x)\n", base, end, mask);
+#endif
+ for (page = base; page != end; page += TARGET_PAGE_SIZE)
+ tlb_flush_page(env, page);
+#if defined (DEBUG_BATS)
+ if (loglevel != 0)
+ fprintf(logfile, "Flush done\n");
+#endif
+}
+#endif
+
+static inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr,
+ target_ulong value)
+{
+#if defined (DEBUG_BATS)
+ if (loglevel != 0) {
+ fprintf(logfile, "Set %cBAT%d%c to 0x%08lx (0x%08lx)\n",
+ ID, nr, ul == 0 ? 'u' : 'l', (unsigned long)value,
+ (unsigned long)env->nip);
+ }
+#endif
+}
+
+target_ulong do_load_ibatu (CPUPPCState *env, int nr)
+{
+ return env->IBAT[0][nr];
+}
+
+target_ulong do_load_ibatl (CPUPPCState *env, int nr)
+{
+ return env->IBAT[1][nr];
+}
+
+void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
+{
+ target_ulong mask;
+
+ dump_store_bat(env, 'I', 0, nr, value);
+ if (env->IBAT[0][nr] != value) {
+ mask = (value << 15) & 0x0FFE0000UL;
+#if !defined(FLUSH_ALL_TLBS)
+ do_invalidate_BAT(env, env->IBAT[0][nr], mask);
+#endif
+ /* When storing valid upper BAT, mask BEPI and BRPN
+ * and invalidate all TLBs covered by this BAT
+ */
+ mask = (value << 15) & 0x0FFE0000UL;
+ env->IBAT[0][nr] = (value & 0x00001FFFUL) |
+ (value & ~0x0001FFFFUL & ~mask);
+ env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
+ (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
+#if !defined(FLUSH_ALL_TLBS)
+ do_invalidate_BAT(env, env->IBAT[0][nr], mask);
+#endif
+#if defined(FLUSH_ALL_TLBS)
+ tlb_flush(env, 1);
+#endif
+ }
+}
+
+void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
+{
+ dump_store_bat(env, 'I', 1, nr, value);
+ env->IBAT[1][nr] = value;
+}
+
+target_ulong do_load_dbatu (CPUPPCState *env, int nr)
+{
+ return env->DBAT[0][nr];
+}
+
+target_ulong do_load_dbatl (CPUPPCState *env, int nr)
+{
+ return env->DBAT[1][nr];
+}
+
+void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
+{
+ target_ulong mask;
+
+ dump_store_bat(env, 'D', 0, nr, value);
+ if (env->DBAT[0][nr] != value) {
+ /* When storing valid upper BAT, mask BEPI and BRPN
+ * and invalidate all TLBs covered by this BAT
+ */
+ mask = (value << 15) & 0x0FFE0000UL;
+#if !defined(FLUSH_ALL_TLBS)
+ do_invalidate_BAT(env, env->DBAT[0][nr], mask);
+#endif
+ mask = (value << 15) & 0x0FFE0000UL;
+ env->DBAT[0][nr] = (value & 0x00001FFFUL) |
+ (value & ~0x0001FFFFUL & ~mask);
+ env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
+ (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
+#if !defined(FLUSH_ALL_TLBS)
+ do_invalidate_BAT(env, env->DBAT[0][nr], mask);
+#else
+ tlb_flush(env, 1);
+#endif
+ }
+}
+
+void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
+{
+ dump_store_bat(env, 'D', 1, nr, value);
+ env->DBAT[1][nr] = value;
+}
+
+static inline void invalidate_all_tlbs (CPUPPCState *env)
+{
+ /* XXX: this needs to be completed for sotware driven TLB support */
+ tlb_flush(env, 1);
+}
+
+/*****************************************************************************/
+/* Special registers manipulation */
+target_ulong do_load_nip (CPUPPCState *env)
+{
+ return env->nip;
+}
+
+void do_store_nip (CPUPPCState *env, target_ulong value)
+{
+ env->nip = value;
+}
+
+target_ulong do_load_sdr1 (CPUPPCState *env)
+{
+ return env->sdr1;
+}
+
+void do_store_sdr1 (CPUPPCState *env, target_ulong value)
+{
+#if defined (DEBUG_MMU)
+ if (loglevel != 0) {
+ fprintf(logfile, "%s: 0x%08lx\n", __func__, (unsigned long)value);
+ }
+#endif
+ if (env->sdr1 != value) {
+ env->sdr1 = value;
+ invalidate_all_tlbs(env);
+ }
+}
+
+target_ulong do_load_sr (CPUPPCState *env, int srnum)
+{
+ return env->sr[srnum];
+}
+
+void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
+{
+#if defined (DEBUG_MMU)
+ if (loglevel != 0) {
+ fprintf(logfile, "%s: reg=%d 0x%08lx %08lx\n",
+ __func__, srnum, (unsigned long)value, env->sr[srnum]);
+ }
+#endif
+ if (env->sr[srnum] != value) {
+ env->sr[srnum] = value;
+#if !defined(FLUSH_ALL_TLBS) && 0
+ {
+ target_ulong page, end;
+ /* Invalidate 256 MB of virtual memory */
+ page = (16 << 20) * srnum;
+ end = page + (16 << 20);
+ for (; page != end; page += TARGET_PAGE_SIZE)
+ tlb_flush_page(env, page);
+ }
+#else
+ invalidate_all_tlbs(env);
+#endif
+ }
+}
+
+uint32_t do_load_cr (CPUPPCState *env)
+{
+ return (env->crf[0] << 28) |
+ (env->crf[1] << 24) |
+ (env->crf[2] << 20) |
+ (env->crf[3] << 16) |
+ (env->crf[4] << 12) |
+ (env->crf[5] << 8) |
+ (env->crf[6] << 4) |
+ (env->crf[7] << 0);
+}
+
+void do_store_cr (CPUPPCState *env, uint32_t value, uint32_t mask)
+{
+ int i, sh;
+
+ for (i = 0, sh = 7; i < 8; i++, sh --) {
+ if (mask & (1 << sh))
+ env->crf[i] = (value >> (sh * 4)) & 0xFUL;
+ }
+}
+
+uint32_t do_load_xer (CPUPPCState *env)