Impl Thumb 19, fix warnings and rustfmt
Former-commit-id: 8690aa25b1aa343b344776716b6213596bd1459a
This commit is contained in:
parent
fb0d3acb14
commit
d4b6952411
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue