diff --git a/src/arm7tdmi/arm/display.rs b/src/arm7tdmi/arm/display.rs index 3b45c19..371bb90 100644 --- a/src/arm7tdmi/arm/display.rs +++ b/src/arm7tdmi/arm/display.rs @@ -1,5 +1,7 @@ use std::fmt; +use crate::bit::BitIndex; + use super::{AluOpCode, ArmCond, ArmFormat, ArmHalfwordTransferType, ArmInstruction}; use crate::arm7tdmi::{ psr::RegPSR, reg_string, Addr, BarrelShiftOpCode, BarrelShifterValue, ShiftedRegister, REG_PC, @@ -253,13 +255,19 @@ impl ArmInstruction { auto_inc = if self.write_back_flag() { "!" } else { "" } )?; - let mut register_list = self.register_list().into_iter(); - if let Some(reg) = register_list.next() { - write!(f, "{}", reg_string(reg))?; - } - for reg in register_list { - write!(f, ", {}", reg_string(reg))?; + let register_list = self.register_list(); + let mut has_first = false; + for i in 0..16 { + if register_list.bit(i) { + if has_first { + write!(f, ", {}", reg_string(i))?; + } else { + write!(f, "{}", reg_string(i))?; + has_first = true; + } + } } + write!( f, "}}{}", diff --git a/src/arm7tdmi/arm/exec.rs b/src/arm7tdmi/arm/exec.rs index 85acbec..58eaddb 100644 --- a/src/arm7tdmi/arm/exec.rs +++ b/src/arm7tdmi/arm/exec.rs @@ -158,7 +158,6 @@ impl Core { fn exec_data_processing(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult { // TODO handle carry flag - let op1 = if insn.rn() == REG_PC { self.pc as i32 // prefething } else { @@ -265,7 +264,6 @@ impl Core { return Err(CpuError::IllegalInstruction); } - let mut addr = self.get_reg(insn.rn()); if insn.rn() == REG_PC { addr = insn.pc + 8; // prefetching @@ -330,54 +328,54 @@ impl Core { let mut addr = self.gpr[rn] as i32; let step: i32 = if ascending { 4 } else { -4 }; - let rlist = if ascending { - insn.register_list() - } else { - let mut rlist = insn.register_list(); - rlist.reverse(); - rlist - }; + let rlist = insn.register_list(); if psr_user { unimplemented!("Too tired to implement the mode enforcement"); } if is_load { - if rlist.contains(&rn) { - writeback = false; - } - for r in rlist { - if full { - addr = addr.wrapping_add(step); - } + for r in 0..16 { + let r = if ascending { r } else { 15 - r }; + if rlist.bit(r) { + if r == rn { + writeback = false; + } + if full { + addr = addr.wrapping_add(step); + } - self.add_cycle(); - let val = self.load_32(addr as Addr, bus); - self.set_reg(r, val); + self.add_cycle(); + let val = self.load_32(addr as Addr, bus); + self.set_reg(r, val); - if r == REG_PC { - self.flush_pipeline(); - } + if r == REG_PC { + self.flush_pipeline(); + } - if !full { - addr = addr.wrapping_add(step); + if !full { + addr = addr.wrapping_add(step); + } } } } else { - for r in rlist { - if full { - addr = addr.wrapping_add(step); - } + for r in 0..16 { + let r = if ascending { r } else { 15 - r }; + if rlist.bit(r) { + if full { + addr = addr.wrapping_add(step); + } - let val = if r == REG_PC { - insn.pc + 12 - } else { - self.get_reg(r) - }; - self.store_32(addr as Addr, val, bus); + let val = if r == REG_PC { + insn.pc + 12 + } else { + self.get_reg(r) + }; + self.store_32(addr as Addr, val, bus); - if !full { - addr = addr.wrapping_add(step); + if !full { + addr = addr.wrapping_add(step); + } } } } diff --git a/src/arm7tdmi/arm/mod.rs b/src/arm7tdmi/arm/mod.rs index 990901b..9eafb4e 100644 --- a/src/arm7tdmi/arm/mod.rs +++ b/src/arm7tdmi/arm/mod.rs @@ -338,15 +338,8 @@ impl ArmInstruction { } } - pub fn register_list(&self) -> Vec { - let list_bits = self.raw & 0xffff; - let mut list = Vec::with_capacity(16); - for i in 0..16 { - if (list_bits & (1 << i)) != 0 { - list.push(i) - } - } - list + pub fn register_list(&self) -> u16 { + (self.raw & 0xffff) as u16 } pub fn swi_comment(&self) -> u32 { diff --git a/src/arm7tdmi/thumb/display.rs b/src/arm7tdmi/thumb/display.rs index f3164e9..ba59cc9 100644 --- a/src/arm7tdmi/thumb/display.rs +++ b/src/arm7tdmi/thumb/display.rs @@ -209,21 +209,27 @@ impl ThumbInstruction { write!(f, "add\tsp, #{imm:x}", imm = self.sword7()) } + fn fmt_register_list(&self, f: &mut fmt::Formatter, rlist: u8) -> fmt::Result { + let mut has_first = false; + for i in 0..8 { + if rlist.bit(i) { + if has_first { + write!(f, ", {}", reg_string(i))?; + } else { + write!(f, "{}", reg_string(i))?; + } + } + } + Ok(()) + } + fn fmt_thumb_push_pop(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}\t{{", if self.is_load() { "pop" } else { "push" })?; - let mut register_list = self.register_list().into_iter(); - let mut has_reg = false; - if let Some(reg) = register_list.next() { - write!(f, "{}", reg_string(reg))?; - has_reg = true; - } - for reg in register_list { - has_reg = true; - write!(f, ", {}", reg_string(reg))?; - } + let rlist = self.register_list(); + self.fmt_register_list(f, rlist)?; if self.flag(ThumbInstruction::FLAG_R) { let r = if self.is_load() { "pc" } else { "lr" }; - if has_reg { + if rlist != 0 { write!(f, ", {}", r)?; } else { write!(f, "{}", r)?; @@ -239,16 +245,7 @@ impl ThumbInstruction { op = if self.is_load() { "ldm" } else { "stm" }, Rb = reg_string(self.rb()), )?; - let mut register_list = self.register_list().into_iter(); - let mut has_reg = false; - if let Some(reg) = register_list.next() { - write!(f, "{}", reg_string(reg))?; - has_reg = true; - } - for reg in register_list { - has_reg = true; - write!(f, ", {}", reg_string(reg))?; - } + self.fmt_register_list(f, self.register_list())?; write!(f, "}}") } diff --git a/src/arm7tdmi/thumb/exec.rs b/src/arm7tdmi/thumb/exec.rs index e63335b..dcbf722 100644 --- a/src/arm7tdmi/thumb/exec.rs +++ b/src/arm7tdmi/thumb/exec.rs @@ -313,14 +313,14 @@ impl Core { fn exec_thumb_push_pop(&mut self, bus: &mut Bus, 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(); if is_pop { - for r in rlist { - pop(self, bus, r); + for r in 0..8 { + if rlist.bit(r) { + pop(self, bus, r); + } } if pc_lr_flag { pop(self, bus, REG_PC); @@ -332,8 +332,10 @@ impl Core { if pc_lr_flag { push(self, bus, REG_LR); } - for r in rlist.into_iter().rev() { - push(self, bus, r); + for r in (0..8).rev() { + if rlist.bit(r) { + push(self, bus, r); + } } } @@ -349,16 +351,20 @@ impl Core { let mut addr = self.gpr[rb]; let rlist = insn.register_list(); if is_load { - for r in rlist { - let val = self.load_32(addr, bus); - addr += 4; - self.add_cycle(); - self.set_reg(r, val); + for r in 0..8 { + if rlist.bit(r) { + let val = self.load_32(addr, bus); + addr += 4; + self.add_cycle(); + self.set_reg(r, val); + } } } else { - for r in rlist { - self.store_32(addr, self.gpr[r], bus); - addr += 4; + for r in 0..8 { + if rlist.bit(r) { + self.store_32(addr, self.gpr[r], bus); + addr += 4; + } } } diff --git a/src/arm7tdmi/thumb/mod.rs b/src/arm7tdmi/thumb/mod.rs index d52bf6f..ed5a167 100644 --- a/src/arm7tdmi/thumb/mod.rs +++ b/src/arm7tdmi/thumb/mod.rs @@ -330,15 +330,8 @@ impl ThumbInstruction { self.raw.bit(bit) } - pub fn register_list(&self) -> Vec { - let list_bits = self.raw & 0xff; - let mut list = Vec::with_capacity(8); - for i in 0..8 { - if (list_bits & (1 << i)) != 0 { - list.push(i) - } - } - list + pub fn register_list(&self) -> u8 { + (self.raw & 0xff) as u8 } pub fn sword7(&self) -> i32 {