From 47a4b0c720243d9d14de675bf46946a342750c04 Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Sun, 29 May 2016 14:18:47 +0200 Subject: [PATCH] Inlining performance critical functions --- src/cpu.rs | 36 ++++++++++++++++++++++++++++++++++++ src/display.rs | 8 +++++++- src/interconnect.rs | 5 +++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/cpu.rs b/src/cpu.rs index 11c1e15..cfb629e 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -58,10 +58,12 @@ impl CPU { } } + #[inline] fn read_byte(&self, addr: u16) -> u8 { self.interconnect.read_byte(addr) } + #[inline] fn load_args(&mut self, num_args: u8) -> Box<[u8]> { let mut args = Vec::new(); for i in 0..num_args { @@ -71,6 +73,7 @@ impl CPU { args.into_boxed_slice() } + #[inline] fn set_8bit_reg(&mut self, reg_id: usize, value: u8) { // Make sure that we skip the (HL) part. if reg_id == REG_N_A { @@ -85,6 +88,7 @@ impl CPU { } } + #[inline] fn get_8bit_reg(&self, reg_id: usize) -> u8 { // Make sure that we skip the (HL) part. if reg_id == REG_N_A { @@ -99,6 +103,7 @@ impl CPU { } } + #[inline] fn run_prefix_instruction(&mut self) { let instruction = self.read_byte(self.ip); self.ip += 1; @@ -464,10 +469,12 @@ impl CPU { } } + #[inline] fn get_pair_value(&self, a: usize, b: usize) -> u16 { (self.get_8bit_reg(a) as u16) << 8 | self.get_8bit_reg(b) as u16 } + #[inline] fn set_pair_value(&mut self, a: usize, b: usize, value: u16) { self.set_8bit_reg(a, (value >> 8) as u8); self.set_8bit_reg(b, value as u8); @@ -479,6 +486,7 @@ impl CPU { } } + #[inline] fn call(&mut self, dst: u16) { let ip = self.ip; self.push(ip); @@ -486,6 +494,7 @@ impl CPU { self.ip = dst; } + #[inline] fn call_condition(&mut self, cond_str: String, cond: bool) -> u8 { let dst = to_u16(self.load_args(2)); if self.debug { @@ -499,6 +508,7 @@ impl CPU { } } + #[inline] fn ret_condition(&mut self, cond_str: String, cond: bool) -> u8 { if self.debug { println!("RET {}", cond_str); @@ -511,6 +521,7 @@ impl CPU { } } + #[inline] fn jmp_r(&mut self, addr: u8) { let off: i8 = addr as i8; if off < 0 { @@ -520,6 +531,7 @@ impl CPU { } } + #[inline] fn jmp_r_condition(&mut self, cond_str: String, cond: bool) -> u8 { let t = self.load_args(1)[0]; if self.debug { @@ -533,10 +545,12 @@ impl CPU { } } + #[inline] fn jmp_p(&mut self, addr: u16) { self.ip = addr; } + #[inline] fn jmp_p_condition(&mut self, cond_str: String, cond: bool) -> u8 { let t = to_u16(self.load_args(2)); if self.debug { @@ -550,6 +564,7 @@ impl CPU { } } + #[inline] fn rst(&mut self, val: u8) -> u8 { // Make sure this is correct. if self.debug { @@ -559,6 +574,7 @@ impl CPU { 16 } + #[inline] fn pop_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("POP {}{}", REG_NAMES[r1], REG_NAMES[r2]); @@ -567,6 +583,8 @@ impl CPU { self.set_pair_value(r1, r2, val); 12 } + + #[inline] fn push_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("PUSH {}{}", REG_NAMES[r1], REG_NAMES[r2]); @@ -576,6 +594,7 @@ impl CPU { 16 } + #[inline] fn dec_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("DEC {}{}", REG_NAMES[r1], REG_NAMES[r2]); @@ -586,6 +605,7 @@ impl CPU { 8 } + #[inline] fn inc_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("INC {}{}", REG_NAMES[r1], REG_NAMES[r2]); @@ -596,17 +616,20 @@ impl CPU { 8 } + #[inline] fn push(&mut self, val: u16) { self.interconnect.write_word(self.sp - 1, val); self.sp -= 2; } + #[inline] fn pop(&mut self) -> u16 { let v: u16 = self.interconnect.read_word(self.sp + 1); self.sp += 2; v } + #[inline] fn ld_r_r(&mut self, reg_dst: usize, reg_src: usize) -> u8 { if self.debug { // println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src]) @@ -620,6 +643,7 @@ impl CPU { } } + #[inline] fn ld_r_v(&mut self, r: usize) -> u8 { let val: u8 = self.load_args(1)[0]; if self.debug { @@ -633,6 +657,7 @@ impl CPU { } } + #[inline] fn ld_rr_vv(&mut self, r1: usize, r2: usize) -> u8 { let val: u16 = to_u16(self.load_args(2)); if self.debug { @@ -642,6 +667,7 @@ impl CPU { 12 } + #[inline] fn reg_inc(&mut self, reg_id: usize) -> u8 { if self.debug { println!("INC {}", REG_NAMES[reg_id]); @@ -654,6 +680,7 @@ impl CPU { 4 } + #[inline] fn add_rr_rr(&mut self, r1: usize, r2: usize, r3: usize, r4: usize) -> u8 { let val1 = self.get_pair_value(r1, r2); let val2 = self.get_pair_value(r3, r4); @@ -661,6 +688,7 @@ impl CPU { 8 } + #[inline] fn reg_dec(&mut self, reg_id: usize) -> u8 { if self.debug { println!("DEC {}", REG_NAMES[reg_id]); @@ -674,6 +702,7 @@ impl CPU { 4 } + #[inline] fn ld_dref_rr_a(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("LD ({}{}), A", REG_NAMES[r1], REG_NAMES[r2]); @@ -684,14 +713,17 @@ impl CPU { 8 } + #[inline] fn set_flag(&mut self, flag: u8) { self.flags |= flag; } + #[inline] fn clear_flag(&mut self, flag: u8) { self.flags &= !flag; } + #[inline] fn set_clear_flag(&mut self, flag: u8, dep: bool) { if dep { self.set_flag(flag); @@ -700,6 +732,7 @@ impl CPU { } } + #[inline] fn int_(&mut self, val: u8){ if self.debug { println!("INT {:02X}", val); @@ -709,18 +742,21 @@ impl CPU { self.call(val as u16); } + #[inline] fn ret(&mut self) { let new_ip: u16 = self.pop(); //self.dump_stack(); self.ip = new_ip; } + #[inline] fn reti(&mut self) -> u8 { self.ret(); self.ime = true; 16 } + #[inline] fn handle_interrupt(&mut self, offset: u8, flag: u8) { // Remove interrupt requested flag let new_flag = self.interconnect.read_byte(0xFF0F) & !flag; diff --git a/src/display.rs b/src/display.rs index e98057d..9992b9c 100644 --- a/src/display.rs +++ b/src/display.rs @@ -112,11 +112,13 @@ impl Display { } } + #[inline] fn set_pixel(&mut self, x: u8, y: u8, color: sdl2::pixels::Color) { self.renderer.set_draw_color(color); self.renderer.fill_rect(sdl2::rect::Rect::new((x as i32) * SCALE as i32, (y as i32) * SCALE as i32, SCALE as u32, SCALE as u32)); } + #[inline] pub fn vblank_interrupt(&mut self) -> bool { // Returns whether or not a vblank interrupt should be done // Yes, this is polling, and yes, this sucks.\ @@ -128,6 +130,7 @@ impl Display { } } + #[inline] pub fn stat_interrupt(&mut self) -> bool { if self.stat_interrupt { self.stat_interrupt = false; @@ -137,6 +140,7 @@ impl Display { } } + #[inline] pub fn write_byte(&mut self, addr: u16, val: u8) { match addr { 0x8000 ... 0x9FFF => { @@ -162,6 +166,7 @@ impl Display { } } + #[inline] pub fn read_byte(&self, addr: u16) -> u8 { match addr { 0x8000 ... 0x9FFF => self.vram[(addr - 0x8000) as usize], @@ -181,7 +186,7 @@ impl Display { } } - // Do we want to have a time delta here? + #[inline] pub fn tick(&mut self, ticks: u16) { self.status &= 0xFC; if self.control & CTRL_LCD_DISPLAY_ENABLE == 0 { @@ -270,6 +275,7 @@ impl Display { } } + #[inline] fn renderscan(&mut self) { // Points to the background map offset to use. let background_map: usize; diff --git a/src/interconnect.rs b/src/interconnect.rs index 3e1600f..de0cc28 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -167,10 +167,12 @@ impl Interconnect { } } + #[inline] pub fn is_boot_rom(&self) -> bool { self.disable_bootrom == 0 } + #[inline] pub fn read_byte(&self, addr: u16) -> u8 { // TODO: Make this more beautiful. // TODO: if some flag set, use bios, otherwise only use rom @@ -241,6 +243,7 @@ impl Interconnect { } } + #[inline] pub fn write_byte(&mut self, addr: u16, val: u8) { // TODO: Make this more beautful /* @@ -336,11 +339,13 @@ impl Interconnect { } } + #[inline] pub fn write_word(&mut self, addr: u16, val: u16) { self.write_byte(addr, val as u8); self.write_byte(addr + 1, (val >> 8) as u8); } + #[inline] pub fn read_word(&self, addr: u16) -> u16 { self.read_byte(addr) as u16 | (self.read_byte(addr + 1) as u16) << 8 // (self.read_byte(addr) as u16) << 8 | (self.read_byte(addr + 1) as u16)