diff --git a/src/mmu.rs b/src/mmu.rs index c75df9f..3ff43bc 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use nullable_result::NullableResult; use crate::{ - backplane::{self, Backplane}, + backplane::Backplane, card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card, Mmu}, m68k::BusError, register, @@ -26,6 +26,25 @@ pub struct MmuCard { tlb_clear_entry: u16, } +impl MmuCard { + fn get_mapping(&self, page: u32, backplane: &Backplane, print_debug: bool) -> NullableResult { + if !self.map_frames_enabled[(page >> 10) as usize] { + if print_debug { + println!("No mapping frame for this quarter"); + } + return NullableResult::Null; + } + let map_frame = self.map_frames[(page >> 10) as usize]; + let mapping_address = (map_frame) | ((page & 0x3FF) << 2); + if print_debug { + println!("Mapping is at {mapping_address:#x}"); + } + let mapping_hi = backplane.read_word_phys(mapping_address)?; + let mapping_lo = backplane.read_word_phys(mapping_address + 2)?; + NullableResult::Ok((u32::from(mapping_hi) << 16 | u32::from(mapping_lo)) | TLB_MAPPING_FLAG_VALID) + } +} + impl Card for MmuCard { fn new(_data: toml::Value) -> anyhow::Result { Ok(Self { @@ -118,6 +137,174 @@ impl Card for MmuCard { if cmd[0] == "debug" && cmd.len() >= 2 { self.print_debug = cmd[1].parse()?; } + if cmd[0] == "dump_tlb" { + let mut i = 0; + while i < 4096 { + let entry = self.tlb[i]; + if entry & TLB_MAPPING_FLAG_VALID == 0 { + i += 1; + continue; + } + let flags = entry & 0xFFF; + let frame = entry & !0xFFF; + let mut j = i; + let mut range_one_page: Option = None; + while j < 4095 { + let entry = self.get_mapping((j+1) as u32, backplane, false).resulting_option()?.unwrap_or(0); + if entry & TLB_MAPPING_FLAG_VALID == 0 { + break; + } + let j_flags = entry & 0xFFF; + let j_frame = entry & !0xFFF; + if j_flags != flags || j_frame < frame { + break; + } + if j_frame == frame { + if range_one_page == Some(false) { + break; + } else { + range_one_page = Some(true); + } + } else if (j_frame - frame) == ((((j - i) as u32) + 1) * 0x1000) { + if range_one_page == Some(true) { + break; + } else { + range_one_page = Some(false); + } + } else { + break; + } + j += 1; + } + let present_flag = (flags & MAPPING_FLAG_PRESENT) > 0; + let wr_flag = (flags & MAPPING_FLAG_WRITABLE) > 0; + let user_flag = (flags & MAPPING_FLAG_USER) > 0; + let present_flag = if present_flag { "P" } else { "_" }; + let wr_flag = if wr_flag { "W" } else { "_" }; + let user_flag = if user_flag { "U" } else { "_" }; + if j == i { + println!( + "0x{:0>6x}: 0x{:0>8x} ({}{}{})", + i << 12, + frame, + user_flag, + wr_flag, + present_flag + ); + i += 1; + } else { + if range_one_page.unwrap() { + println!( + "0x{:0>6x}-0x{:0>6x}: 0x{:0>8x} ({}{}{})", + i << 12, + j << 12, + frame, + user_flag, + wr_flag, + present_flag + ); + } else { + let range_len = (j - i) as u32; + println!( + "0x{:0>6x}-0x{:0>6x}: 0x{:0>8x}-0x{:0>8x} ({}{}{})", + i << 12, + j << 12, + frame, + frame + (range_len * 0x1000), + user_flag, + wr_flag, + present_flag + ); + } + i = j + 1; + + } + } + } + if cmd[0] == "dump_map_pages" { + let mut i = 0; + while i < 4096 { + let entry = self.get_mapping(i as u32, backplane, false).resulting_option()?.unwrap_or(0); + if entry & TLB_MAPPING_FLAG_VALID == 0 { + i+=1; + continue; + } + let flags = entry & 0xFFF; + let frame = entry & !0xFFF; + let mut j = i; + let mut range_one_page: Option = None; + while j < 4095 { + let entry = self.get_mapping((j+1) as u32, backplane, false).resulting_option()?.unwrap_or(0); + if entry & TLB_MAPPING_FLAG_VALID == 0 { + break; + } + let j_flags = entry & 0xFFF; + let j_frame = entry & !0xFFF; + if j_flags != flags || j_frame < frame { + break; + } + if j_frame == frame { + if range_one_page == Some(false) { + break; + } else { + range_one_page = Some(true); + } + } else if (j_frame - frame) == ((((j - i) as u32) + 1) * 0x1000) { + if range_one_page == Some(true) { + break; + } else { + range_one_page = Some(false); + } + } else { + break; + } + j += 1; + } + let present_flag = (flags & MAPPING_FLAG_PRESENT) > 0; + let wr_flag = (flags & MAPPING_FLAG_WRITABLE) > 0; + let user_flag = (flags & MAPPING_FLAG_USER) > 0; + let present_flag = if present_flag { "P" } else { "_" }; + let wr_flag = if wr_flag { "W" } else { "_" }; + let user_flag = if user_flag { "U" } else { "_" }; + if j == i { + println!( + "0x{:0>6x}: 0x{:0>8x} ({}{}{})", + i << 12, + frame, + user_flag, + wr_flag, + present_flag + ); + i += 1; + } else { + if range_one_page.unwrap() { + println!( + "0x{:0>6x}-0x{:0>6x}: 0x{:0>8x} ({}{}{})", + i << 12, + j << 12, + frame, + user_flag, + wr_flag, + present_flag + ); + } else { + let range_len = (j - i) as u32; + println!( + "0x{:0>6x}-0x{:0>6x}: 0x{:0>8x}-0x{:0>8x} ({}{}{})", + i << 12, + j << 12, + frame, + frame + (range_len * 0x1000), + user_flag, + wr_flag, + present_flag + ); + } + i = j + 1; + } + } + } + Ok(()) } @@ -180,21 +367,7 @@ impl Mmu for MmuCard { if print_debug { println!("TLB miss, fetching mapping"); } - if !self.map_frames_enabled[(page >> 10) as usize] { - if print_debug { - println!("No mapping frame for this quarter"); - } - return NullableResult::Null; - } - let map_frame = self.map_frames[(page >> 10) as usize]; - let mapping_address = (map_frame) | ((page & 0x3FF) << 2); - if print_debug { - println!("Mapping is at {mapping_address:#x}"); - } - let mapping_hi = backplane.read_word_phys(mapping_address)?; - let mapping_lo = backplane.read_word_phys(mapping_address + 2)?; - let mapping = - (u32::from(mapping_hi) << 16 | u32::from(mapping_lo)) | TLB_MAPPING_FLAG_VALID; + let mapping = self.get_mapping(page, backplane, print_debug)?; self.tlb[page as usize] = mapping; mapping }; diff --git a/src/rom.rs b/src/rom.rs index 6002c7d..673d600 100644 --- a/src/rom.rs +++ b/src/rom.rs @@ -7,7 +7,7 @@ use serde::Deserialize; use toml::Value; use crate::{ - backplane::{self, Backplane}, card::{u16_get_be_byte, u16_set_be_byte, Card}, m68k::BusError, register + backplane::Backplane, card::{u16_get_be_byte, u16_set_be_byte, Card}, m68k::BusError, register }; const ID: u16 = 1;