Start working on Interrupts.

it kinda works now, but needs testing.


Former-commit-id: 8510314cce248a737d492d935cf5b48f86d920ed
This commit is contained in:
Michel Heily 2019-07-29 01:28:22 +03:00
parent 66a484e3ae
commit e962150aaf
5 changed files with 82 additions and 57 deletions

View file

@ -375,7 +375,7 @@ mod tests {
let mut core = Core::new(); let mut core = Core::new();
let bytes = vec![]; let bytes = vec![];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
// swi #0x1337 // swi #0x1337
let decoded = ArmInstruction::decode(0xef001337, 0).unwrap(); let decoded = ArmInstruction::decode(0xef001337, 0).unwrap();
@ -406,7 +406,7 @@ mod tests {
core.pc = 0x20 + 8; core.pc = 0x20 + 8;
let bytes = vec![]; let bytes = vec![];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
core.exec_arm(&mut mem, decoded).unwrap(); core.exec_arm(&mut mem, decoded).unwrap();
assert_eq!(core.did_pipeline_flush(), true); assert_eq!(core.did_pipeline_flush(), true);
@ -429,7 +429,7 @@ mod tests {
core.pc = 0x20 + 8; core.pc = 0x20 + 8;
let bytes = vec![]; let bytes = vec![];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
core.exec_arm(&mut mem, decoded).unwrap(); core.exec_arm(&mut mem, decoded).unwrap();
assert_eq!(core.did_pipeline_flush(), true); assert_eq!(core.did_pipeline_flush(), true);
@ -472,7 +472,7 @@ mod tests {
/* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
core.exec_arm(&mut mem, decoded).unwrap(); core.exec_arm(&mut mem, decoded).unwrap();
assert_eq!(core.gpr[2], 0x1337); assert_eq!(core.gpr[2], 0x1337);
@ -513,7 +513,7 @@ mod tests {
/* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
core.exec_arm(&mut mem, decoded).unwrap(); core.exec_arm(&mut mem, decoded).unwrap();
assert_eq!(mem.read_32(0), 0xabababab); assert_eq!(mem.read_32(0), 0xabababab);
@ -538,7 +538,7 @@ mod tests {
/* c: */ 0xaa, 0xbb, 0xcc, 0xdd, /* c: */ 0xaa, 0xbb, 0xcc, 0xdd,
/* 10: */ 0xaa, 0xbb, 0xcc, 0xdd, /* 10: */ 0xaa, 0xbb, 0xcc, 0xdd,
]; ];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
assert_ne!(mem.read_32(core.get_reg(REG_SP) + 0x10), 0x12345678); assert_ne!(mem.read_32(core.get_reg(REG_SP) + 0x10), 0x12345678);
core.exec_arm(&mut mem, decoded).unwrap(); core.exec_arm(&mut mem, decoded).unwrap();

View file

@ -36,11 +36,12 @@ impl Core {
let new_mode = CpuMode::from(e); let new_mode = CpuMode::from(e);
if self.verbose { if self.verbose {
println!( println!(
"{}: {:?}, pc: {:#x}, new_mode: {:?}", "{}: {:?}, pc: {:#x}, new_mode: {:?} old_mode: {:?}",
"Exception".cyan(), "Exception".cyan(),
e, e,
self.pc, self.pc,
new_mode new_mode,
self.cpsr.mode(),
); );
} }

View file

@ -358,7 +358,7 @@ mod tests {
#[test] #[test]
fn mov_low_reg() { fn mov_low_reg() {
let bytes = vec![]; let bytes = vec![];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
let mut core = Core::new(); let mut core = Core::new();
core.set_reg(0, 0); core.set_reg(0, 0);
@ -390,7 +390,7 @@ mod tests {
/* 8: */ 0x00, 0x00, 0x00, 0x00, /* 8: */ 0x00, 0x00, 0x00, 0x00,
/* c: */ 0x78, 0x56, 0x34, 0x12, /* c: */ 0x78, 0x56, 0x34, 0x12,
]; ];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
let mut core = Core::new(); let mut core = Core::new();
core.set_reg(0, 0); core.set_reg(0, 0);
@ -420,7 +420,7 @@ mod tests {
/* 0ch: */ 0xaa, 0xbb, 0xcc, 0xdd, /* 0ch: */ 0xaa, 0xbb, 0xcc, 0xdd,
/* 10h: */ 0xaa, 0xbb, 0xcc, 0xdd, /* 10h: */ 0xaa, 0xbb, 0xcc, 0xdd,
]; ];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
assert_eq!(format!("{}", str_insn), "str\tr0, [r4, r1]"); assert_eq!(format!("{}", str_insn), "str\tr0, [r4, r1]");
assert_eq!(format!("{}", ldr_insn), "ldrb\tr2, [r4, r1]"); assert_eq!(format!("{}", ldr_insn), "ldrb\tr2, [r4, r1]");
@ -440,7 +440,7 @@ mod tests {
/* 08h: */ 0xaa, 0xbb, 0xcc, 0xdd, 0xaa, 0xbb, 0xcc, 0xdd, /* 08h: */ 0xaa, 0xbb, 0xcc, 0xdd, 0xaa, 0xbb, 0xcc, 0xdd,
/* 10h: */ 0xaa, 0xbb, 0xcc, 0xdd, 0xaa, 0xbb, 0xcc, 0xdd, /* 10h: */ 0xaa, 0xbb, 0xcc, 0xdd, 0xaa, 0xbb, 0xcc, 0xdd,
]; ];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice()); let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
core.gpr[4] = 0x12345678; core.gpr[4] = 0x12345678;
core.gpr[3] = 0x2; core.gpr[3] = 0x2;

View file

@ -11,6 +11,8 @@ use super::EmuIoDev;
use super::{GBAError, GBAResult}; use super::{GBAError, GBAResult};
use crate::backend::*; use crate::backend::*;
use crate::bit::BitIndex;
pub struct GameBoyAdvance { pub struct GameBoyAdvance {
backend: Box<EmulatorBackend>, backend: Box<EmulatorBackend>,
pub cpu: Core, pub cpu: Core,
@ -86,23 +88,27 @@ impl GameBoyAdvance {
let previous_cycles = self.cpu.cycles; let previous_cycles = self.cpu.cycles;
self.cpu.step(&mut self.sysbus).unwrap(); self.cpu.step(&mut self.sysbus).unwrap();
let cycles = self.cpu.cycles - previous_cycles; let cycles = self.cpu.cycles - previous_cycles;
self.gpu.step(cycles, &mut self.sysbus); let (_, irq) = self.gpu.step(cycles, &mut self.sysbus);
if let Some(irq) = irq {
self.request_irq(irq);
}
} }
fn interrupts_disabled(&self) -> bool { fn interrupts_disabled(&self) -> bool {
self.sysbus.ioregs.read_reg(REG_IME) & 1 == 0 self.cpu.cpsr.irq_disabled() | (self.sysbus.ioregs.read_reg(REG_IME) & 1 == 0)
} }
fn request_irq(&mut self, irq: Interrupt) { fn request_irq(&mut self, irq: Interrupt) {
// if self.interrupts_disabled() { if self.interrupts_disabled() {
// return; return;
// } }
// let irq_bit = irq as usize; let irq_bit_index = irq as usize;
// let reg_ie = self.sysbus.ioregs.read_reg(REG_IE); let reg_ie = self.sysbus.ioregs.read_reg(REG_IE);
// if reg_ie & (1 << irq_bit) != 0 { if reg_ie.bit(irq_bit_index) {
// println!("entering {:?}", irq); self.sysbus.ioregs.write_reg(REG_IF, (1 << irq_bit_index) as u16);
// self.cpu.exception(Exception::Irq); println!("entering {:?}", irq);
// } self.cpu.exception(Exception::Irq);
}
} }
pub fn step(&mut self) -> GBAResult<DecodedInstruction> { pub fn step(&mut self) -> GBAResult<DecodedInstruction> {
@ -125,12 +131,10 @@ impl GameBoyAdvance {
// let (dma_cycles, _) = self.dma3.step(cycles, &mut self.sysbus); // let (dma_cycles, _) = self.dma3.step(cycles, &mut self.sysbus);
// cycles += dma_cycles; // cycles += dma_cycles;
/* let (_, irq) = */ let (_, irq) = self.gpu.step(cycles, &mut self.sysbus);
self.gpu.step(cycles, &mut self.sysbus); if let Some(irq) = irq {
// if let Some(irq) = irq { self.request_irq(irq);
// self.request_irq(irq); }
// }
// cycles += lcd_cycles;
Ok(executed_insn) Ok(executed_insn)
} }

View file

@ -9,20 +9,32 @@ use super::arm7tdmi::Addr;
const VIDEO_RAM_SIZE: usize = 128 * 1024; const VIDEO_RAM_SIZE: usize = 128 * 1024;
const WORK_RAM_SIZE: usize = 256 * 1024; const WORK_RAM_SIZE: usize = 256 * 1024;
const INTERNAL_RAM: usize = 32 * 1024; const INTERNAL_RAM_SIZE: usize = 32 * 1024;
const PALETTE_RAM_SIZE: usize = 1 * 1024; const PALETTE_RAM_SIZE: usize = 1 * 1024;
const OAM_SIZE: usize = 1 * 1024; const OAM_SIZE: usize = 1 * 1024;
#[derive(Debug)] #[derive(Debug)]
pub struct BoxedMemory(Box<[u8]>, WaitState); pub struct BoxedMemory {
mem: Box<[u8]>,
impl BoxedMemory { ws: WaitState,
pub fn new(boxed_slice: Box<[u8]>) -> BoxedMemory { mask: u32,
BoxedMemory(boxed_slice, Default::default())
} }
pub fn new_with_waitstate(boxed_slice: Box<[u8]>, ws: WaitState) -> BoxedMemory { impl BoxedMemory {
BoxedMemory(boxed_slice, ws) pub fn new(boxed_slice: Box<[u8]>, mask: u32) -> BoxedMemory {
BoxedMemory {
mem: boxed_slice,
mask: mask,
ws: WaitState::default(),
}
}
pub fn new_with_waitstate(boxed_slice: Box<[u8]>, mask: u32, ws: WaitState) -> BoxedMemory {
BoxedMemory {
mem: boxed_slice,
mask: mask,
ws: ws,
}
} }
} }
@ -51,50 +63,52 @@ impl Default for WaitState {
impl Bus for BoxedMemory { impl Bus for BoxedMemory {
fn read_32(&self, addr: Addr) -> u32 { fn read_32(&self, addr: Addr) -> u32 {
(&self.0[addr as usize..]) (&self.mem[(addr & self.mask) as usize..])
.read_u32::<LittleEndian>() .read_u32::<LittleEndian>()
.unwrap() .unwrap()
} }
fn read_16(&self, addr: Addr) -> u16 { fn read_16(&self, addr: Addr) -> u16 {
(&self.0[addr as usize..]) (&self.mem[(addr & self.mask) as usize..])
.read_u16::<LittleEndian>() .read_u16::<LittleEndian>()
.unwrap() .unwrap()
} }
fn read_8(&self, addr: Addr) -> u8 { fn read_8(&self, addr: Addr) -> u8 {
(&self.0[addr as usize..])[0] (&self.mem[(addr & self.mask) as usize..])[0]
} }
fn write_32(&mut self, addr: Addr, value: u32) { fn write_32(&mut self, addr: Addr, value: u32) {
(&mut self.0[addr as usize..]) (&mut self.mem[(addr & self.mask) as usize..])
.write_u32::<LittleEndian>(value) .write_u32::<LittleEndian>(value)
.unwrap() .unwrap()
} }
fn write_16(&mut self, addr: Addr, value: u16) { fn write_16(&mut self, addr: Addr, value: u16) {
(&mut self.0[addr as usize..]) (&mut self.mem[(addr & self.mask) as usize..])
.write_u16::<LittleEndian>(value) .write_u16::<LittleEndian>(value)
.unwrap() .unwrap()
} }
fn write_8(&mut self, addr: Addr, value: u8) { fn write_8(&mut self, addr: Addr, value: u8) {
(&mut self.0[addr as usize..]).write_u8(value).unwrap() (&mut self.mem[(addr & self.mask) as usize..])
.write_u8(value)
.unwrap()
} }
fn get_bytes(&self, addr: Addr) -> &[u8] { fn get_bytes(&self, addr: Addr) -> &[u8] {
&self.0[addr as usize..] &self.mem[(addr & self.mask) as usize..]
} }
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] { fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] {
&mut self.0[addr as usize..] &mut self.mem[(addr & self.mask) as usize..]
} }
fn get_cycles(&self, _addr: Addr, access: MemoryAccess) -> usize { fn get_cycles(&self, _addr: Addr, access: MemoryAccess) -> usize {
match access.1 { match access.1 {
MemoryAccessWidth::MemoryAccess8 => self.1.access8, MemoryAccessWidth::MemoryAccess8 => self.ws.access8,
MemoryAccessWidth::MemoryAccess16 => self.1.access16, MemoryAccessWidth::MemoryAccess16 => self.ws.access16,
MemoryAccessWidth::MemoryAccess32 => self.1.access32, MemoryAccessWidth::MemoryAccess32 => self.ws.access32,
} }
} }
} }
@ -151,22 +165,28 @@ pub struct SysBus {
impl SysBus { impl SysBus {
pub fn new(bios_rom: Vec<u8>, gamepak: Cartridge) -> SysBus { pub fn new(bios_rom: Vec<u8>, gamepak: Cartridge) -> SysBus {
SysBus { SysBus {
bios: BoxedMemory::new(bios_rom.into_boxed_slice()), bios: BoxedMemory::new(bios_rom.into_boxed_slice(), 0xff_ffff),
onboard_work_ram: BoxedMemory::new_with_waitstate( onboard_work_ram: BoxedMemory::new_with_waitstate(
vec![0; WORK_RAM_SIZE].into_boxed_slice(), vec![0; WORK_RAM_SIZE].into_boxed_slice(),
(WORK_RAM_SIZE as u32) - 1,
WaitState::new(3, 3, 6), WaitState::new(3, 3, 6),
), ),
internal_work_ram: BoxedMemory::new(vec![0; INTERNAL_RAM].into_boxed_slice()), internal_work_ram: BoxedMemory::new(
vec![0; INTERNAL_RAM_SIZE].into_boxed_slice(),
0x7fff,
),
ioregs: IoRegs::default(), ioregs: IoRegs::default(),
palette_ram: BoxedMemory::new_with_waitstate( palette_ram: BoxedMemory::new_with_waitstate(
vec![0; PALETTE_RAM_SIZE].into_boxed_slice(), vec![0; PALETTE_RAM_SIZE].into_boxed_slice(),
(PALETTE_RAM_SIZE as u32) - 1,
WaitState::new(1, 1, 2), WaitState::new(1, 1, 2),
), ),
vram: BoxedMemory::new_with_waitstate( vram: BoxedMemory::new_with_waitstate(
vec![0; VIDEO_RAM_SIZE].into_boxed_slice(), vec![0; VIDEO_RAM_SIZE].into_boxed_slice(),
(VIDEO_RAM_SIZE as u32) - 1,
WaitState::new(1, 1, 2), WaitState::new(1, 1, 2),
), ),
oam: BoxedMemory::new(vec![0; OAM_SIZE].into_boxed_slice()), oam: BoxedMemory::new(vec![0; OAM_SIZE].into_boxed_slice(), (OAM_SIZE as u32) - 1),
gamepak: gamepak, gamepak: gamepak,
dummy: DummyBus([0; 4]), dummy: DummyBus([0; 4]),
} }
@ -175,11 +195,11 @@ impl SysBus {
fn map(&self, addr: Addr) -> &Bus { fn map(&self, addr: Addr) -> &Bus {
match addr as usize { match addr as usize {
0x0000_0000...0x0000_3fff => &self.bios, 0x0000_0000...0x0000_3fff => &self.bios,
0x0200_0000...0x0203_ffff => &self.onboard_work_ram, 0x0200_0000...0x02ff_ffff => &self.onboard_work_ram,
0x0300_0000...0x0300_7fff => &self.internal_work_ram, 0x0300_0000...0x03ff_ffff => &self.internal_work_ram,
0x0400_0000...0x0400_03fe => &self.ioregs, 0x0400_0000...0x0400_03fe => &self.ioregs,
0x0500_0000...0x0500_03ff => &self.palette_ram, 0x0500_0000...0x05ff_ffff => &self.palette_ram,
0x0600_0000...0x0601_7fff => &self.vram, 0x0600_0000...0x06ff_ffff => &self.vram,
0x0700_0000...0x0700_03ff => &self.oam, 0x0700_0000...0x0700_03ff => &self.oam,
0x0800_0000...0x09ff_ffff => &self.gamepak, 0x0800_0000...0x09ff_ffff => &self.gamepak,
_ => &self.dummy, _ => &self.dummy,
@ -190,11 +210,11 @@ impl SysBus {
fn map_mut(&mut self, addr: Addr) -> &mut Bus { fn map_mut(&mut self, addr: Addr) -> &mut Bus {
match addr as usize { match addr as usize {
0x0000_0000...0x0000_3fff => &mut self.bios, 0x0000_0000...0x0000_3fff => &mut self.bios,
0x0200_0000...0x0203_ffff => &mut self.onboard_work_ram, 0x0200_0000...0x02ff_ffff => &mut self.onboard_work_ram,
0x0300_0000...0x0300_7fff => &mut self.internal_work_ram, 0x0300_0000...0x03ff_ffff => &mut self.internal_work_ram,
0x0400_0000...0x0400_03fe => &mut self.ioregs, 0x0400_0000...0x0400_03fe => &mut self.ioregs,
0x0500_0000...0x0500_03ff => &mut self.palette_ram, 0x0500_0000...0x05ff_ffff => &mut self.palette_ram,
0x0600_0000...0x0601_7fff => &mut self.vram, 0x0600_0000...0x06ff_ffff => &mut self.vram,
0x0700_0000...0x0700_03ff => &mut self.oam, 0x0700_0000...0x0700_03ff => &mut self.oam,
0x0800_0000...0x09ff_ffff => &mut self.gamepak, 0x0800_0000...0x09ff_ffff => &mut self.gamepak,
_ => &mut self.dummy, _ => &mut self.dummy,