Skip to content

Commit

Permalink
Performance improvements for sm83 cpu
Browse files Browse the repository at this point in the history
  • Loading branch information
Javier-varez committed May 22, 2024
1 parent d9fdcd2 commit a23533a
Showing 1 changed file with 62 additions and 63 deletions.
125 changes: 62 additions & 63 deletions sm83/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ const fn translate_irq_target(interrupt: Interrupt) -> u16 {

/// Clock cycles, not machine cycles
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Cycles(usize);

impl Cycles {
Expand Down Expand Up @@ -468,85 +469,85 @@ impl Cpu {
}

const fn get_flag(&self, flag: Flag) -> bool {
self.get_regs().flags.is_flag_set(flag)
self.regs.flags.is_flag_set(flag)
}

const fn get_flags(&self) -> Flags {
self.get_regs().flags
self.regs.flags
}

fn set_flags(&mut self, flags: Flags) {
self.get_mut_regs().flags = flags;
self.regs.flags = flags;
}

const fn get_reg(&self, reg: Register) -> u8 {
let regs = self.get_regs();
match reg {
Register::A => regs.a_reg,
Register::B => regs.b_reg,
Register::C => regs.c_reg,
Register::D => regs.d_reg,
Register::E => regs.e_reg,
Register::H => regs.h_reg,
Register::L => regs.l_reg,
Register::A => self.regs.a_reg,
Register::B => self.regs.b_reg,
Register::C => self.regs.c_reg,
Register::D => self.regs.d_reg,
Register::E => self.regs.e_reg,
Register::H => self.regs.h_reg,
Register::L => self.regs.l_reg,
}
}

fn set_reg(&mut self, reg: Register, value: u8) {
let regs = self.get_mut_regs();
let target = match reg {
Register::A => &mut regs.a_reg,
Register::B => &mut regs.b_reg,
Register::C => &mut regs.c_reg,
Register::D => &mut regs.d_reg,
Register::E => &mut regs.e_reg,
Register::H => &mut regs.h_reg,
Register::L => &mut regs.l_reg,
Register::A => &mut self.regs.a_reg,
Register::B => &mut self.regs.b_reg,
Register::C => &mut self.regs.c_reg,
Register::D => &mut self.regs.d_reg,
Register::E => &mut self.regs.e_reg,
Register::H => &mut self.regs.h_reg,
Register::L => &mut self.regs.l_reg,
};
*target = value;
}

fn get_reg_pair(&mut self, reg: RegisterPair) -> u16 {
let regs = self.get_regs();
let (hi, lo) = match reg {
RegisterPair::BC => (regs.b_reg, regs.c_reg),
RegisterPair::DE => (regs.d_reg, regs.e_reg),
RegisterPair::BC => (self.regs.b_reg, self.regs.c_reg),
RegisterPair::DE => (self.regs.d_reg, self.regs.e_reg),
RegisterPair::HL | RegisterPair::HLINC | RegisterPair::HLDEC => {
(regs.h_reg, regs.l_reg)
(self.regs.h_reg, self.regs.l_reg)
}
RegisterPair::SP => {
return regs.sp_reg;
return self.regs.sp_reg;
}
RegisterPair::AF => (regs.a_reg, regs.flags.0),
RegisterPair::AF => (self.regs.a_reg, self.regs.flags.0),
};
let value = ((hi as u16) << 8) | (lo as u16);

match reg {
RegisterPair::HLINC => {
self.set_reg_pair(RegisterPair::HL, value.wrapping_add(1));
let value = value.wrapping_add(1);
self.regs.h_reg = (value >> 8) as u8;
self.regs.l_reg = (value & 0xFF) as u8;
}
RegisterPair::HLDEC => {
self.set_reg_pair(RegisterPair::HL, value.wrapping_sub(1));
let value = value.wrapping_sub(1);
self.regs.h_reg = (value >> 8) as u8;
self.regs.l_reg = (value & 0xFF) as u8;
}
_ => {}
}
value
}

fn set_reg_pair(&mut self, reg: RegisterPair, value: u16) {
let regs = self.get_mut_regs();
let (hi, lo) = match reg {
RegisterPair::BC => (&mut regs.b_reg, &mut regs.c_reg),
RegisterPair::DE => (&mut regs.d_reg, &mut regs.e_reg),
RegisterPair::BC => (&mut self.regs.b_reg, &mut self.regs.c_reg),
RegisterPair::DE => (&mut self.regs.d_reg, &mut self.regs.e_reg),
RegisterPair::HL | RegisterPair::HLINC | RegisterPair::HLDEC => {
(&mut regs.h_reg, &mut regs.l_reg)
(&mut self.regs.h_reg, &mut self.regs.l_reg)
}
RegisterPair::SP => {
regs.sp_reg = value;
self.regs.sp_reg = value;
return;
}
RegisterPair::AF => {
let (hi, lo) = (&mut regs.a_reg, &mut regs.flags);
let (hi, lo) = (&mut self.regs.a_reg, &mut self.regs.flags);
*hi = ((value >> 8) & 0xff) as u8;
*lo = ((value & 0xf0) as u8).into(); // lo-bits are hardcoded to 0
return;
Expand All @@ -558,9 +559,8 @@ impl Cpu {

#[cfg_attr(feature = "profile", inline(never))]
fn step_pc(&mut self) -> u16 {
let regs = self.get_mut_regs();
let pc = regs.pc_reg;
regs.pc_reg = regs.pc_reg.wrapping_add(1);
let pc = self.regs.pc_reg;
self.regs.pc_reg = self.regs.pc_reg.wrapping_add(1);
pc
}

Expand Down Expand Up @@ -590,23 +590,23 @@ impl Cpu {

#[cfg_attr(feature = "profile", inline(never))]
fn stack_push<T: Memory>(&mut self, memory: &mut T, value: u16) {
let sp = self.get_reg_pair(RegisterPair::SP);
let sp = self.regs.sp_reg;
let pos = sp.wrapping_sub(1);
memory.write(pos, (value >> 8) as u8);
let pos = pos.wrapping_sub(1);
memory.write(pos, (value & 0xff) as u8);
self.set_reg_pair(RegisterPair::SP, pos);
self.regs.sp_reg = pos;
}

#[cfg_attr(feature = "profile", inline(never))]
fn stack_pop<T: Memory>(&mut self, memory: &mut T) -> u16 {
let sp = self.get_reg_pair(RegisterPair::SP);
let sp = self.regs.sp_reg;
let pos = sp;
let lo = memory.read(pos);
let pos = pos.wrapping_add(1);
let hi = memory.read(pos);
let pos = pos.wrapping_add(1);
self.set_reg_pair(RegisterPair::SP, pos);
self.regs.sp_reg = pos;
(lo as u16) | ((hi as u16) << 8)
}

Expand Down Expand Up @@ -639,9 +639,9 @@ impl Cpu {
.and_then(|irq| if self.regs.irq_en { Some(irq) } else { None })
{
self.regs.irq_en = false;
let return_addr = self.get_regs().pc_reg;
let return_addr = self.regs.pc_reg;
self.stack_push(memory, return_addr);
self.get_mut_regs().pc_reg = translate_irq_target(irq);
self.regs.pc_reg = translate_irq_target(irq);
ExitReason::InterruptTaken(Cycles::new(20), irq)
} else {
let instruction = self.fetch_and_decode(memory);
Expand Down Expand Up @@ -783,7 +783,7 @@ impl Cpu {
}
}
OpCode::Ld16HlSpImm => {
let sp = self.get_regs().sp_reg;
let sp = self.regs.sp_reg;
let imm = self.read_8_bit_immediate(memory) as i8 as i16;
let value = ((sp as i16).wrapping_add(imm)) as u16;
self.set_reg_pair(RegisterPair::HL, value);
Expand Down Expand Up @@ -996,85 +996,84 @@ impl Cpu {
}
OpCode::JrImm(None) => {
let target_offset = self.read_8_bit_immediate(memory) as i8 as i16;
let pc = self.get_regs().pc_reg;
let pc = self.regs.pc_reg;
let target = (pc as i16).wrapping_add(target_offset) as u16;
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(12)
}
OpCode::JrImm(Some(condition)) => {
let target_offset = self.read_8_bit_immediate(memory) as i8 as i16;
if self.check_condition(condition) {
let pc = self.get_regs().pc_reg;
let pc = self.regs.pc_reg;
let target = (pc as i16).wrapping_add(target_offset) as u16;
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(12)
} else {
Cycles::new(8)
}
}
OpCode::Ret(None) => {
let value = self.stack_pop(memory);
self.get_mut_regs().pc_reg = value;
self.regs.pc_reg = value;
Cycles::new(16)
}
OpCode::Ret(Some(condition)) => {
if self.check_condition(condition) {
let value = self.stack_pop(memory);
self.get_mut_regs().pc_reg = value;
self.regs.pc_reg = value;
Cycles::new(20)
} else {
Cycles::new(8)
}
}
OpCode::Reti => {
let value = self.stack_pop(memory);
let regs = self.get_mut_regs();
regs.pc_reg = value;
regs.irq_en = true;
self.regs.pc_reg = value;
self.regs.irq_en = true;
Cycles::new(16)
}
OpCode::JpImm(Some(condition)) => {
let target = self.read_16_bit_immediate(memory);
if self.check_condition(condition) {
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(16)
} else {
Cycles::new(12)
}
}
OpCode::JpImm(None) => {
let target = self.read_16_bit_immediate(memory);
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(16)
}
OpCode::JpHl => {
let target = self.get_reg_pair(RegisterPair::HL);
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(4)
}
OpCode::CallImm(Some(condition)) => {
let target = self.read_16_bit_immediate(memory);
if self.check_condition(condition) {
let return_addr = self.get_regs().pc_reg;
let return_addr = self.regs.pc_reg;
self.stack_push(memory, return_addr);
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(24)
} else {
Cycles::new(12)
}
}
OpCode::CallImm(None) => {
let target = self.read_16_bit_immediate(memory);
let return_addr = self.get_regs().pc_reg;
let return_addr = self.regs.pc_reg;
self.stack_push(memory, return_addr);
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(24)
}
OpCode::Reset(target) => {
let target = translate_reset_target(target);
let return_addr = self.get_regs().pc_reg;
let return_addr = self.regs.pc_reg;
self.stack_push(memory, return_addr);
self.get_mut_regs().pc_reg = target;
self.regs.pc_reg = target;
Cycles::new(16)
}
OpCode::Pop(reg) => {
Expand All @@ -1088,12 +1087,12 @@ impl Cpu {
Cycles::new(16)
}
OpCode::Di => {
self.get_mut_regs().irq_en = false;
self.regs.irq_en = false;
Cycles::new(4)
}
OpCode::Ei => {
// TODO: make this delayed by 1 instruction
self.get_mut_regs().irq_en = true;
self.regs.irq_en = true;
Cycles::new(4)
}
OpCode::Rlca => {
Expand Down

0 comments on commit a23533a

Please sign in to comment.