Impl Thumb 19, fix warnings and rustfmt

Former-commit-id: 8690aa25b1aa343b344776716b6213596bd1459a
This commit is contained in:
Michel Heily 2019-07-05 15:34:52 +03:00
parent fb0d3acb14
commit d4b6952411
9 changed files with 68 additions and 43 deletions

View file

@ -1,6 +1,6 @@
use crate::bit::BitIndex; use crate::bit::BitIndex;
use crate::arm7tdmi::bus::{Bus, MemoryAccessType::*, MemoryAccessWidth::*}; use crate::arm7tdmi::bus::Bus;
use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction}; use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction};
use crate::arm7tdmi::exception::Exception; use crate::arm7tdmi::exception::Exception;
use crate::arm7tdmi::psr::RegPSR; use crate::arm7tdmi::psr::RegPSR;
@ -31,7 +31,7 @@ impl Core {
} }
/// Cycles 2S+1N /// Cycles 2S+1N
fn exec_b_bl(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> { fn exec_b_bl(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
if insn.link_flag() { if insn.link_flag() {
self.set_reg(14, (insn.pc + (self.word_size() as u32)) & !0b1); self.set_reg(14, (insn.pc + (self.word_size() as u32)) & !0b1);
} }
@ -42,7 +42,7 @@ impl Core {
} }
/// Cycles 2S+1N /// Cycles 2S+1N
fn exec_bx(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> { fn exec_bx(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
let rn = self.get_reg(insn.rn()); let rn = self.get_reg(insn.rn());
if rn.bit(0) { if rn.bit(0) {
self.cpsr.set_state(CpuState::THUMB); self.cpsr.set_state(CpuState::THUMB);
@ -62,7 +62,7 @@ impl Core {
fn exec_msr_reg( fn exec_msr_reg(
&mut self, &mut self,
bus: &mut Bus, _bus: &mut Bus,
insn: ArmInstruction, insn: ArmInstruction,
) -> CpuResult<CpuPipelineAction> { ) -> CpuResult<CpuPipelineAction> {
let new_psr = RegPSR::new(self.get_reg(insn.rm())); let new_psr = RegPSR::new(self.get_reg(insn.rm()));
@ -119,6 +119,7 @@ impl Core {
res res
} }
#[allow(non_snake_case)]
pub fn alu( pub fn alu(
&mut self, &mut self,
opcode: ArmOpCode, opcode: ArmOpCode,
@ -129,7 +130,7 @@ impl Core {
let C = self.cpsr.C() as i32; let C = self.cpsr.C() as i32;
let mut carry = self.cpsr.C(); let mut carry = self.cpsr.C();
let mut overflow = self.cpsr.V(); let overflow = self.cpsr.V();
let result = match opcode { let result = match opcode {
ArmOpCode::AND | ArmOpCode::TST => op1 & op2, ArmOpCode::AND | ArmOpCode::TST => op1 & op2,
@ -165,7 +166,7 @@ impl Core {
/// Add x=1I cycles if Op2 shifted-by-register. Add y=1S+1N cycles if Rd=R15. /// Add x=1I cycles if Op2 shifted-by-register. Add y=1S+1N cycles if Rd=R15.
fn exec_data_processing( fn exec_data_processing(
&mut self, &mut self,
bus: &mut Bus, _bus: &mut Bus,
insn: ArmInstruction, insn: ArmInstruction,
) -> CpuResult<CpuPipelineAction> { ) -> CpuResult<CpuPipelineAction> {
// TODO handle carry flag // TODO handle carry flag
@ -251,7 +252,6 @@ impl Core {
if insn.rn() == REG_PC { if insn.rn() == REG_PC {
addr = insn.pc + 8; // prefetching addr = insn.pc + 8; // prefetching
} }
let dest = self.get_reg(insn.rd());
let offset = self.get_rn_offset(&insn); let offset = self.get_rn_offset(&insn);

View file

@ -198,12 +198,6 @@ impl fmt::Display for CpuError {
pub type CpuResult<T> = Result<T, CpuError>; pub type CpuResult<T> = Result<T, CpuError>;
pub struct CpuModeContext {
// r8-r14
banked_gpr: [u32; 7],
spsr: u32,
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]

View file

@ -3,7 +3,7 @@ use std::fmt;
use crate::bit::BitIndex; use crate::bit::BitIndex;
use super::*; use super::*;
use crate::arm7tdmi::reg_string; use crate::arm7tdmi::*;
impl ThumbInstruction { impl ThumbInstruction {
fn fmt_thumb_move_shifted_reg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt_thumb_move_shifted_reg(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -158,6 +158,17 @@ impl ThumbInstruction {
} }
) )
} }
fn fmt_thumb_branch_long_with_link(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "bl\t#0x{:08x}", {
let offset11 = self.offset11();
if self.flag(ThumbInstruction::FLAG_LOW_OFFSET) {
(offset11 << 1) as i32
} else {
((offset11 << 21) >> 9) as i32
}
})
}
} }
impl fmt::Display for ThumbInstruction { impl fmt::Display for ThumbInstruction {
@ -175,6 +186,7 @@ impl fmt::Display for ThumbInstruction {
ThumbFormat::AddSp => self.fmt_thumb_add_sp(f), ThumbFormat::AddSp => self.fmt_thumb_add_sp(f),
ThumbFormat::PushPop => self.fmt_thumb_push_pop(f), ThumbFormat::PushPop => self.fmt_thumb_push_pop(f),
ThumbFormat::BranchConditional => self.fmt_thumb_branch_with_cond(f), ThumbFormat::BranchConditional => self.fmt_thumb_branch_with_cond(f),
ThumbFormat::BranchLongWithLink => self.fmt_thumb_branch_long_with_link(f),
_ => write!(f, "({:?})", self), _ => write!(f, "({:?})", self),
} }
} }

View file

@ -1,7 +1,7 @@
use crate::arm7tdmi::arm::*; use crate::arm7tdmi::arm::*;
use crate::arm7tdmi::bus::{Bus, MemoryAccessType::*, MemoryAccessWidth::*}; use crate::arm7tdmi::bus::Bus;
use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction}; use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction};
use crate::arm7tdmi::{reg_string, Addr, CpuState, REG_LR, REG_PC, REG_SP}; use crate::arm7tdmi::*;
use super::*; use super::*;
fn push(cpu: &mut Core, bus: &mut Bus, r: usize) { fn push(cpu: &mut Core, bus: &mut Bus, r: usize) {
@ -19,7 +19,7 @@ fn pop(cpu: &mut Core, bus: &mut Bus, r: usize) {
impl Core { impl Core {
fn exec_thumb_move_shifted_reg( fn exec_thumb_move_shifted_reg(
&mut self, &mut self,
bus: &mut Bus, _bus: &mut Bus,
insn: ThumbInstruction, insn: ThumbInstruction,
) -> CpuExecResult { ) -> CpuExecResult {
let result = self let result = self
@ -33,7 +33,7 @@ impl Core {
Ok(CpuPipelineAction::IncPC) Ok(CpuPipelineAction::IncPC)
} }
fn exec_thumb_add_sub(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult { fn exec_thumb_add_sub(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
let op1 = self.get_reg(insn.rs()) as i32; let op1 = self.get_reg(insn.rs()) as i32;
let op2 = if insn.is_immediate_operand() { let op2 = if insn.is_immediate_operand() {
insn.rn() as u32 as i32 insn.rn() as u32 as i32
@ -56,7 +56,7 @@ impl Core {
fn exec_thumb_data_process_imm( fn exec_thumb_data_process_imm(
&mut self, &mut self,
bus: &mut Bus, _bus: &mut Bus,
insn: ThumbInstruction, insn: ThumbInstruction,
) -> CpuExecResult { ) -> CpuExecResult {
let arm_alu_op: ArmOpCode = insn.format3_op().into(); let arm_alu_op: ArmOpCode = insn.format3_op().into();
@ -70,18 +70,18 @@ impl Core {
Ok(CpuPipelineAction::IncPC) Ok(CpuPipelineAction::IncPC)
} }
fn exec_thumb_mul(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult { fn exec_thumb_mul(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
let op1 = self.get_reg(insn.rd()) as i32; let op1 = self.get_reg(insn.rd()) as i32;
let op2 = self.get_reg(insn.rs()) as i32; let op2 = self.get_reg(insn.rs()) as i32;
let m = self.get_required_multipiler_array_cycles(op2); let m = self.get_required_multipiler_array_cycles(op2);
for i in 0..m { for _ in 0..m {
self.add_cycle(); self.add_cycle();
} }
self.gpr[insn.rd()] = (op1 * op2) as u32; self.gpr[insn.rd()] = (op1 * op2) as u32;
Ok(CpuPipelineAction::IncPC) Ok(CpuPipelineAction::IncPC)
} }
fn exec_thumb_alu_ops(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult { fn exec_thumb_alu_ops(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
let arm_alu_op: ArmOpCode = insn.alu_opcode(); let arm_alu_op: ArmOpCode = insn.alu_opcode();
let op1 = self.get_reg(insn.rd()) as i32; let op1 = self.get_reg(insn.rd()) as i32;
let op2 = self.get_reg(insn.rs()) as i32; let op2 = self.get_reg(insn.rs()) as i32;
@ -94,7 +94,7 @@ impl Core {
} }
/// Cycles 2S+1N /// Cycles 2S+1N
fn exec_thumb_bx(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult { fn exec_thumb_bx(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
let src_reg = if insn.flag(ThumbInstruction::FLAG_H2) { let src_reg = if insn.flag(ThumbInstruction::FLAG_H2) {
insn.rs() + 8 insn.rs() + 8
} else { } else {
@ -180,7 +180,7 @@ impl Core {
Ok(CpuPipelineAction::IncPC) Ok(CpuPipelineAction::IncPC)
} }
fn exec_thumb_add_sp(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult { fn exec_thumb_add_sp(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
let op1 = self.gpr[REG_SP] as i32; let op1 = self.gpr[REG_SP] as i32;
let op2 = insn.sword7(); let op2 = insn.sword7();
let arm_alu_op = ArmOpCode::ADD; let arm_alu_op = ArmOpCode::ADD;
@ -230,12 +230,33 @@ impl Core {
if !self.check_arm_cond(insn.cond()) { if !self.check_arm_cond(insn.cond()) {
Ok(CpuPipelineAction::IncPC) Ok(CpuPipelineAction::IncPC)
} else { } else {
let offset = insn.offset8() as u8 as i32; let offset = insn.offset8() as i8 as i32;
self.pc = (insn.pc as i32).wrapping_add(offset) as u32; self.pc = (insn.pc as i32).wrapping_add(offset) as u32;
Ok(CpuPipelineAction::Flush) Ok(CpuPipelineAction::Flush)
} }
} }
fn exec_thumb_branch_long_with_link(
&mut self,
_bus: &mut Bus,
insn: ThumbInstruction,
) -> CpuExecResult {
let mut off = insn.offset11();
if insn.flag(ThumbInstruction::FLAG_LOW_OFFSET) {
off = off << 1;
let next_pc = (self.pc - 2) | 1;
self.pc = (self.gpr[REG_LR] as i32).wrapping_add(off) as u32;
self.gpr[REG_LR] = next_pc;
Ok(CpuPipelineAction::Flush)
} else {
off = (off << 21) >> 9;
self.gpr[REG_LR] = (self.pc as i32).wrapping_add(off) as u32;
Ok(CpuPipelineAction::IncPC)
}
}
pub fn exec_thumb(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult { pub fn exec_thumb(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
match insn.fmt { match insn.fmt {
ThumbFormat::MoveShiftedReg => self.exec_thumb_move_shifted_reg(bus, insn), ThumbFormat::MoveShiftedReg => self.exec_thumb_move_shifted_reg(bus, insn),
@ -250,6 +271,7 @@ impl Core {
ThumbFormat::AddSp => self.exec_thumb_add_sp(bus, insn), ThumbFormat::AddSp => self.exec_thumb_add_sp(bus, insn),
ThumbFormat::PushPop => self.exec_thumb_push_pop(bus, insn), ThumbFormat::PushPop => self.exec_thumb_push_pop(bus, insn),
ThumbFormat::BranchConditional => self.exec_thumb_branch_with_cond(bus, insn), ThumbFormat::BranchConditional => self.exec_thumb_branch_with_cond(bus, insn),
ThumbFormat::BranchLongWithLink => self.exec_thumb_branch_long_with_link(bus, insn),
_ => unimplemented!("thumb not implemented {:#x?}", insn), _ => unimplemented!("thumb not implemented {:#x?}", insn),
} }
} }

View file

@ -198,6 +198,7 @@ impl ThumbInstruction {
const FLAG_H2: usize = 6; const FLAG_H2: usize = 6;
const FLAG_R: usize = 8; const FLAG_R: usize = 8;
const FLAG_S: usize = 7; const FLAG_S: usize = 7;
const FLAG_LOW_OFFSET: usize = 11;
pub fn rd(&self) -> usize { pub fn rd(&self) -> usize {
match self.fmt { match self.fmt {
@ -252,6 +253,10 @@ impl ThumbInstruction {
self.raw.bit_range(0..8) as i8 self.raw.bit_range(0..8) as i8
} }
pub fn offset11(&self) -> i32 {
(self.raw & 0x7FF) as i32
}
pub fn word8(&self) -> u16 { pub fn word8(&self) -> u16 {
self.raw.bit_range(0..8) << 2 self.raw.bit_range(0..8) << 2
} }

View file

@ -1,9 +1,7 @@
use std::str::from_utf8; use std::str::from_utf8;
use nom::number::streaming::le_u32;
use crate::arm7tdmi::{ use crate::arm7tdmi::{
bus::{Bus, MemoryAccess, MemoryAccessType, MemoryAccessWidth}, bus::{Bus, MemoryAccess, MemoryAccessWidth},
Addr, Addr,
}; };
use crate::sysbus::WaitState; use crate::sysbus::WaitState;

View file

@ -1,7 +1,3 @@
use std::fmt;
use crate::arm7tdmi::Addr;
use nom; use nom;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::{tag, take_while1, take_while_m_n}; use nom::bytes::complete::{tag, take_while1, take_while_m_n};

View file

@ -1,8 +1,6 @@
use std::convert::TryFrom;
use std::marker::PhantomData; use std::marker::PhantomData;
use super::arm7tdmi::{Addr, InstructionDecoder, InstructionDecoderError}; use super::arm7tdmi::{Addr, InstructionDecoder, InstructionDecoderError};
use std::io;
use std::io::ErrorKind; use std::io::ErrorKind;
pub struct Disassembler<'a, D> pub struct Disassembler<'a, D>

View file

@ -69,38 +69,38 @@ impl Bus for BoxedMemory {
struct DummyBus([u8; 4]); struct DummyBus([u8; 4]);
impl Bus for DummyBus { impl Bus for DummyBus {
fn read_32(&self, addr: Addr) -> u32 { fn read_32(&self, _addr: Addr) -> u32 {
0 0
} }
fn read_16(&self, addr: Addr) -> u16 { fn read_16(&self, _addr: Addr) -> u16 {
0 0
} }
fn read_8(&self, addr: Addr) -> u8 { fn read_8(&self, _addr: Addr) -> u8 {
0 0
} }
fn write_32(&mut self, addr: Addr, value: u32) -> Result<(), io::Error> { fn write_32(&mut self, _addr: Addr, _value: u32) -> Result<(), io::Error> {
Ok(()) Ok(())
} }
fn write_16(&mut self, addr: Addr, value: u16) -> Result<(), io::Error> { fn write_16(&mut self, _addr: Addr, _value: u16) -> Result<(), io::Error> {
Ok(()) Ok(())
} }
fn write_8(&mut self, addr: Addr, value: u8) -> Result<(), io::Error> { fn write_8(&mut self, _addr: Addr, _value: u8) -> Result<(), io::Error> {
Ok(()) Ok(())
} }
fn get_bytes(&self, addr: Addr) -> &[u8] { fn get_bytes(&self, _addr: Addr) -> &[u8] {
&self.0 &self.0
} }
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] { fn get_bytes_mut(&mut self, _addr: Addr) -> &mut [u8] {
&mut self.0 &mut self.0
} }
fn get_cycles(&self, addr: Addr, access: MemoryAccess) -> usize { fn get_cycles(&self, _addr: Addr, _access: MemoryAccess) -> usize {
1 1
} }
} }