Gotta make clippy happy
Former-commit-id: b2e4b28ae9d054020891029ae0be5e148357779e Former-commit-id: fd0c17e9729f35fd40bd3c75fe53907129776445
This commit is contained in:
parent
12d9edf5c4
commit
25b630951d
|
@ -25,29 +25,20 @@ pub enum AluOpCode {
|
||||||
impl AluOpCode {
|
impl AluOpCode {
|
||||||
pub fn is_setting_flags(&self) -> bool {
|
pub fn is_setting_flags(&self) -> bool {
|
||||||
use AluOpCode::*;
|
use AluOpCode::*;
|
||||||
match self {
|
matches!(self, TST | TEQ | CMP | CMN)
|
||||||
TST | TEQ | CMP | CMN => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_logical(&self) -> bool {
|
pub fn is_logical(&self) -> bool {
|
||||||
use AluOpCode::*;
|
use AluOpCode::*;
|
||||||
match self {
|
matches!(self, MOV | MVN | ORR | EOR | AND | BIC | TST | TEQ)
|
||||||
MOV | MVN | ORR | EOR | AND | BIC | TST | TEQ => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn is_arithmetic(&self) -> bool {
|
pub fn is_arithmetic(&self) -> bool {
|
||||||
use AluOpCode::*;
|
use AluOpCode::*;
|
||||||
match self {
|
matches!(self, ADD | ADC | SUB | SBC | RSB | RSC | CMP | CMN)
|
||||||
ADD | ADC | SUB | SBC | RSB | RSC | CMP | CMN => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Primitive, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Primitive, Copy, Clone)]
|
||||||
pub enum BarrelShiftOpCode {
|
pub enum BarrelShiftOpCode {
|
||||||
LSL = 0,
|
LSL = 0,
|
||||||
LSR = 1,
|
LSR = 1,
|
||||||
|
@ -55,13 +46,13 @@ pub enum BarrelShiftOpCode {
|
||||||
ROR = 3,
|
ROR = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum ShiftRegisterBy {
|
pub enum ShiftRegisterBy {
|
||||||
ByAmount(u32),
|
ByAmount(u32),
|
||||||
ByRegister(usize),
|
ByRegister(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub struct ShiftedRegister {
|
pub struct ShiftedRegister {
|
||||||
pub reg: usize,
|
pub reg: usize,
|
||||||
pub shift_by: ShiftRegisterBy,
|
pub shift_by: ShiftRegisterBy,
|
||||||
|
@ -71,14 +62,11 @@ pub struct ShiftedRegister {
|
||||||
|
|
||||||
impl ShiftedRegister {
|
impl ShiftedRegister {
|
||||||
pub fn is_shifted_by_reg(&self) -> bool {
|
pub fn is_shifted_by_reg(&self) -> bool {
|
||||||
match self.shift_by {
|
matches!(self.shift_by, ShiftRegisterBy::ByRegister(_))
|
||||||
ShiftRegisterBy::ByRegister(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum BarrelShifterValue {
|
pub enum BarrelShifterValue {
|
||||||
ImmediateValue(u32),
|
ImmediateValue(u32),
|
||||||
RotatedImmediate(u32, u32),
|
RotatedImmediate(u32, u32),
|
||||||
|
@ -285,9 +273,7 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
pub fn register_shift(&mut self, shift: &ShiftedRegister, carry: &mut bool) -> u32 {
|
pub fn register_shift(&mut self, shift: &ShiftedRegister, carry: &mut bool) -> u32 {
|
||||||
match shift.shift_by {
|
match shift.shift_by {
|
||||||
ShiftRegisterBy::ByAmount(amount) => {
|
ShiftRegisterBy::ByAmount(amount) => {
|
||||||
let result =
|
self.barrel_shift_op(shift.bs_op, self.get_reg(shift.reg), amount, carry, true)
|
||||||
self.barrel_shift_op(shift.bs_op, self.get_reg(shift.reg), amount, carry, true);
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
ShiftRegisterBy::ByRegister(rs) => {
|
ShiftRegisterBy::ByRegister(rs) => {
|
||||||
self.shift_by_register(shift.bs_op, shift.reg, rs, carry)
|
self.shift_by_register(shift.bs_op, shift.reg, rs, carry)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::bit::BitIndex;
|
use bit::BitIndex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
alu::*,
|
alu::*,
|
||||||
|
@ -36,12 +36,12 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
|
|
||||||
pub fn branch_exchange(&mut self, mut addr: Addr) -> CpuAction {
|
pub fn branch_exchange(&mut self, mut addr: Addr) -> CpuAction {
|
||||||
if addr.bit(0) {
|
if addr.bit(0) {
|
||||||
addr = addr & !0x1;
|
addr &= !0x1;
|
||||||
self.cpsr.set_state(CpuState::THUMB);
|
self.cpsr.set_state(CpuState::THUMB);
|
||||||
self.pc = addr;
|
self.pc = addr;
|
||||||
self.reload_pipeline16();
|
self.reload_pipeline16();
|
||||||
} else {
|
} else {
|
||||||
addr = addr & !0x3;
|
addr &= !0x3;
|
||||||
self.cpsr.set_state(CpuState::ARM);
|
self.cpsr.set_state(CpuState::ARM);
|
||||||
self.pc = addr;
|
self.pc = addr;
|
||||||
self.reload_pipeline32();
|
self.reload_pipeline32();
|
||||||
|
@ -101,7 +101,7 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
mask |= 0xff << 8;
|
mask |= 0xff << 8;
|
||||||
}
|
}
|
||||||
if c {
|
if c {
|
||||||
mask |= 0xff << 0;
|
mask |= 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.cpsr.mode() {
|
match self.cpsr.mode() {
|
||||||
|
@ -186,7 +186,7 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
let shifted_reg = ShiftedRegister {
|
let shifted_reg = ShiftedRegister {
|
||||||
reg: reg as usize,
|
reg: reg as usize,
|
||||||
bs_op: insn.get_bs_op(),
|
bs_op: insn.get_bs_op(),
|
||||||
shift_by: shift_by,
|
shift_by,
|
||||||
added: None,
|
added: None,
|
||||||
};
|
};
|
||||||
self.register_shift(&shifted_reg, &mut carry)
|
self.register_shift(&shifted_reg, &mut carry)
|
||||||
|
@ -335,10 +335,8 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if !LOAD || base_reg != dest_reg {
|
if (!LOAD || base_reg != dest_reg) && (!PRE_INDEX || WRITEBACK) {
|
||||||
if !PRE_INDEX || WRITEBACK{
|
self.set_reg(base_reg, effective_addr);
|
||||||
self.set_reg(base_reg, effective_addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !PRE_INDEX && WRITEBACK {
|
if !PRE_INDEX && WRITEBACK {
|
||||||
|
@ -444,12 +442,8 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if !LOAD || base_reg != dest_reg {
|
if (!LOAD || base_reg != dest_reg) && (!PRE_INDEX || WRITEBACK) {
|
||||||
if !PRE_INDEX {
|
self.set_reg(base_reg, effective_addr);
|
||||||
self.set_reg(base_reg, effective_addr);
|
|
||||||
} else if WRITEBACK {
|
|
||||||
self.set_reg(base_reg, effective_addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
@ -554,16 +548,14 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
} else {
|
} else {
|
||||||
self.get_reg(r)
|
self.get_reg(r)
|
||||||
}
|
}
|
||||||
|
} else if first {
|
||||||
|
old_base
|
||||||
} else {
|
} else {
|
||||||
if first {
|
let x = rlist_count * 4;
|
||||||
old_base
|
if ascending {
|
||||||
|
old_base + x
|
||||||
} else {
|
} else {
|
||||||
let x = rlist_count * 4;
|
old_base - x
|
||||||
if ascending {
|
|
||||||
old_base + x
|
|
||||||
} else {
|
|
||||||
old_base - x
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use num::FromPrimitive;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum ArmDecodeErrorKind {
|
pub enum ArmDecodeErrorKind {
|
||||||
UnknownInstructionFormat,
|
UnknownInstructionFormat,
|
||||||
DecodedPartDoesNotBelongToInstruction,
|
DecodedPartDoesNotBelongToInstruction,
|
||||||
|
@ -24,7 +24,7 @@ pub enum ArmDecodeErrorKind {
|
||||||
IoError(io::ErrorKind),
|
IoError(io::ErrorKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ArmDecodeError {
|
pub struct ArmDecodeError {
|
||||||
pub kind: ArmDecodeErrorKind,
|
pub kind: ArmDecodeErrorKind,
|
||||||
pub insn: u32,
|
pub insn: u32,
|
||||||
|
@ -34,15 +34,11 @@ pub struct ArmDecodeError {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl ArmDecodeError {
|
impl ArmDecodeError {
|
||||||
fn new(kind: ArmDecodeErrorKind, insn: u32, addr: Addr) -> ArmDecodeError {
|
fn new(kind: ArmDecodeErrorKind, insn: u32, addr: Addr) -> ArmDecodeError {
|
||||||
ArmDecodeError {
|
ArmDecodeError { kind, insn, addr }
|
||||||
kind: kind,
|
|
||||||
insn: insn,
|
|
||||||
addr: addr,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Primitive)]
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Primitive)]
|
||||||
pub enum ArmCond {
|
pub enum ArmCond {
|
||||||
EQ = 0b0000,
|
EQ = 0b0000,
|
||||||
NE = 0b0001,
|
NE = 0b0001,
|
||||||
|
@ -62,7 +58,7 @@ pub enum ArmCond {
|
||||||
Invalid = 0b1111,
|
Invalid = 0b1111,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ArmFormat {
|
pub enum ArmFormat {
|
||||||
BranchExchange = 0,
|
BranchExchange = 0,
|
||||||
BranchLink,
|
BranchLink,
|
||||||
|
@ -90,33 +86,33 @@ impl From<u32> for ArmFormat {
|
||||||
use ArmFormat::*;
|
use ArmFormat::*;
|
||||||
if (0x0fff_fff0 & raw) == 0x012f_ff10 {
|
if (0x0fff_fff0 & raw) == 0x012f_ff10 {
|
||||||
BranchExchange
|
BranchExchange
|
||||||
} else if (0x0e00_0000 & raw) == 0x0a00_0000 {
|
} else if (0x0E00_0000 & raw) == 0x0A00_0000 {
|
||||||
BranchLink
|
BranchLink
|
||||||
} else if (0xe000_0010 & raw) == 0x0600_0000 {
|
} else if (0x0E00_0010 & raw) == 0x0600_0000 {
|
||||||
Undefined
|
Undefined
|
||||||
} else if (0x0fb0_0ff0 & raw) == 0x0100_0090 {
|
} else if (0x0FB0_0FF0 & raw) == 0x0100_0090 {
|
||||||
SingleDataSwap
|
SingleDataSwap
|
||||||
} else if (0x0fc0_00f0 & raw) == 0x0000_0090 {
|
} else if (0x0FC0_00F0 & raw) == 0x0000_0090 {
|
||||||
Multiply
|
Multiply
|
||||||
} else if (0x0f80_00f0 & raw) == 0x0080_0090 {
|
} else if (0x0F80_00F0 & raw) == 0x0080_0090 {
|
||||||
MultiplyLong
|
MultiplyLong
|
||||||
} else if (0x0fbf_0fff & raw) == 0x010f_0000 {
|
} else if (0x0FBF_0FFF & raw) == 0x010F_0000 {
|
||||||
MoveFromStatus
|
MoveFromStatus
|
||||||
} else if (0x0fbf_fff0 & raw) == 0x0129_f000 {
|
} else if (0x0FBF_FFF0 & raw) == 0x0129_F000 {
|
||||||
MoveToStatus
|
MoveToStatus
|
||||||
} else if (0x0dbf_f000 & raw) == 0x0128_f000 {
|
} else if (0x0DBF_F000 & raw) == 0x0128_F000 {
|
||||||
MoveToFlags
|
MoveToFlags
|
||||||
} else if (0x0c00_0000 & raw) == 0x0400_0000 {
|
} else if (0x0C00_0000 & raw) == 0x0400_0000 {
|
||||||
SingleDataTransfer
|
SingleDataTransfer
|
||||||
} else if (0x0e40_0F90 & raw) == 0x0000_0090 {
|
} else if (0x0E40_0F90 & raw) == 0x0000_0090 {
|
||||||
HalfwordDataTransferRegOffset
|
HalfwordDataTransferRegOffset
|
||||||
} else if (0x0e40_0090 & raw) == 0x0040_0090 {
|
} else if (0x0E40_0090 & raw) == 0x0040_0090 {
|
||||||
HalfwordDataTransferImmediateOffset
|
HalfwordDataTransferImmediateOffset
|
||||||
} else if (0x0e00_0000 & raw) == 0x0800_0000 {
|
} else if (0x0E00_0000 & raw) == 0x0800_0000 {
|
||||||
BlockDataTransfer
|
BlockDataTransfer
|
||||||
} else if (0x0f00_0000 & raw) == 0x0f00_0000 {
|
} else if (0x0F00_0000 & raw) == 0x0F00_0000 {
|
||||||
SoftwareInterrupt
|
SoftwareInterrupt
|
||||||
} else if (0x0c00_0000 & raw) == 0x0000_0000 {
|
} else if (0x0C00_0000 & raw) == 0x0000_0000 {
|
||||||
DataProcessing
|
DataProcessing
|
||||||
} else {
|
} else {
|
||||||
Undefined
|
Undefined
|
||||||
|
@ -124,14 +120,14 @@ impl From<u32> for ArmFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Primitive)]
|
#[derive(Debug, PartialEq, Eq, Primitive)]
|
||||||
pub enum ArmHalfwordTransferType {
|
pub enum ArmHalfwordTransferType {
|
||||||
UnsignedHalfwords = 0b01,
|
UnsignedHalfwords = 0b01,
|
||||||
SignedByte = 0b10,
|
SignedByte = 0b10,
|
||||||
SignedHalfwords = 0b11,
|
SignedHalfwords = 0b11,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ArmInstruction {
|
pub struct ArmInstruction {
|
||||||
pub fmt: ArmFormat,
|
pub fmt: ArmFormat,
|
||||||
pub raw: u32,
|
pub raw: u32,
|
||||||
|
@ -150,11 +146,7 @@ impl InstructionDecoder for ArmInstruction {
|
||||||
fn decode(raw: u32, addr: Addr) -> Self {
|
fn decode(raw: u32, addr: Addr) -> Self {
|
||||||
let fmt = ArmFormat::from(raw);
|
let fmt = ArmFormat::from(raw);
|
||||||
|
|
||||||
ArmInstruction {
|
ArmInstruction {fmt, raw, pc: addr }
|
||||||
fmt: fmt,
|
|
||||||
raw: raw,
|
|
||||||
pc: addr,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_from_bytes(bytes: &[u8], addr: Addr) -> Self {
|
fn decode_from_bytes(bytes: &[u8], addr: Addr) -> Self {
|
||||||
|
|
|
@ -166,10 +166,10 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
SavedCpuState {
|
SavedCpuState {
|
||||||
cpsr: self.cpsr,
|
cpsr: self.cpsr,
|
||||||
pc: self.pc,
|
pc: self.pc,
|
||||||
gpr: self.gpr.clone(),
|
gpr: self.gpr,
|
||||||
spsr: self.spsr,
|
spsr: self.spsr,
|
||||||
banks: self.banks.clone(),
|
banks: self.banks.clone(),
|
||||||
pipeline: self.pipeline.clone(),
|
pipeline: self.pipeline,
|
||||||
next_fetch_access: self.next_fetch_access,
|
next_fetch_access: self.next_fetch_access,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,8 +264,8 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_registers(&self) -> [u32; 15] {
|
pub fn copy_registers(&self) -> [u32; 15] {
|
||||||
self.gpr.clone()
|
self.gpr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn change_mode(&mut self, old_mode: CpuMode, new_mode: CpuMode) {
|
pub(super) fn change_mode(&mut self, old_mode: CpuMode, new_mode: CpuMode) {
|
||||||
|
@ -352,7 +352,7 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
|
|
||||||
#[cfg(feature = "debugger")]
|
#[cfg(feature = "debugger")]
|
||||||
fn debugger_record_step(&mut self, d: DecodedInstruction) {
|
fn debugger_record_step(&mut self, d: DecodedInstruction) {
|
||||||
self.dbg.gpr_previous = self.get_registers();
|
self.dbg.gpr_previous = self.copy_registers();
|
||||||
self.dbg.last_executed = Some(d);
|
self.dbg.last_executed = Some(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,12 +433,10 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
self.pipeline[1] = fetched_now;
|
self.pipeline[1] = fetched_now;
|
||||||
let cond = ArmCond::from_u8(insn.bit_range(28..32) as u8)
|
let cond = ArmCond::from_u8(insn.bit_range(28..32) as u8)
|
||||||
.unwrap_or_else(|| unsafe { std::hint::unreachable_unchecked() });
|
.unwrap_or_else(|| unsafe { std::hint::unreachable_unchecked() });
|
||||||
if cond != ArmCond::AL {
|
if cond != ArmCond::AL && !self.check_arm_cond(cond) {
|
||||||
if !self.check_arm_cond(cond) {
|
self.advance_arm();
|
||||||
self.advance_arm();
|
self.next_fetch_access = MemoryAccess::NonSeq;
|
||||||
self.next_fetch_access = MemoryAccess::NonSeq;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match self.step_arm_exec(insn) {
|
match self.step_arm_exec(insn) {
|
||||||
CpuAction::AdvancePC(access) => {
|
CpuAction::AdvancePC(access) => {
|
||||||
|
@ -499,7 +497,7 @@ impl<I: MemoryInterface> fmt::Display for Core<I> {
|
||||||
writeln!(f, "\tGeneral Purpose Registers:")?;
|
writeln!(f, "\tGeneral Purpose Registers:")?;
|
||||||
let reg_normal_style = Style::new().bold();
|
let reg_normal_style = Style::new().bold();
|
||||||
let reg_dirty_style = Colour::Black.bold().on(Colour::Yellow);
|
let reg_dirty_style = Colour::Black.bold().on(Colour::Yellow);
|
||||||
let gpr = self.get_registers();
|
let gpr = self.copy_registers();
|
||||||
for i in 0..15 {
|
for i in 0..15 {
|
||||||
let mut reg_name = reg_string(i).to_string();
|
let mut reg_name = reg_string(i).to_string();
|
||||||
reg_name.make_ascii_uppercase();
|
reg_name.make_ascii_uppercase();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::fmt::Write;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use super::Addr;
|
use super::Addr;
|
||||||
|
@ -23,7 +24,7 @@ where
|
||||||
Disassembler {
|
Disassembler {
|
||||||
base: base as Addr,
|
base: base as Addr,
|
||||||
pos: 0,
|
pos: 0,
|
||||||
bytes: bytes,
|
bytes,
|
||||||
word_size: std::mem::size_of::<D::IntType>(),
|
word_size: std::mem::size_of::<D::IntType>(),
|
||||||
instruction_decoder: PhantomData,
|
instruction_decoder: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -42,14 +43,9 @@ where
|
||||||
|
|
||||||
let addr = self.base + self.pos as Addr;
|
let addr = self.base + self.pos as Addr;
|
||||||
let decoded: D = D::decode_from_bytes(&self.bytes[(self.pos as usize)..], addr);
|
let decoded: D = D::decode_from_bytes(&self.bytes[(self.pos as usize)..], addr);
|
||||||
|
let decoded_raw = decoded.get_raw();
|
||||||
self.pos += self.word_size;
|
self.pos += self.word_size;
|
||||||
line.push_str(&format!(
|
write!(&mut line, "{addr:8x}:\t{decoded_raw:08x} \t{decoded}").unwrap();
|
||||||
"{:8x}:\t{:08x} \t{}",
|
|
||||||
addr,
|
|
||||||
decoded.get_raw(),
|
|
||||||
decoded
|
|
||||||
));
|
|
||||||
|
|
||||||
Some((self.pos as Addr, line))
|
Some((self.pos as Addr, line))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::memory::MemoryInterface;
|
||||||
use super::Arm7tdmiCore;
|
use super::Arm7tdmiCore;
|
||||||
use super::{CpuMode, CpuState};
|
use super::{CpuMode, CpuState};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// Models a CPU exception, and maps to the relavnt entry in the exception vector
|
/// Models a CPU exception, and maps to the relavnt entry in the exception vector
|
||||||
pub enum Exception {
|
pub enum Exception {
|
||||||
|
|
|
@ -3,9 +3,6 @@ extern crate serde;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate enum_primitive_derive;
|
extern crate enum_primitive_derive;
|
||||||
use bit;
|
|
||||||
use num;
|
|
||||||
use num_traits;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -35,7 +32,7 @@ pub mod registers_consts {
|
||||||
pub const REG_SP: usize = 13;
|
pub const REG_SP: usize = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum DecodedInstruction {
|
pub enum DecodedInstruction {
|
||||||
Arm(ArmInstruction),
|
Arm(ArmInstruction),
|
||||||
Thumb(ThumbInstruction),
|
Thumb(ThumbInstruction),
|
||||||
|
@ -77,7 +74,7 @@ pub fn reg_string<T: Into<usize>>(reg: T) -> &'static str {
|
||||||
reg_names[reg.into()]
|
reg_names[reg.into()]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Primitive, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Primitive, Copy, Clone)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum CpuState {
|
pub enum CpuState {
|
||||||
ARM = 0,
|
ARM = 0,
|
||||||
|
@ -94,7 +91,7 @@ impl fmt::Display for CpuState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Primitive, Copy, Clone, PartialEq)]
|
#[derive(Debug, Primitive, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum CpuMode {
|
pub enum CpuMode {
|
||||||
User = 0b10000,
|
User = 0b10000,
|
||||||
Fiq = 0b10001,
|
Fiq = 0b10001,
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl fmt::Display for MemoryAccess {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum MemoryAccessWidth {
|
pub enum MemoryAccessWidth {
|
||||||
MemoryAccess8 = 0,
|
MemoryAccess8 = 0,
|
||||||
|
|
|
@ -3,8 +3,8 @@ use std::fmt;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::bit::BitIndex;
|
use bit::BitIndex;
|
||||||
use crate::num::FromPrimitive;
|
use num::FromPrimitive;
|
||||||
|
|
||||||
use super::{CpuMode, CpuState};
|
use super::{CpuMode, CpuState};
|
||||||
|
|
||||||
|
|
|
@ -428,7 +428,7 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
}
|
}
|
||||||
if FLAG_R {
|
if FLAG_R {
|
||||||
pop!(REG_PC);
|
pop!(REG_PC);
|
||||||
self.pc = self.pc & !1;
|
self.pc &= !1;
|
||||||
result = CpuAction::PipelineFlushed;
|
result = CpuAction::PipelineFlushed;
|
||||||
self.reload_pipeline16();
|
self.reload_pipeline16();
|
||||||
}
|
}
|
||||||
|
@ -482,16 +482,12 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
if rlist.bit(r) {
|
if rlist.bit(r) {
|
||||||
let v = if r != RB {
|
let v = if r != RB {
|
||||||
self.gpr[r]
|
self.gpr[r]
|
||||||
} else {
|
} else if first {
|
||||||
if first {
|
|
||||||
addr
|
|
||||||
} else {
|
|
||||||
addr + (rlist.count_ones() - 1) * 4
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if first {
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
addr
|
||||||
|
} else {
|
||||||
|
addr + (rlist.count_ones() - 1) * 4
|
||||||
|
};
|
||||||
self.store_32(addr, v, access);
|
self.store_32(addr, v, access);
|
||||||
access = Seq;
|
access = Seq;
|
||||||
addr += 4;
|
addr += 4;
|
||||||
|
@ -559,7 +555,7 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
) -> CpuAction {
|
) -> CpuAction {
|
||||||
let mut off = insn.offset11();
|
let mut off = insn.offset11();
|
||||||
if FLAG_LOW_OFFSET {
|
if FLAG_LOW_OFFSET {
|
||||||
off = off << 1;
|
off <<= 1;
|
||||||
let next_pc = (self.pc - 2) | 1;
|
let next_pc = (self.pc - 2) | 1;
|
||||||
self.pc = ((self.gpr[REG_LR] & !1) as i32).wrapping_add(off) as u32;
|
self.pc = ((self.gpr[REG_LR] & !1) as i32).wrapping_add(off) as u32;
|
||||||
self.gpr[REG_LR] = next_pc;
|
self.gpr[REG_LR] = next_pc;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use num::FromPrimitive;
|
||||||
pub mod disass;
|
pub mod disass;
|
||||||
pub mod exec;
|
pub mod exec;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ThumbFormat {
|
pub enum ThumbFormat {
|
||||||
/// Format 1
|
/// Format 1
|
||||||
MoveShiftedReg,
|
MoveShiftedReg,
|
||||||
|
@ -102,7 +102,7 @@ impl From<u16> for ThumbFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ThumbInstruction {
|
pub struct ThumbInstruction {
|
||||||
pub fmt: ThumbFormat,
|
pub fmt: ThumbFormat,
|
||||||
pub raw: u16,
|
pub raw: u16,
|
||||||
|
@ -134,7 +134,7 @@ impl InstructionDecoder for ThumbInstruction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Primitive, PartialEq)]
|
#[derive(Debug, Primitive, PartialEq, Eq)]
|
||||||
pub enum OpFormat3 {
|
pub enum OpFormat3 {
|
||||||
MOV = 0,
|
MOV = 0,
|
||||||
CMP = 1,
|
CMP = 1,
|
||||||
|
@ -153,7 +153,7 @@ impl From<OpFormat3> for AluOpCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Primitive, PartialEq)]
|
#[derive(Debug, Primitive, PartialEq, Eq)]
|
||||||
pub enum OpFormat5 {
|
pub enum OpFormat5 {
|
||||||
ADD = 0,
|
ADD = 0,
|
||||||
CMP = 1,
|
CMP = 1,
|
||||||
|
@ -161,7 +161,7 @@ pub enum OpFormat5 {
|
||||||
BX = 3,
|
BX = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Primitive, PartialEq)]
|
#[derive(Debug, Primitive, PartialEq, Eq)]
|
||||||
pub enum ThumbAluOps {
|
pub enum ThumbAluOps {
|
||||||
AND = 0b0000,
|
AND = 0b0000,
|
||||||
EOR = 0b0001,
|
EOR = 0b0001,
|
||||||
|
@ -184,17 +184,11 @@ pub enum ThumbAluOps {
|
||||||
impl ThumbAluOps {
|
impl ThumbAluOps {
|
||||||
pub fn is_setting_flags(&self) -> bool {
|
pub fn is_setting_flags(&self) -> bool {
|
||||||
use ThumbAluOps::*;
|
use ThumbAluOps::*;
|
||||||
match self {
|
matches!(self, TST | CMP | CMN)
|
||||||
TST | CMP | CMN => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn is_arithmetic(&self) -> bool {
|
pub fn is_arithmetic(&self) -> bool {
|
||||||
use ThumbAluOps::*;
|
use ThumbAluOps::*;
|
||||||
match self {
|
matches!(self, ADC | SBC | NEG | CMP | CMN)
|
||||||
ADC | SBC | NEG | CMP | CMN => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue