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 bytes = vec![];
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
// swi #0x1337
let decoded = ArmInstruction::decode(0xef001337, 0).unwrap();
@ -406,7 +406,7 @@ mod tests {
core.pc = 0x20 + 8;
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();
assert_eq!(core.did_pipeline_flush(), true);
@ -429,7 +429,7 @@ mod tests {
core.pc = 0x20 + 8;
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();
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,
/* 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();
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,
/* 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();
assert_eq!(mem.read_32(0), 0xabababab);
@ -538,7 +538,7 @@ mod tests {
/* c: */ 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);
core.exec_arm(&mut mem, decoded).unwrap();

View file

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

View file

@ -358,7 +358,7 @@ mod tests {
#[test]
fn mov_low_reg() {
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();
core.set_reg(0, 0);
@ -390,7 +390,7 @@ mod tests {
/* 8: */ 0x00, 0x00, 0x00, 0x00,
/* 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();
core.set_reg(0, 0);
@ -420,7 +420,7 @@ mod tests {
/* 0ch: */ 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!("{}", ldr_insn), "ldrb\tr2, [r4, r1]");
@ -440,7 +440,7 @@ mod tests {
/* 08h: */ 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[3] = 0x2;

View file

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

View file

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