diff --git a/src/bin/main.rs b/src/bin/main.rs
index 6599576..ea34086 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -38,7 +38,6 @@ fn run_emulator(matches: &ArgMatches) -> GBAResult<()> {
println!("loaded rom: {:#?}", gamepak.header);
let mut core = Core::new();
- core.reset();
if skip_bios {
core.gpr[13] = 0x0300_7f00;
core.gpr_banked_r13[0] = 0x0300_7f00; // USR/SYS
diff --git a/src/core/arm7tdmi/alu.rs b/src/core/arm7tdmi/alu.rs
index 1723ad4..1276e55 100644
--- a/src/core/arm7tdmi/alu.rs
+++ b/src/core/arm7tdmi/alu.rs
@@ -240,6 +240,7 @@ impl Core {
Ok(result)
}
ShiftRegisterBy::ByRegister(rs) => {
+ self.add_cycle(); // +1I
if shift.reg == REG_PC {
val = val + 4; // PC prefetching
}
diff --git a/src/core/arm7tdmi/arm/exec.rs b/src/core/arm7tdmi/arm/exec.rs
index 540cade..4c101b0 100644
--- a/src/core/arm7tdmi/arm/exec.rs
+++ b/src/core/arm7tdmi/arm/exec.rs
@@ -4,25 +4,27 @@ use super::super::alu::*;
use crate::core::arm7tdmi::bus::Bus;
use crate::core::arm7tdmi::cpu::{Core, CpuExecResult};
use crate::core::arm7tdmi::psr::RegPSR;
-use crate::core::arm7tdmi::{Addr, CpuError, CpuMode, CpuResult, CpuState, REG_PC};
+use crate::core::arm7tdmi::{Addr, CpuError, CpuMode, CpuResult, CpuState, REG_LR, REG_PC};
+use crate::core::sysbus::SysBus;
use super::*;
impl Core {
- pub fn exec_arm(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ pub fn exec_arm(&mut self, bus: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
if !self.check_arm_cond(insn.cond) {
+ self.S_cycle32(bus, self.pc);
return Ok(());
}
match insn.fmt {
ArmFormat::BX => self.exec_bx(bus, insn),
ArmFormat::B_BL => self.exec_b_bl(bus, insn),
ArmFormat::DP => self.exec_data_processing(bus, insn),
- ArmFormat::SWI => self.exec_swi(),
+ ArmFormat::SWI => self.exec_swi(bus),
ArmFormat::LDR_STR => self.exec_ldr_str(bus, insn),
ArmFormat::LDR_STR_HS_IMM => self.exec_ldr_str_hs(bus, insn),
ArmFormat::LDR_STR_HS_REG => self.exec_ldr_str_hs(bus, insn),
ArmFormat::LDM_STM => self.exec_ldm_stm(bus, insn),
- ArmFormat::MRS => self.exec_mrs(insn),
+ ArmFormat::MRS => self.exec_mrs(bus, insn),
ArmFormat::MSR_REG => self.exec_msr_reg(bus, insn),
ArmFormat::MSR_FLAGS => self.exec_msr_flags(bus, insn),
ArmFormat::MUL_MLA => self.exec_mul_mla(bus, insn),
@@ -32,18 +34,23 @@ impl Core {
}
/// Cycles 2S+1N
- fn exec_b_bl(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_b_bl(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
+ self.S_cycle32(sb, self.pc);
if insn.link_flag() {
- self.set_reg(14, (insn.pc + (self.word_size() as u32)) & !0b1);
+ self.set_reg(REG_LR, (insn.pc + (self.word_size() as u32)) & !0b1);
}
self.pc = (self.pc as i32).wrapping_add(insn.branch_offset()) as u32 & !1;
- self.flush_pipeline();
+ self.flush_pipeline(sb);
Ok(())
}
- pub fn branch_exchange(&mut self, mut addr: Addr) -> CpuExecResult {
+ pub fn branch_exchange(&mut self, sb: &mut SysBus, mut addr: Addr) -> CpuExecResult {
+ match self.cpsr.state() {
+ CpuState::ARM => self.S_cycle32(sb, self.pc),
+ CpuState::THUMB => self.S_cycle16(sb, self.pc),
+ }
if addr.bit(0) {
addr = addr & !0x1;
self.cpsr.set_state(CpuState::THUMB);
@@ -53,17 +60,17 @@ impl Core {
}
self.pc = addr;
- self.flush_pipeline();
+ self.flush_pipeline(sb); // +1S+1N
Ok(())
}
/// Cycles 2S+1N
- fn exec_bx(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
- self.branch_exchange(self.get_reg(insn.rn()))
+ fn exec_bx(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
+ self.branch_exchange(sb, self.get_reg(insn.rn()))
}
- fn exec_mrs(&mut self, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_mrs(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let mode = self.cpsr.mode();
let result = if insn.spsr_flag() {
if let Some(index) = mode.spsr_index() {
@@ -75,14 +82,15 @@ impl Core {
self.cpsr.get()
};
self.set_reg(insn.rd(), result);
+ self.S_cycle32(sb, self.pc);
Ok(())
}
- fn exec_msr_reg(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
- self.exec_msr(insn, self.get_reg(insn.rm()))
+ fn exec_msr_reg(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
+ self.exec_msr(sb, insn, self.get_reg(insn.rm()))
}
- fn exec_msr(&mut self, insn: ArmInstruction, value: u32) -> CpuExecResult {
+ fn exec_msr(&mut self, sb: &mut SysBus, insn: ArmInstruction, value: u32) -> CpuExecResult {
let new_psr = RegPSR::new(value);
let old_mode = self.cpsr.mode();
if insn.spsr_flag() {
@@ -97,10 +105,12 @@ impl Core {
}
self.cpsr = new_psr;
}
+ self.S_cycle32(sb, self.pc);
Ok(())
}
- fn exec_msr_flags(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_msr_flags(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
+ self.S_cycle32(sb, self.pc);
let op = insn.operand2()?;
let op = self.decode_operand2(op, false)?;
@@ -124,8 +134,6 @@ impl Core {
Ok(result)
}
BarrelShifterValue::ShiftedRegister(x) => {
- // +1I
- self.add_cycle();
let result = self.register_shift(x)?;
if set_flags {
self.cpsr.set_C(self.bs_carry_out);
@@ -151,7 +159,8 @@ impl Core {
///
/// Cycles: 1S+x+y (from GBATEK)
/// Add x=1I cycles if Op2 shifted-by-register. Add y=1S+1N cycles if Rd=R15.
- fn exec_data_processing(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_data_processing(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
+ self.S_cycle32(sb, self.pc);
let op1 = if insn.rn() == REG_PC {
self.pc as i32
} else {
@@ -167,9 +176,9 @@ impl Core {
if !s_flag {
match opcode {
AluOpCode::TEQ | AluOpCode::CMN => {
- return self.exec_msr(insn, op2 as u32);
+ return self.exec_msr(sb, insn, op2 as u32);
}
- AluOpCode::TST | AluOpCode::CMP => return self.exec_mrs(insn),
+ AluOpCode::TST | AluOpCode::CMP => return self.exec_mrs(sb, insn),
_ => (),
}
}
@@ -185,7 +194,7 @@ impl Core {
if let Some(result) = alu_res {
if rd == REG_PC {
self.transfer_spsr_mode();
- self.flush_pipeline();
+ self.flush_pipeline(sb);
}
self.set_reg(rd, result as u32);
}
@@ -200,16 +209,13 @@ impl Core {
/// STR{cond}{B}{T} Rd,
| 2N | ---- | [Rn+/-]=Rd
/// ------------------------------------------------------------------------------
/// For LDR, add y=1S+1N if Rd=R15.
- fn exec_ldr_str(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_ldr_str(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let mut writeback = insn.write_back_flag();
-
let mut addr = self.get_reg(insn.rn());
if insn.rn() == REG_PC {
addr = insn.pc + 8; // prefetching
}
-
let offset = self.get_barrel_shifted_value(insn.ldr_str_offset());
-
let effective_addr = (addr as i32).wrapping_add(offset) as Addr;
addr = if insn.pre_index_flag() {
effective_addr
@@ -220,12 +226,14 @@ impl Core {
if writeback && insn.rd() == insn.rn() {
writeback = false;
}
-
if insn.load_flag() {
+ self.S_cycle32(sb, self.pc);
let data = if insn.transfer_size() == 1 {
- self.load_8(addr, bus) as u32
+ self.N_cycle8(sb, addr);
+ sb.read_8(addr) as u32
} else {
- self.ldr_word(addr, bus)
+ self.N_cycle32(sb, addr);
+ self.ldr_word(addr, sb)
};
self.set_reg(insn.rd(), data);
@@ -234,7 +242,7 @@ impl Core {
self.add_cycle();
if insn.rd() == REG_PC {
- self.flush_pipeline();
+ self.flush_pipeline(sb);
}
} else {
let value = if insn.rd() == REG_PC {
@@ -243,10 +251,13 @@ impl Core {
self.get_reg(insn.rd())
};
if insn.transfer_size() == 1 {
- self.store_8(addr, value as u8, bus);
+ self.N_cycle8(sb, addr);
+ sb.write_8(addr, value as u8);
} else {
- self.store_32(addr & !0x3, value, bus);
+ self.N_cycle32(sb, addr);
+ sb.write_32(addr & !0x3, value);
};
+ self.N_cycle32(sb, self.pc);
}
if writeback {
@@ -256,7 +267,7 @@ impl Core {
Ok(())
}
- fn exec_ldr_str_hs(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_ldr_str_hs(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let mut writeback = insn.write_back_flag();
let mut addr = self.get_reg(insn.rn());
@@ -277,10 +288,20 @@ impl Core {
writeback = false;
}
if insn.load_flag() {
+ self.S_cycle32(sb, self.pc);
let data = match insn.halfword_data_transfer_type().unwrap() {
- ArmHalfwordTransferType::SignedByte => self.load_8(addr, bus) as u8 as i8 as u32,
- ArmHalfwordTransferType::SignedHalfwords => self.ldr_sign_half(addr, bus),
- ArmHalfwordTransferType::UnsignedHalfwords => self.ldr_half(addr, bus),
+ ArmHalfwordTransferType::SignedByte => {
+ self.N_cycle8(sb, addr);
+ sb.read_8(addr) as u8 as i8 as u32
+ }
+ ArmHalfwordTransferType::SignedHalfwords => {
+ self.N_cycle16(sb, addr);
+ self.ldr_sign_half(addr, sb)
+ }
+ ArmHalfwordTransferType::UnsignedHalfwords => {
+ self.N_cycle16(sb, addr);
+ self.ldr_half(addr, sb)
+ }
};
self.set_reg(insn.rd(), data);
@@ -289,7 +310,7 @@ impl Core {
self.add_cycle();
if insn.rd() == REG_PC {
- self.flush_pipeline();
+ self.flush_pipeline(sb);
}
} else {
let value = if insn.rd() == REG_PC {
@@ -300,7 +321,9 @@ impl Core {
match insn.halfword_data_transfer_type().unwrap() {
ArmHalfwordTransferType::UnsignedHalfwords => {
- self.store_16(addr, value as u16, bus)
+ self.N_cycle32(sb, addr);
+ sb.write_16(addr, value as u16);
+ self.N_cycle32(sb, self.pc);
}
_ => panic!("invalid HS flags for L=0"),
};
@@ -313,7 +336,7 @@ impl Core {
Ok(())
}
- fn exec_ldm_stm(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_ldm_stm(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let full = insn.pre_index_flag();
let ascending = insn.add_offset_flag();
let psr_user_flag = insn.psr_and_force_user_flag();
@@ -347,6 +370,8 @@ impl Core {
let psr_transfer = psr_user_flag & is_load & rlist.bit(REG_PC);
if is_load {
+ self.add_cycle();
+ self.N_cycle32(sb, self.pc);
for r in 0..16 {
let r = if ascending { r } else { 15 - r };
if rlist.bit(r) {
@@ -357,8 +382,8 @@ impl Core {
addr = addr.wrapping_add(step);
}
- self.add_cycle();
- let val = self.load_32(addr as Addr, bus);
+ let val = sb.read_32(addr as Addr);
+ self.S_cycle32(sb, self.pc);
if user_bank_transfer {
self.set_reg_user(r, val);
} else {
@@ -369,7 +394,7 @@ impl Core {
if psr_transfer {
self.transfer_spsr_mode();
}
- self.flush_pipeline();
+ self.flush_pipeline(sb);
}
if !full {
@@ -378,6 +403,7 @@ impl Core {
}
}
} else {
+ let mut first = true;
for r in 0..16 {
let r = if ascending { r } else { 15 - r };
if rlist.bit(r) {
@@ -394,13 +420,20 @@ impl Core {
self.get_reg(r)
}
};
- self.store_32(addr as Addr, val, bus);
+ if first {
+ self.N_cycle32(sb, addr as u32);
+ first = false;
+ } else {
+ self.S_cycle32(sb, addr as u32);
+ }
+ sb.write_32(addr as Addr, val);
if !full {
addr = addr.wrapping_add(step);
}
}
}
+ self.N_cycle32(sb, self.pc);
}
if writeback {
@@ -410,7 +443,7 @@ impl Core {
Ok(())
}
- fn exec_mul_mla(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_mul_mla(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let (rd, rn, rs, rm) = (insn.rd(), insn.rn(), insn.rs(), insn.rm());
// check validity
@@ -444,10 +477,11 @@ impl Core {
self.cpsr.set_V(false);
}
+ self.S_cycle32(sb, self.pc);
Ok(())
}
- fn exec_mull_mlal(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_mull_mlal(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let (rd_hi, rd_lo, rn, rs, rm) =
(insn.rd_hi(), insn.rd_lo(), insn.rn(), insn.rs(), insn.rm());
@@ -491,21 +525,27 @@ impl Core {
self.cpsr.set_V(false);
}
+ self.S_cycle32(sb, self.pc);
Ok(())
}
- fn exec_arm_swp(&mut self, sb: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
+ fn exec_arm_swp(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let base_addr = self.get_reg(insn.rn());
+ self.add_cycle();
if insn.transfer_size() == 1 {
- let t = self.load_8(base_addr, sb);
- self.store_8(base_addr, self.get_reg(insn.rm()) as u8, sb);
+ let t = sb.read_8(base_addr);
+ self.N_cycle8(sb, base_addr);
+ sb.write_8(base_addr, self.get_reg(insn.rm()) as u8);
+ self.S_cycle8(sb, base_addr);
self.set_reg(insn.rd(), t as u32);
} else {
- let t = self.load_32(base_addr, sb);
- self.store_32(base_addr, self.get_reg(insn.rm()), sb);
+ let t = sb.read_32(base_addr);
+ self.N_cycle32(sb, base_addr);
+ sb.write_32(base_addr, self.get_reg(insn.rm()));
+ self.S_cycle32(sb, base_addr);
self.set_reg(insn.rd(), t as u32);
}
-
+ self.N_cycle32(sb, self.pc);
Ok(())
}
}
diff --git a/src/core/arm7tdmi/cpu.rs b/src/core/arm7tdmi/cpu.rs
index 4d3cfdb..7f8072b 100644
--- a/src/core/arm7tdmi/cpu.rs
+++ b/src/core/arm7tdmi/cpu.rs
@@ -4,12 +4,12 @@ use ansi_term::{Colour, Style};
pub use super::exception::Exception;
use super::{
- arm::*,
- bus::{Bus, MemoryAccess, MemoryAccessType, MemoryAccessType::*, MemoryAccessWidth::*},
- psr::RegPSR,
- reg_string,
- thumb::ThumbInstruction,
- Addr, CpuMode, CpuResult, CpuState, DecodedInstruction, InstructionDecoder,
+ arm::*, bus::Bus, psr::RegPSR, reg_string, thumb::ThumbInstruction, Addr, CpuMode, CpuResult,
+ CpuState, DecodedInstruction, InstructionDecoder,
+};
+
+use super::super::sysbus::{
+ MemoryAccess, MemoryAccessType, MemoryAccessType::*, MemoryAccessWidth::*, SysBus,
};
#[derive(Debug, PartialEq)]
@@ -125,33 +125,33 @@ impl Core {
}
/// Helper function for "ldr" instruction that handles misaligned addresses
- pub fn ldr_word(&mut self, addr: Addr, bus: &Bus) -> u32 {
+ pub fn ldr_word(&mut self, addr: Addr, bus: &SysBus) -> u32 {
if addr & 0x3 != 0 {
let rotation = (addr & 0x3) << 3;
- let value = self.load_32(addr & !0x3, bus);
+ let value = bus.read_32(addr & !0x3);
self.ror(value, rotation, self.cpsr.C(), false, false)
} else {
- self.load_32(addr, bus)
+ bus.read_32(addr)
}
}
/// Helper function for "ldrh" instruction that handles misaligned addresses
- pub fn ldr_half(&mut self, addr: Addr, bus: &Bus) -> u32 {
+ pub fn ldr_half(&mut self, addr: Addr, bus: &SysBus) -> u32 {
if addr & 0x1 != 0 {
let rotation = (addr & 0x1) << 3;
- let value = self.load_16(addr & !0x1, bus);
+ let value = bus.read_16(addr & !0x1);
self.ror(value as u32, rotation, self.cpsr.C(), false, false)
} else {
- self.load_16(addr, bus) as u32
+ bus.read_16(addr) as u32
}
}
/// Helper function for "ldrsh" instruction that handles misaligned addresses
- pub fn ldr_sign_half(&mut self, addr: Addr, bus: &Bus) -> u32 {
+ pub fn ldr_sign_half(&mut self, addr: Addr, bus: &SysBus) -> u32 {
if addr & 0x1 != 0 {
- self.load_8(addr, bus) as i8 as i32 as u32
+ bus.read_8(addr) as i8 as i32 as u32
} else {
- self.load_16(addr, bus) as i16 as i32 as u32
+ bus.read_16(addr) as i16 as i32 as u32
}
}
@@ -194,8 +194,8 @@ impl Core {
}
/// Resets the cpu
- pub fn reset(&mut self) {
- self.exception(Exception::Reset);
+ pub fn reset(&mut self, sb: &mut SysBus) {
+ self.exception(sb, Exception::Reset);
}
pub fn word_size(&self) -> usize {
@@ -214,9 +214,10 @@ impl Core {
self.cycles += 1;
}
- pub fn add_cycles(&mut self, addr: Addr, bus: &Bus, access: MemoryAccess) {
- // println!(" total: {}", addr, access, self.cycles);
- self.cycles += bus.get_cycles(addr, access);
+ pub fn add_cycles(&mut self, addr: Addr, bus: &SysBus, access: MemoryAccess) {
+ let cycles_to_add = 1 + bus.get_cycles(addr, access);
+ // println!(" took: {}", addr, access, cycles_to_add);
+ self.cycles += cycles_to_add;
}
pub fn cycle_type(&self, addr: Addr) -> MemoryAccessType {
@@ -239,45 +240,40 @@ impl Core {
}
}
- pub fn load_32(&mut self, addr: Addr, bus: &Bus) -> u32 {
- self.add_cycles(addr, bus, self.cycle_type(addr) + MemoryAccess32);
- self.memreq = addr;
- bus.read_32(addr)
+ #[allow(non_snake_case)]
+ pub fn S_cycle32(&mut self, sb: &SysBus, addr: u32) {
+ self.cycles += 1;
+ self.cycles += sb.get_cycles(addr, Seq + MemoryAccess32);
}
- pub fn load_16(&mut self, addr: Addr, bus: &Bus) -> u16 {
- let cycle_type = self.cycle_type(addr);
- self.add_cycles(addr, bus, cycle_type + MemoryAccess16);
- self.memreq = addr;
- bus.read_16(addr)
+ #[allow(non_snake_case)]
+ pub fn S_cycle16(&mut self, sb: &SysBus, addr: u32) {
+ self.cycles += 1;
+ self.cycles += sb.get_cycles(addr, Seq + MemoryAccess16);
}
- pub fn load_8(&mut self, addr: Addr, bus: &Bus) -> u8 {
- let cycle_type = self.cycle_type(addr);
- self.add_cycles(addr, bus, cycle_type + MemoryAccess8);
- self.memreq = addr;
- bus.read_8(addr)
+ #[allow(non_snake_case)]
+ pub fn S_cycle8(&mut self, sb: &SysBus, addr: u32) {
+ self.cycles += 1;
+ self.cycles += sb.get_cycles(addr, Seq + MemoryAccess8);
}
- pub fn store_32(&mut self, addr: Addr, value: u32, bus: &mut Bus) {
- let cycle_type = self.cycle_type(addr);
- self.add_cycles(addr, bus, cycle_type + MemoryAccess32);
- self.memreq = addr;
- bus.write_32(addr, value);
+ #[allow(non_snake_case)]
+ pub fn N_cycle32(&mut self, sb: &SysBus, addr: u32) {
+ self.cycles += 1;
+ self.cycles += sb.get_cycles(addr, NonSeq + MemoryAccess32);
}
- pub fn store_16(&mut self, addr: Addr, value: u16, bus: &mut Bus) {
- let cycle_type = self.cycle_type(addr);
- self.add_cycles(addr, bus, cycle_type + MemoryAccess16);
- self.memreq = addr;
- bus.write_16(addr, value);
+ #[allow(non_snake_case)]
+ pub fn N_cycle16(&mut self, sb: &SysBus, addr: u32) {
+ self.cycles += 1;
+ self.cycles += sb.get_cycles(addr, NonSeq + MemoryAccess16);
}
- pub fn store_8(&mut self, addr: Addr, value: u8, bus: &mut Bus) {
- let cycle_type = self.cycle_type(addr);
- self.add_cycles(addr, bus, cycle_type + MemoryAccess8);
- self.memreq = addr;
- bus.write_8(addr, value);
+ #[allow(non_snake_case)]
+ pub fn N_cycle8(&mut self, sb: &SysBus, addr: u32) {
+ self.cycles += 1;
+ self.cycles += sb.get_cycles(addr, NonSeq + MemoryAccess8);
}
pub fn check_arm_cond(&self, cond: ArmCond) -> bool {
@@ -301,13 +297,16 @@ impl Core {
}
}
- pub fn exec_swi(&mut self) -> CpuExecResult {
- self.exception(Exception::SoftwareInterrupt);
- self.flush_pipeline();
+ pub fn exec_swi(&mut self, sb: &mut SysBus) -> CpuExecResult {
+ match self.cpsr.state() {
+ CpuState::ARM => self.N_cycle32(sb, self.pc),
+ CpuState::THUMB => self.N_cycle16(sb, self.pc),
+ };
+ self.exception(sb, Exception::SoftwareInterrupt);
Ok(())
}
- fn step_arm_exec(&mut self, insn: u32, sb: &mut Bus) -> CpuResult<()> {
+ fn step_arm_exec(&mut self, insn: u32, sb: &mut SysBus) -> CpuResult<()> {
let pc = self.pc;
match self.pipeline_state {
PipelineState::Refill1 => {
@@ -331,11 +330,11 @@ impl Core {
Ok(())
}
- fn arm(&mut self, sb: &mut Bus) -> CpuResult<()> {
+ fn arm(&mut self, sb: &mut SysBus) -> CpuResult<()> {
let pc = self.pc;
// fetch
- let fetched_now = self.load_32(pc, sb);
+ let fetched_now = sb.read_32(pc);
let executed_now = self.decoded_arm;
// decode
@@ -351,7 +350,7 @@ impl Core {
self.pipeline_state == PipelineState::Refill1
}
- fn step_thumb_exec(&mut self, insn: u16, sb: &mut Bus) -> CpuResult<()> {
+ fn step_thumb_exec(&mut self, insn: u16, sb: &mut SysBus) -> CpuResult<()> {
let pc = self.pc;
match self.pipeline_state {
PipelineState::Refill1 => {
@@ -375,11 +374,11 @@ impl Core {
Ok(())
}
- fn thumb(&mut self, sb: &mut Bus) -> CpuResult<()> {
+ fn thumb(&mut self, sb: &mut SysBus) -> CpuResult<()> {
let pc = self.pc;
// fetch
- let fetched_now = self.load_16(pc, sb);
+ let fetched_now = sb.read_16(pc);
let executed_now = self.decoded_thumb;
// decode
@@ -391,13 +390,23 @@ impl Core {
Ok(())
}
- pub fn flush_pipeline(&mut self) {
+ pub fn flush_pipeline(&mut self, sb: &mut SysBus) {
self.pipeline_state = PipelineState::Refill1;
+ match self.cpsr.state() {
+ CpuState::ARM => {
+ self.N_cycle32(sb, self.pc);
+ self.S_cycle32(sb, self.pc + 4);
+ }
+ CpuState::THUMB => {
+ self.N_cycle16(sb, self.pc);
+ self.S_cycle16(sb, self.pc + 2);
+ }
+ }
}
/// Perform a pipeline step
/// If an instruction was executed in this step, return it.
- pub fn step(&mut self, bus: &mut Bus) -> CpuResult<()> {
+ pub fn step(&mut self, bus: &mut SysBus) -> CpuResult<()> {
match self.cpsr.state() {
CpuState::ARM => self.arm(bus),
CpuState::THUMB => self.thumb(bus),
@@ -417,7 +426,7 @@ impl Core {
/// A step that returns only once an instruction was executed.
/// Returns the address of PC before executing an instruction,
/// and the address of the next instruction to be executed;
- pub fn step_one(&mut self, bus: &mut Bus) -> CpuResult {
+ pub fn step_one(&mut self, bus: &mut SysBus) -> CpuResult {
loop {
match self.pipeline_state {
PipelineState::Execute => {
diff --git a/src/core/arm7tdmi/exception.rs b/src/core/arm7tdmi/exception.rs
index aedfc25..9ee9a39 100644
--- a/src/core/arm7tdmi/exception.rs
+++ b/src/core/arm7tdmi/exception.rs
@@ -1,5 +1,7 @@
+use super::super::sysbus::SysBus;
+use super::cpu::Core;
use super::REG_LR;
-use super::{cpu::Core, CpuMode, CpuState};
+use super::{CpuMode, CpuState};
use colored::*;
#[derive(Debug, Clone, Copy, PartialEq)]
@@ -31,7 +33,7 @@ impl From for CpuMode {
}
impl Core {
- pub fn exception(&mut self, e: Exception) {
+ pub fn exception(&mut self, sb: &mut SysBus, e: Exception) {
let vector = e as u32;
let new_mode = CpuMode::from(e);
if self.verbose {
@@ -58,6 +60,6 @@ impl Core {
// Set PC to vector address
self.pc = vector;
- self.flush_pipeline();
+ self.flush_pipeline(sb);
}
}
diff --git a/src/core/arm7tdmi/thumb/exec.rs b/src/core/arm7tdmi/thumb/exec.rs
index 896df06..5e77ff7 100644
--- a/src/core/arm7tdmi/thumb/exec.rs
+++ b/src/core/arm7tdmi/thumb/exec.rs
@@ -1,16 +1,17 @@
use crate::core::arm7tdmi::bus::Bus;
use crate::core::arm7tdmi::cpu::{Core, CpuExecResult};
use crate::core::arm7tdmi::*;
+use crate::core::sysbus::SysBus;
use super::*;
-fn push(cpu: &mut Core, bus: &mut Bus, r: usize) {
+fn push(cpu: &mut Core, bus: &mut SysBus, r: usize) {
cpu.gpr[REG_SP] -= 4;
let stack_addr = cpu.gpr[REG_SP];
- cpu.store_32(stack_addr, cpu.get_reg(r), bus)
+ bus.write_32(stack_addr, cpu.get_reg(r))
}
-fn pop(cpu: &mut Core, bus: &mut Bus, r: usize) {
+fn pop(cpu: &mut Core, bus: &mut SysBus, r: usize) {
let stack_addr = cpu.gpr[REG_SP];
- let val = cpu.load_32(stack_addr, bus);
+ let val = bus.read_32(stack_addr);
cpu.set_reg(r, val);
cpu.gpr[REG_SP] = stack_addr + 4;
}
@@ -18,7 +19,7 @@ fn pop(cpu: &mut Core, bus: &mut Bus, r: usize) {
impl Core {
fn exec_thumb_move_shifted_reg(
&mut self,
- _bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
let op2 = self
@@ -37,11 +38,11 @@ impl Core {
if let Some(result) = result {
self.set_reg(rd, result as u32);
}
-
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
- fn exec_thumb_add_sub(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_add_sub(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let op1 = self.get_reg(insn.rs()) as i32;
let op2 = if insn.is_immediate_operand() {
insn.rn() as u32 as i32
@@ -58,13 +59,13 @@ impl Core {
if let Some(result) = result {
self.set_reg(insn.rd(), result as u32);
}
-
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
fn exec_thumb_data_process_imm(
&mut self,
- _bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
let arm_alu_op: AluOpCode = insn.format3_op().into();
@@ -74,11 +75,11 @@ impl Core {
if let Some(result) = result {
self.set_reg(insn.rd(), result as u32);
}
-
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
- fn exec_thumb_mul(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_mul(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let op1 = self.get_reg(insn.rd()) as i32;
let op2 = self.get_reg(insn.rs()) as i32;
let m = self.get_required_multipiler_array_cycles(op2);
@@ -89,10 +90,11 @@ impl Core {
self.cpsr.set_N((result as i32) < 0);
self.cpsr.set_Z(result == 0);
self.gpr[insn.rd()] = result;
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
- fn exec_thumb_alu_ops(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_alu_ops(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let rd = insn.rd();
let (arm_alu_op, shft) = insn.alu_opcode();
@@ -107,27 +109,27 @@ impl Core {
if let Some(result) = result {
self.set_reg(rd, result as u32);
}
-
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
/// Cycles 2S+1N
- fn exec_thumb_bx(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_bx(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let src_reg = if insn.flag(ThumbInstruction::FLAG_H2) {
insn.rs() + 8
} else {
insn.rs()
};
- self.branch_exchange(self.get_reg(src_reg))
+ self.branch_exchange(sb, self.get_reg(src_reg))
}
fn exec_thumb_hi_reg_op_or_bx(
&mut self,
- bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
if OpFormat5::BX == insn.format5_op() {
- self.exec_thumb_bx(bus, insn)
+ self.exec_thumb_bx(sb, insn)
} else {
let dst_reg = if insn.flag(ThumbInstruction::FLAG_H1) {
insn.rd() + 8
@@ -151,16 +153,19 @@ impl Core {
if let Some(result) = alu_res {
self.set_reg(dst_reg, result as u32);
if dst_reg == REG_PC {
- self.flush_pipeline();
+ self.flush_pipeline(sb);
}
}
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
}
- fn exec_thumb_ldr_pc(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_ldr_pc(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let addr = (insn.pc & !0b10) + 4 + (insn.word8() as Addr);
- let data = self.load_32(addr, bus);
+ self.S_cycle16(sb, self.pc + 2);
+ let data = sb.read_32(addr);
+ self.N_cycle16(sb, addr);
self.set_reg(insn.rd(), data);
// +1I
@@ -171,15 +176,17 @@ impl Core {
fn do_exec_thumb_ldr_str(
&mut self,
- bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
addr: Addr,
) -> CpuExecResult {
if insn.is_load() {
let data = if insn.is_transferring_bytes() {
- self.load_8(addr, bus) as u32
+ self.S_cycle8(sb, addr);
+ sb.read_8(addr) as u32
} else {
- self.ldr_word(addr, bus)
+ self.S_cycle32(sb, addr);
+ self.ldr_word(addr, sb)
};
self.set_reg(insn.rd(), data);
@@ -189,18 +196,21 @@ impl Core {
} else {
let value = self.get_reg(insn.rd());
if insn.is_transferring_bytes() {
- self.store_8(addr, value as u8, bus);
+ self.N_cycle8(sb, addr);
+ sb.write_8(addr, value as u8);
} else {
- self.store_32(addr, value, bus);
+ self.N_cycle32(sb, addr);
+ sb.write_32(addr, value);
};
}
+ self.N_cycle16(sb, self.pc + 2);
Ok(())
}
fn exec_thumb_ldr_str_reg_offset(
&mut self,
- bus: &mut Bus,
+ bus: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
let addr = self
@@ -209,7 +219,7 @@ impl Core {
self.do_exec_thumb_ldr_str(bus, insn, addr)
}
- fn exec_thumb_ldr_str_shb(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_ldr_str_shb(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let addr = self
.get_reg(insn.rb())
.wrapping_add(self.get_reg(insn.ro()));
@@ -221,33 +231,41 @@ impl Core {
(false, false) =>
/* strh */
{
- self.store_16(addr, self.gpr[rd] as u16, bus)
+ sb.write_16(addr, self.gpr[rd] as u16);
+ self.N_cycle16(sb, addr);
}
(false, true) =>
/* ldrh */
{
- self.gpr[rd] = self.ldr_half(addr, bus)
+ self.gpr[rd] = self.ldr_half(addr, sb);
+ self.S_cycle16(sb, addr);
+ self.add_cycle();
}
(true, false) =>
/* ldsb */
{
- let val = self.load_8(addr, bus) as i8 as i32 as u32;
+ let val = sb.read_8(addr) as i8 as i32 as u32;
self.gpr[rd] = val;
+ self.S_cycle8(sb, addr);
+ self.add_cycle();
}
(true, true) =>
/* ldsh */
{
- let val = self.ldr_sign_half(addr, bus);
+ let val = self.ldr_sign_half(addr, sb);
self.gpr[rd] = val;
+ self.S_cycle16(sb, addr);
+ self.add_cycle();
}
}
+ self.N_cycle16(sb, self.pc + 2);
Ok(())
}
fn exec_thumb_ldr_str_imm_offset(
&mut self,
- bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
let offset = if insn.is_transferring_bytes() {
@@ -256,92 +274,115 @@ impl Core {
(insn.offset5() << 3) >> 1
};
let addr = self.get_reg(insn.rb()).wrapping_add(offset as u32);
- self.do_exec_thumb_ldr_str(bus, insn, addr)
+ self.do_exec_thumb_ldr_str(sb, insn, addr)
}
fn exec_thumb_ldr_str_halfword(
&mut self,
- bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
let base = self.gpr[insn.rb()] as i32;
let addr = base.wrapping_add((insn.offset5() << 1) as i32) as Addr;
if insn.is_load() {
- let data = self.ldr_half(addr, bus);
+ let data = self.ldr_half(addr, sb);
+ self.S_cycle16(sb, addr);
self.add_cycle();
self.gpr[insn.rd()] = data as u32;
} else {
- self.store_16(addr, self.gpr[insn.rd()] as u16, bus);
+ sb.write_16(addr, self.gpr[insn.rd()] as u16);
+ self.N_cycle16(sb, addr);
}
+ self.N_cycle16(sb, self.pc + 2);
Ok(())
}
- fn exec_thumb_ldr_str_sp(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_ldr_str_sp(&mut self, bus: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let addr = self.gpr[REG_SP] + (insn.word8() as Addr);
self.do_exec_thumb_ldr_str_with_addr(bus, insn, addr)
}
- fn exec_thumb_load_address(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_load_address(
+ &mut self,
+ sb: &mut SysBus,
+ insn: ThumbInstruction,
+ ) -> CpuExecResult {
let result = if insn.flag(ThumbInstruction::FLAG_SP) {
self.gpr[REG_SP] + (insn.word8() as Addr)
} else {
(insn.pc & !0b10) + 4 + (insn.word8() as Addr)
};
self.gpr[insn.rd()] = result;
-
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
fn do_exec_thumb_ldr_str_with_addr(
&mut self,
- bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
addr: Addr,
) -> CpuExecResult {
if insn.is_load() {
- let data = self.load_32(addr, bus);
+ let data = sb.read_32(addr);
+ self.S_cycle16(sb, addr);
self.add_cycle();
self.gpr[insn.rd()] = data;
} else {
- self.store_32(addr, self.gpr[insn.rd()], bus);
+ sb.write_32(addr, self.gpr[insn.rd()]);
+ self.N_cycle16(sb, addr);
}
+ self.N_cycle16(sb, self.pc + 2);
Ok(())
}
- fn exec_thumb_add_sp(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_add_sp(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let op1 = self.gpr[REG_SP] as i32;
let op2 = insn.sword7();
let arm_alu_op = AluOpCode::ADD;
self.gpr[REG_SP] = self.alu(arm_alu_op, op1, op2) as u32;
-
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
}
- fn exec_thumb_push_pop(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_push_pop(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
// (From GBATEK) Execution Time: nS+1N+1I (POP), (n+1)S+2N+1I (POP PC), or (n-1)S+2N (PUSH).
let is_pop = insn.is_load();
let pc_lr_flag = insn.flag(ThumbInstruction::FLAG_R);
let rlist = insn.register_list();
+ self.N_cycle16(sb, self.pc);
+ let mut first = true;
if is_pop {
for r in 0..8 {
if rlist.bit(r) {
- pop(self, bus, r);
+ pop(self, sb, r);
+ if first {
+ self.add_cycle();
+ first = false;
+ } else {
+ self.S_cycle16(sb, self.gpr[REG_SP]);
+ }
}
}
if pc_lr_flag {
- pop(self, bus, REG_PC);
+ pop(self, sb, REG_PC);
self.pc = self.pc & !1;
- self.flush_pipeline();
+ self.flush_pipeline(sb);
}
- self.add_cycle();
+ self.S_cycle16(sb, self.pc + 2);
} else {
if pc_lr_flag {
- push(self, bus, REG_LR);
+ push(self, sb, REG_LR);
}
for r in (0..8).rev() {
if rlist.bit(r) {
- push(self, bus, r);
+ push(self, sb, r);
+ if first {
+ first = false;
+ } else {
+ self.S_cycle16(sb, self.gpr[REG_SP]);
+ }
}
}
}
@@ -349,7 +390,7 @@ impl Core {
Ok(())
}
- fn exec_thumb_ldm_stm(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_ldm_stm(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
// (From GBATEK) Execution Time: nS+1N+1I (POP), (n+1)S+2N+1I (POP PC), or (n-1)S+2N (PUSH).
let is_load = insn.is_load();
@@ -357,19 +398,33 @@ impl Core {
let mut addr = self.gpr[rb];
let rlist = insn.register_list();
+ self.N_cycle16(sb, self.pc);
+ let mut first = true;
if is_load {
for r in 0..8 {
if rlist.bit(r) {
- let val = self.load_32(addr, bus);
+ let val = sb.read_32(addr);
+ if first {
+ first = false;
+ self.add_cycle();
+ } else {
+ self.S_cycle16(sb, addr);
+ }
addr += 4;
self.add_cycle();
self.set_reg(r, val);
}
}
+ self.S_cycle16(sb, self.pc + 2);
} else {
for r in 0..8 {
if rlist.bit(r) {
- self.store_32(addr, self.gpr[r], bus);
+ if first {
+ first = false;
+ } else {
+ self.S_cycle16(sb, addr);
+ }
+ sb.write_32(addr, self.gpr[r]);
addr += 4;
}
}
@@ -382,49 +437,53 @@ impl Core {
fn exec_thumb_branch_with_cond(
&mut self,
- _bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
if !self.check_arm_cond(insn.cond()) {
+ self.S_cycle16(sb, self.pc + 2);
Ok(())
} else {
let offset = insn.bcond_offset();
+ self.S_cycle16(sb, self.pc);
self.pc = (self.pc as i32).wrapping_add(offset) as u32;
- self.flush_pipeline();
+ self.flush_pipeline(sb);
Ok(())
}
}
- fn exec_thumb_branch(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ fn exec_thumb_branch(&mut self, sb: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
let offset = ((insn.offset11() << 21) >> 20) as i32;
self.pc = (self.pc as i32).wrapping_add(offset) as u32;
- self.flush_pipeline();
+ self.S_cycle16(sb, self.pc);
+ self.flush_pipeline(sb);
Ok(())
}
fn exec_thumb_branch_long_with_link(
&mut self,
- _bus: &mut Bus,
+ sb: &mut SysBus,
insn: ThumbInstruction,
) -> CpuExecResult {
let mut off = insn.offset11();
if insn.flag(ThumbInstruction::FLAG_LOW_OFFSET) {
+ self.S_cycle16(sb, self.pc);
off = off << 1;
let next_pc = (self.pc - 2) | 1;
self.pc = ((self.gpr[REG_LR] & !1) as i32).wrapping_add(off) as u32;
self.gpr[REG_LR] = next_pc;
- self.flush_pipeline();
+ self.flush_pipeline(sb);
Ok(())
} else {
off = (off << 21) >> 9;
self.gpr[REG_LR] = (self.pc as i32).wrapping_add(off) as u32;
-
+ self.S_cycle16(sb, self.pc);
Ok(())
}
}
- pub fn exec_thumb(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
+ pub fn exec_thumb(&mut self, bus: &mut SysBus, insn: ThumbInstruction) -> CpuExecResult {
match insn.fmt {
ThumbFormat::MoveShiftedReg => self.exec_thumb_move_shifted_reg(bus, insn),
ThumbFormat::AddSub => self.exec_thumb_add_sub(bus, insn),
@@ -443,7 +502,7 @@ impl Core {
ThumbFormat::PushPop => self.exec_thumb_push_pop(bus, insn),
ThumbFormat::LdmStm => self.exec_thumb_ldm_stm(bus, insn),
ThumbFormat::BranchConditional => self.exec_thumb_branch_with_cond(bus, insn),
- ThumbFormat::Swi => self.exec_swi(),
+ ThumbFormat::Swi => self.exec_swi(bus),
ThumbFormat::Branch => self.exec_thumb_branch(bus, insn),
ThumbFormat::BranchLongWithLink => self.exec_thumb_branch_long_with_link(bus, insn),
}
diff --git a/src/core/gba.rs b/src/core/gba.rs
index 3eefd16..8fd4359 100644
--- a/src/core/gba.rs
+++ b/src/core/gba.rs
@@ -93,7 +93,7 @@ impl GameBoyAdvance {
if !self.cpu.cpsr.irq_disabled() {
io.intc.request_irqs(irqs);
if io.intc.irq_pending() {
- self.cpu.exception(Exception::Irq);
+ self.cpu.exception(&mut self.sysbus, Exception::Irq);
}
}
}
@@ -105,7 +105,7 @@ impl GameBoyAdvance {
self.emulate_peripherals(cycles);
- if self.io.borrow().gpu.state == GpuState::HBlank {
+ if self.io.borrow().gpu.state == GpuState::VBlank {
self.backend.render(self.io.borrow().gpu.render());
}
diff --git a/src/core/gpu.rs b/src/core/gpu.rs
index 114c664..51d2e26 100644
--- a/src/core/gpu.rs
+++ b/src/core/gpu.rs
@@ -350,8 +350,8 @@ impl Gpu {
}
}
BGMode::BGMode2 => {
- self.scanline_mode0(2, sb);
self.scanline_mode0(3, sb);
+ self.scanline_mode0(2, sb);
}
BGMode::BGMode3 => {
self.scanline_mode3(2, sb);
diff --git a/src/core/ioregs.rs b/src/core/ioregs.rs
index a168a3c..dc55b6c 100644
--- a/src/core/ioregs.rs
+++ b/src/core/ioregs.rs
@@ -3,8 +3,8 @@ use std::rc::Rc;
use super::arm7tdmi::{Addr, Bus};
use super::gba::IoDevices;
-use super::sysbus::BoxedMemory;
use super::keypad;
+use super::sysbus::BoxedMemory;
pub mod consts {
use super::*;
@@ -188,9 +188,7 @@ impl Bus for IoRegs {
REG_POSTFLG => self.post_boot_flag as u16,
REG_HALTCNT => 0,
REG_KEYINPUT => self.keyinput as u16,
- _ => {
- self.mem.read_16(addr)
- }
+ _ => self.mem.read_16(addr),
}
}
diff --git a/src/core/sysbus.rs b/src/core/sysbus.rs
index 0ef4358..e96f82c 100644
--- a/src/core/sysbus.rs
+++ b/src/core/sysbus.rs
@@ -232,39 +232,33 @@ impl SysBus {
// TODO handle EWRAM accesses
match addr & 0xff000000 {
- EWRAM_ADDR => {
- match access.1 {
- MemoryAccessWidth::MemoryAccess32 => cycles += 6,
- _ => cycles += 3
- }
- }
+ EWRAM_ADDR => match access.1 {
+ MemoryAccessWidth::MemoryAccess32 => cycles += 6,
+ _ => cycles += 3,
+ },
OAM_ADDR | VRAM_ADDR | PALRAM_ADDR => {
match access.1 {
MemoryAccessWidth::MemoryAccess32 => cycles += 2,
- _ => cycles += 1
+ _ => cycles += 1,
}
if self.io.borrow().gpu.state == GpuState::HDraw {
cycles += 1;
}
}
- GAMEPAK_WS0_ADDR => {
- match access.0 {
- MemoryAccessType::NonSeq => {
- match access.1 {
- MemoryAccessWidth::MemoryAccess32 => {
- cycles += nonseq_cycles[self.ioregs.waitcnt.ws0_first_access() as usize];
- cycles += seq_cycles[self.ioregs.waitcnt.ws0_second_access() as usize];
- }
- _ => {
- cycles += nonseq_cycles[self.ioregs.waitcnt.ws0_first_access() as usize];
- }
- }
- }
- MemoryAccessType::Seq => {
+ GAMEPAK_WS0_ADDR => match access.0 {
+ MemoryAccessType::NonSeq => match access.1 {
+ MemoryAccessWidth::MemoryAccess32 => {
+ cycles += nonseq_cycles[self.ioregs.waitcnt.ws0_first_access() as usize];
+ cycles += seq_cycles[self.ioregs.waitcnt.ws0_second_access() as usize];
+ }
+ _ => {
+ cycles += nonseq_cycles[self.ioregs.waitcnt.ws0_first_access() as usize];
+ }
+ },
+ MemoryAccessType::Seq => {
+ cycles += seq_cycles[self.ioregs.waitcnt.ws0_second_access() as usize];
+ if access.1 == MemoryAccessWidth::MemoryAccess32 {
cycles += seq_cycles[self.ioregs.waitcnt.ws0_second_access() as usize];
- if access.1 == MemoryAccessWidth::MemoryAccess32 {
- cycles += seq_cycles[self.ioregs.waitcnt.ws0_second_access() as usize];
- }
}
}
},
diff --git a/src/debugger/command.rs b/src/debugger/command.rs
index 3322900..6cd2ca0 100644
--- a/src/debugger/command.rs
+++ b/src/debugger/command.rs
@@ -49,61 +49,61 @@ impl Command {
DisplayInfo => println!("GPU: {:#?}", debugger.gba.io.borrow().gpu),
Step(count) => {
for _ in 0..count {
- if let Some(bp) = debugger.check_breakpoint() {
- println!("hit breakpoint #0x{:08x}!", bp);
- debugger.delete_breakpoint(bp);
- } else {
- match debugger.gba.step() {
- Ok(insn) => {
- print!(
- "{}\t{}",
- Colour::Black
- .bold()
- .italic()
- .on(Colour::White)
- .paint(format!("Executed at @0x{:08x}:", insn.get_pc(),)),
- insn
- );
- println!(
- "{}",
- Colour::Purple.dimmed().italic().paint(format!(
- "\t\t/// Next instruction at @0x{:08x}",
- debugger.gba.cpu.get_next_pc()
- ))
- )
- }
- Err(GBAError::CpuError(e)) => {
- println!("{}: {}", "cpu encountered an error".red(), e);
- println!("cpu: {:x?}", debugger.gba.cpu)
- }
- _ => unreachable!(),
+ match debugger.gba.step() {
+ Ok(insn) => {
+ print!(
+ "{}\t{}",
+ Colour::Black
+ .bold()
+ .italic()
+ .on(Colour::White)
+ .paint(format!("Executed at @0x{:08x}:", insn.get_pc(),)),
+ insn
+ );
+ println!(
+ "{}",
+ Colour::Purple.dimmed().italic().paint(format!(
+ "\t\t/// Next instruction at @0x{:08x}",
+ debugger.gba.cpu.get_next_pc()
+ ))
+ )
}
+ Err(GBAError::CpuError(e)) => {
+ println!("{}: {}", "cpu encountered an error".red(), e);
+ println!("cpu: {:x?}", debugger.gba.cpu)
+ }
+ _ => unreachable!(),
}
}
println!("{}\n", debugger.gba.cpu);
}
- Continue => loop {
- if let Some(bp) = debugger.check_breakpoint() {
- println!("hit breakpoint #0x{:08x}!", bp);
- debugger.delete_breakpoint(bp);
- break;
- }
- match debugger.gba.step() {
- // Ok(insn) => {
- // println!(
- // "@0x{:08x}:\t{}",
- // insn.get_pc(),
- // Colour::Yellow.italic().paint(format!("{} ", insn))
- // );
- // }
- Err(GBAError::CpuError(e)) => {
- println!("{}: {}", "cpu encountered an error".red(), e);
- println!("cpu: {:x?}", debugger.gba.cpu);
+ Continue => {
+ let start_cycles = debugger.gba.cpu.cycles();
+ loop {
+ if let Some(bp) = debugger.check_breakpoint() {
+ match debugger.gba.step() {
+ Err(GBAError::CpuError(e)) => {
+ println!("{}: {}", "cpu encountered an error".red(), e);
+ println!("cpu: {:x?}", debugger.gba.cpu);
+ break;
+ }
+ _ => (),
+ };
+ let num_cycles = debugger.gba.cpu.cycles() - start_cycles;
+ println!("hit breakpoint #0x{:08x} after {} cycles !", bp, num_cycles);
break;
+ } else {
+ match debugger.gba.step() {
+ Err(GBAError::CpuError(e)) => {
+ println!("{}: {}", "cpu encountered an error".red(), e);
+ println!("cpu: {:x?}", debugger.gba.cpu);
+ break;
+ }
+ _ => (),
+ };
}
- _ => (),
- };
- },
+ }
+ }
Frame(count) => {
use super::time::PreciseTime;
let start = PreciseTime::now();
@@ -160,7 +160,7 @@ impl Command {
TileView(bg) => create_tile_view(bg, &debugger.gba),
Reset => {
println!("resetting cpu...");
- debugger.gba.cpu.reset();
+ debugger.gba.cpu.reset(&mut debugger.gba.sysbus);
println!("cpu is restarted!")
}
}