core: Implement open bus (Reading from unused memory)
Former-commit-id: f0223556894a02ad1f85bb81abc18d47b7508445 Former-commit-id: e44b952867197467fa724022a05ba4579b1e2f03
This commit is contained in:
parent
8afb443354
commit
6b8f4e8f51
|
@ -457,6 +457,16 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
self.pc = self.pc.wrapping_add(4)
|
self.pc = self.pc.wrapping_add(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_decoded_opcode(&self) -> u32 {
|
||||||
|
self.pipeline[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_prefetched_opcode(&self) -> u32 {
|
||||||
|
self.pipeline[1]
|
||||||
|
}
|
||||||
|
|
||||||
/// Perform a pipeline step
|
/// Perform a pipeline step
|
||||||
/// If an instruction was executed in this step, return it.
|
/// If an instruction was executed in this step, return it.
|
||||||
pub fn step(&mut self) {
|
pub fn step(&mut self) {
|
||||||
|
|
|
@ -263,8 +263,51 @@ impl SysBus {
|
||||||
|
|
||||||
self.scheduler.update(cycles);
|
self.scheduler.update(cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper for "open-bus" accesses
|
||||||
|
/// http://problemkaputt.de/gbatek.htm#gbaunpredictablethings
|
||||||
|
/// Reading from Unused Memory (00004000-01FFFFFF,10000000-FFFFFFFF)
|
||||||
|
/// `addr` is considered to be an address of
|
||||||
|
fn read_invalid(&mut self, addr: Addr) -> u32 {
|
||||||
|
warn!("invalid read @{:08x}", addr);
|
||||||
|
use super::arm7tdmi::CpuState;
|
||||||
|
let value = match self.arm_core.cpsr.state() {
|
||||||
|
CpuState::ARM => self.arm_core.get_prefetched_opcode(),
|
||||||
|
CpuState::THUMB => {
|
||||||
|
// For THUMB code the result consists of two 16bit fragments and depends on the address area
|
||||||
|
// and alignment where the opcode was stored.
|
||||||
|
|
||||||
|
let decoded = self.arm_core.get_decoded_opcode() & 0xffff; // [$+2]
|
||||||
|
let prefetched = self.arm_core.get_prefetched_opcode() & 0xffff; // [$+4]
|
||||||
|
let r15 = self.arm_core.pc;
|
||||||
|
let mut value = prefetched;
|
||||||
|
match (r15 >> 24) as usize {
|
||||||
|
PAGE_BIOS | PAGE_OAM => {
|
||||||
|
// TODO this is probably wrong, according to GBATEK, we should be using $+6 here but it isn't prefetched yet.
|
||||||
|
value = value << 16;
|
||||||
|
value |= decoded;
|
||||||
|
}
|
||||||
|
PAGE_IWRAM => {
|
||||||
|
// OldLO=[$+2], OldHI=[$+2]
|
||||||
|
if r15 & 3 == 0 {
|
||||||
|
// LSW = [$+4], MSW = OldHI ;for opcodes at 4-byte aligned locations
|
||||||
|
value |= decoded << 16;
|
||||||
|
} else {
|
||||||
|
// LSW = OldLO, MSW = [$+4] ;for opcodes at non-4-byte aligned locations
|
||||||
|
value = value << 16;
|
||||||
|
value |= decoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => value |= value << 16,
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
value >> ((addr & 3) << 3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Todo - implement bound checks for EWRAM/IWRAM
|
||||||
impl Bus for SysBus {
|
impl Bus for SysBus {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_32(&mut self, addr: Addr) -> u32 {
|
fn read_32(&mut self, addr: Addr) -> u32 {
|
||||||
|
@ -273,7 +316,7 @@ impl Bus for SysBus {
|
||||||
if addr <= 0x3ffc {
|
if addr <= 0x3ffc {
|
||||||
self.bios.read_32(addr)
|
self.bios.read_32(addr)
|
||||||
} else {
|
} else {
|
||||||
0 // TODO open-bus
|
self.read_invalid(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EWRAM_ADDR => self.ewram.read_32(addr & 0x3_fffc),
|
EWRAM_ADDR => self.ewram.read_32(addr & 0x3_fffc),
|
||||||
|
@ -292,10 +335,7 @@ impl Bus for SysBus {
|
||||||
}
|
}
|
||||||
GAMEPAK_WS2_HI => self.cartridge.read_32(addr),
|
GAMEPAK_WS2_HI => self.cartridge.read_32(addr),
|
||||||
SRAM_LO | SRAM_HI => self.cartridge.read_32(addr),
|
SRAM_LO | SRAM_HI => self.cartridge.read_32(addr),
|
||||||
_ => {
|
_ => self.read_invalid(addr),
|
||||||
// TODO open-bus
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +346,7 @@ impl Bus for SysBus {
|
||||||
if addr <= 0x3ffe {
|
if addr <= 0x3ffe {
|
||||||
self.bios.read_16(addr)
|
self.bios.read_16(addr)
|
||||||
} else {
|
} else {
|
||||||
0 // TODO open-bus
|
self.read_invalid(addr) as u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EWRAM_ADDR => self.ewram.read_16(addr & 0x3_fffe),
|
EWRAM_ADDR => self.ewram.read_16(addr & 0x3_fffe),
|
||||||
|
@ -325,10 +365,7 @@ impl Bus for SysBus {
|
||||||
}
|
}
|
||||||
GAMEPAK_WS2_HI => self.cartridge.read_16(addr),
|
GAMEPAK_WS2_HI => self.cartridge.read_16(addr),
|
||||||
SRAM_LO | SRAM_HI => self.cartridge.read_16(addr),
|
SRAM_LO | SRAM_HI => self.cartridge.read_16(addr),
|
||||||
_ => {
|
_ => self.read_invalid(addr) as u16,
|
||||||
// TODO open-bus
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +376,7 @@ impl Bus for SysBus {
|
||||||
if addr <= 0x3fff {
|
if addr <= 0x3fff {
|
||||||
self.bios.read_8(addr)
|
self.bios.read_8(addr)
|
||||||
} else {
|
} else {
|
||||||
0 // TODO open-bus
|
self.read_invalid(addr) as u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EWRAM_ADDR => self.ewram.read_8(addr & 0x3_ffff),
|
EWRAM_ADDR => self.ewram.read_8(addr & 0x3_ffff),
|
||||||
|
@ -358,10 +395,7 @@ impl Bus for SysBus {
|
||||||
}
|
}
|
||||||
GAMEPAK_WS2_HI => self.cartridge.read_8(addr),
|
GAMEPAK_WS2_HI => self.cartridge.read_8(addr),
|
||||||
SRAM_LO | SRAM_HI => self.cartridge.read_8(addr),
|
SRAM_LO | SRAM_HI => self.cartridge.read_8(addr),
|
||||||
_ => {
|
_ => self.read_invalid(addr) as u8,
|
||||||
// TODO open-bus
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue