moa/emulator/cpus/m68k/src/state.rs

257 lines
6.0 KiB
Rust

use moa_core::{Address, BusPort};
use moa_core::timers::CpuTimer;
use crate::instructions::Size;
use crate::decode::M68kDecoder;
use crate::debugger::M68kDebugger;
use crate::timing::M68kInstructionTiming;
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum M68kType {
MC68000,
MC68010,
MC68020,
MC68030,
}
const FLAGS_ON_RESET: u16 = 0x2700;
#[repr(u16)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Flags {
Carry = 0x0001,
Overflow = 0x0002,
Zero = 0x0004,
Negative = 0x0008,
Extend = 0x0010,
IntMask = 0x0700,
Interrupt = 0x1000,
Supervisor = 0x2000,
Tracing = 0x8000,
}
#[repr(u8)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Exceptions {
BusError = 2,
AddressError = 3,
IllegalInstruction = 4,
ZeroDivide = 5,
ChkInstruction = 6,
TrapvInstruction = 7,
PrivilegeViolation = 8,
Trace = 9,
LineAEmulator = 10,
LineFEmulator = 11,
}
#[repr(u8)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FunctionCode {
Reserved0 = 0,
UserData = 1,
UserProgram = 2,
Reserved3 = 3,
Reserved4 = 4,
SupervisorData = 5,
SupervisorProgram = 6,
CpuSpace = 7,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Status {
Init,
Running,
Stopped,
}
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InterruptPriority {
NoInterrupt = 0,
Level1 = 1,
Level2 = 2,
Level3 = 3,
Level4 = 4,
Level5 = 5,
Level6 = 6,
Level7 = 7,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MemType {
Program,
Data,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MemAccess {
Read,
Write,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MemoryRequest {
pub i_n_bit: bool,
pub access: MemAccess,
pub code: FunctionCode,
pub size: Size,
pub address: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct M68kState {
pub status: Status,
pub request: MemoryRequest,
pub current_ipl: InterruptPriority,
pub pending_ipl: InterruptPriority,
pub pc: u32,
pub sr: u16,
pub d_reg: [u32; 8],
pub a_reg: [u32; 7],
pub ssp: u32,
pub usp: u32,
pub vbr: u32,
}
#[derive(Clone)]
pub struct M68k {
pub cputype: M68kType,
pub frequency: u32,
pub state: M68kState,
pub decoder: M68kDecoder,
pub timing: M68kInstructionTiming,
pub debugger: M68kDebugger,
pub port: BusPort,
pub timer: CpuTimer,
}
impl Default for M68kState {
fn default() -> M68kState {
M68kState {
status: Status::Init,
request: MemoryRequest::default(),
current_ipl: InterruptPriority::NoInterrupt,
pending_ipl: InterruptPriority::NoInterrupt,
pc: 0,
sr: FLAGS_ON_RESET,
d_reg: [0; 8],
a_reg: [0; 7],
ssp: 0,
usp: 0,
vbr: 0,
}
}
}
impl M68k {
pub fn new(cputype: M68kType, frequency: u32, port: BusPort) -> M68k {
M68k {
cputype,
frequency,
state: M68kState::default(),
decoder: M68kDecoder::new(cputype, 0),
timing: M68kInstructionTiming::new(cputype, port.data_width()),
debugger: M68kDebugger::default(),
port,
timer: CpuTimer::default(),
}
}
#[allow(dead_code)]
pub fn reset(&mut self) {
self.state = M68kState::default();
self.decoder = M68kDecoder::new(self.cputype, 0);
self.timing = M68kInstructionTiming::new(self.cputype, self.port.data_width());
self.debugger = M68kDebugger::default();
}
pub fn dump_state(&mut self) {
println!("Status: {:?}", self.state.status);
println!("PC: {:#010x}", self.state.pc);
println!("SR: {:#06x}", self.state.sr);
for i in 0..7 {
println!("D{}: {:#010x} A{}: {:#010x}", i, self.state.d_reg[i as usize], i, self.state.a_reg[i as usize]);
}
println!("D7: {:#010x} USP: {:#010x}", self.state.d_reg[7], self.state.usp);
println!(" SSP: {:#010x}", self.state.ssp);
println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction);
println!();
self.port.dump_memory(self.state.ssp as Address, 0x40);
println!();
}
}
impl InterruptPriority {
pub fn from_u8(priority: u8) -> InterruptPriority {
match priority {
0 => InterruptPriority::NoInterrupt,
1 => InterruptPriority::Level1,
2 => InterruptPriority::Level2,
3 => InterruptPriority::Level3,
4 => InterruptPriority::Level4,
5 => InterruptPriority::Level5,
6 => InterruptPriority::Level6,
_ => InterruptPriority::Level7,
}
}
}
impl FunctionCode {
pub fn program(sr: u16) -> Self {
if sr & Flags::Supervisor as u16 != 0 {
FunctionCode::SupervisorProgram
} else {
FunctionCode::UserProgram
}
}
pub fn data(sr: u16) -> Self {
if sr & Flags::Supervisor as u16 != 0 {
FunctionCode::SupervisorData
} else {
FunctionCode::UserData
}
}
}
impl Default for MemoryRequest {
fn default() -> Self {
Self {
i_n_bit: false,
access: MemAccess::Read,
code: FunctionCode::Reserved0,
size: Size::Word,
address: 0,
}
}
}
impl MemoryRequest {
pub fn get_type_code(&self) -> u16 {
let ins = match self.i_n_bit {
false => 0x0000,
true => 0x0008,
};
let rw = match self.access {
MemAccess::Write => 0x0000,
MemAccess::Read => 0x0010,
};
ins | rw | (self.code as u16)
}
}