From 3fc76335d005c1dfebe9760bbbf3f232f8e82e26 Mon Sep 17 00:00:00 2001 From: transistor Date: Mon, 18 Oct 2021 12:05:10 -0700 Subject: [PATCH] Moved m68k instruction types to their own file --- src/cpus/m68k/decode.rs | 422 ++-------------------------------- src/cpus/m68k/execute.rs | 15 +- src/cpus/m68k/instructions.rs | 408 ++++++++++++++++++++++++++++++++ src/cpus/m68k/mod.rs | 1 + src/cpus/m68k/tests.rs | 38 +-- src/devices.rs | 2 +- src/memory.rs | 3 +- src/peripherals/ata.rs | 3 +- src/system.rs | 2 +- 9 files changed, 453 insertions(+), 441 deletions(-) create mode 100644 src/cpus/m68k/instructions.rs diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index b8b8909..7887c99 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -1,11 +1,22 @@ -use std::fmt; - use crate::error::Error; use crate::system::System; use crate::devices::{Address, Addressable}; use super::state::{M68kType, Exceptions}; +use super::instructions::{ + Size, + Sign, + Direction, + ShiftDirection, + XRegister, + RegOrImmediate, + ControlRegister, + Condition, + Target, + Instruction, + sign_extend_to_long, +}; const OPCG_BIT_OPS: u8 = 0x0; @@ -29,184 +40,6 @@ const OPCG_RESERVED1: u8 = 0xA; const OPCG_RESERVED2: u8 = 0xF; -pub type Register = u8; - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Sign { - Signed, - Unsigned, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Direction { - FromTarget, - ToTarget, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum ShiftDirection { - Right, - Left, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum XRegister { - Data(u8), - Address(u8), -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum RegOrImmediate { - DReg(u8), - Immediate(u8), -} - - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum ControlRegister { - VBR, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Size { - Byte, - Word, - Long, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Condition { - True, - False, - High, - LowOrSame, - CarryClear, - CarrySet, - NotEqual, - Equal, - OverflowClear, - OverflowSet, - Plus, - Minus, - GreaterThanOrEqual, - LessThan, - GreaterThan, - LessThanOrEqual, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Target { - Immediate(u32), - DirectDReg(Register), - DirectAReg(Register), - IndirectAReg(Register), - IndirectARegInc(Register), - IndirectARegDec(Register), - IndirectARegOffset(Register, i32), - IndirectARegXRegOffset(Register, XRegister, i32, u8, Size), - IndirectMemory(u32), - IndirectPCOffset(i32), - IndirectPCXRegOffset(XRegister, i32, u8, Size), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum Instruction { - ABCD(Target, Target), - ADD(Target, Target, Size), - AND(Target, Target, Size), - ANDtoCCR(u8), - ANDtoSR(u16), - ASd(Target, Target, Size, ShiftDirection), - - Bcc(Condition, i32), - BRA(i32), - BSR(i32), - BCHG(Target, Target, Size), - BCLR(Target, Target, Size), - BSET(Target, Target, Size), - BTST(Target, Target, Size), - BFCHG(Target, RegOrImmediate, RegOrImmediate), - BFCLR(Target, RegOrImmediate, RegOrImmediate), - BFEXTS(Target, RegOrImmediate, RegOrImmediate, Register), - BFEXTU(Target, RegOrImmediate, RegOrImmediate, Register), - BFFFO(Target, RegOrImmediate, RegOrImmediate, Register), - BFINS(Register, Target, RegOrImmediate, RegOrImmediate), - BFSET(Target, RegOrImmediate, RegOrImmediate), - BFTST(Target, RegOrImmediate, RegOrImmediate), - BKPT(u8), - - CHK(Target, Register, Size), - CLR(Target, Size), - CMP(Target, Target, Size), - CMPA(Target, Register, Size), - - DBcc(Condition, Register, i16), - DIV(Target, Target, Size, Sign), - - EOR(Target, Target, Size), - EORtoCCR(u8), - EORtoSR(u16), - EXG(Target, Target), - EXT(Register, Size, Size), - - ILLEGAL, - - JMP(Target), - JSR(Target), - - LEA(Target, Register), - LINK(Register, i16), - LSd(Target, Target, Size, ShiftDirection), - - MOVE(Target, Target, Size), - MOVEA(Target, Register, Size), - MOVEfromSR(Target), - MOVEtoSR(Target), - MOVEfromCCR(Target), - MOVEtoCCR(Target), - MOVEC(Target, ControlRegister, Direction), - MOVEM(Target, Size, Direction, u16), - MOVEP(Register, Target, Size, Direction), - MOVEQ(u8, Register), - MOVEUSP(Target, Direction), - MUL(Target, Target, Size, Sign), - - NBCD(Target), - NEG(Target, Size), - NEGX(Target, Size), - - NOP, - NOT(Target, Size), - - OR(Target, Target, Size), - ORtoCCR(u8), - ORtoSR(u16), - - PEA(Target), - - RESET, - ROd(Target, Target, Size, ShiftDirection), - ROXd(Target, Target, Size, ShiftDirection), - RTE, - RTR, - RTS, - RTD(i16), - - SBCD(Target, Target), - Scc(Condition, Target), - STOP(u16), - SUB(Target, Target, Size), - SWAP(Register), - - TAS(Target), - TST(Target, Size), - TRAP(u8), - TRAPV, - - UNLK(Register), -} - - pub struct M68kDecoder { pub cputype: M68kType, pub base: u32, @@ -929,232 +762,3 @@ fn get_condition(ins: u16) -> Condition { } } - -impl Size { - pub fn in_bytes(&self) -> u32 { - match self { - Size::Byte => 1, - Size::Word => 2, - Size::Long => 4, - } - } - - pub fn in_bits(&self) -> u32 { - match self { - Size::Byte => 8, - Size::Word => 16, - Size::Long => 32, - } - } -} - -pub fn sign_extend_to_long(value: u32, from: Size) -> i32 { - match from { - Size::Byte => ((value as u8) as i8) as i32, - Size::Word => ((value as u16) as i16) as i32, - Size::Long => value as i32, - } -} - - -impl fmt::Display for Sign { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Sign::Signed => write!(f, "s"), - Sign::Unsigned => write!(f, "u"), - } - } -} - -impl fmt::Display for ShiftDirection { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ShiftDirection::Right => write!(f, "r"), - ShiftDirection::Left => write!(f, "l"), - } - } -} - -impl fmt::Display for Size { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Size::Byte => write!(f, "b"), - Size::Word => write!(f, "w"), - Size::Long => write!(f, "l"), - } - } -} - -impl fmt::Display for Condition { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Condition::True => write!(f, "t"), - Condition::False => write!(f, "f"), - Condition::High => write!(f, "hi"), - Condition::LowOrSame => write!(f, "ls"), - Condition::CarryClear => write!(f, "cc"), - Condition::CarrySet => write!(f, "cs"), - Condition::NotEqual => write!(f, "ne"), - Condition::Equal => write!(f, "eq"), - Condition::OverflowClear => write!(f, "oc"), - Condition::OverflowSet => write!(f, "os"), - Condition::Plus => write!(f, "p"), - Condition::Minus => write!(f, "m"), - Condition::GreaterThanOrEqual => write!(f, "ge"), - Condition::LessThan => write!(f, "lt"), - Condition::GreaterThan => write!(f, "gt"), - Condition::LessThanOrEqual => write!(f, "le"), - } - } -} - -impl fmt::Display for ControlRegister { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ControlRegister::VBR => write!(f, "%vbr"), - } - } -} - -impl fmt::Display for XRegister { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - XRegister::Data(reg) => write!(f, "d{}", reg), - XRegister::Address(reg) => write!(f, "a{}", reg), - } - } -} - -impl fmt::Display for Target { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Target::Immediate(value) => write!(f, "#{:08x}", value), - Target::DirectDReg(reg) => write!(f, "%d{}", reg), - Target::DirectAReg(reg) => write!(f, "%a{}", reg), - Target::IndirectAReg(reg) => write!(f, "(%a{})", reg), - Target::IndirectARegInc(reg) => write!(f, "(%a{})+", reg), - Target::IndirectARegDec(reg) => write!(f, "-(%a{})", reg), - Target::IndirectARegOffset(reg, offset) => write!(f, "(%a{} + #{:04x})", reg, offset), - Target::IndirectARegXRegOffset(reg, xreg, offset, scale, _) => { - let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() }; - write!(f, "(%a{} + %{} + #{:04x}{})", reg, xreg, offset, scale_str) - }, - Target::IndirectMemory(value) => write!(f, "(#{:08x})", value), - Target::IndirectPCOffset(offset) => write!(f, "(%pc + #{:04x})", offset), - Target::IndirectPCXRegOffset(xreg, offset, scale, _) => { - let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() }; - write!(f, "(%pc + %{} + #{:04x}{})", xreg, offset, scale_str) - }, - } - } -} - -fn fmt_movem_mask(mask: u16) -> String { - format!("something") -} - -impl fmt::Display for Instruction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Instruction::ABCD(src, dest) => write!(f, "abcd\t{}, {}", src, dest), - Instruction::ADD(src, dest, size) => write!(f, "add{}\t{}, {}", size, src, dest), - Instruction::AND(src, dest, size) => write!(f, "and{}\t{}, {}", size, src, dest), - Instruction::ANDtoCCR(value) => write!(f, "andb\t{:02x}, %ccr", value), - Instruction::ANDtoSR(value) => write!(f, "andw\t{:04x}, %sr", value), - Instruction::ASd(src, dest, size, dir) => write!(f, "as{}{}\t{}, {}", dir, size, src, dest), - - Instruction::Bcc(cond, offset) => write!(f, "b{}\t{}", cond, offset), - Instruction::BRA(offset) => write!(f, "bra\t{}", offset), - Instruction::BSR(offset) => write!(f, "bra\t{}", offset), - Instruction::BCHG(src, dest, size) => write!(f, "bchg{}\t{}, {}", size, src, dest), - Instruction::BCLR(src, dest, size) => write!(f, "bclr{}\t{}, {}", size, src, dest), - Instruction::BSET(src, dest, size) => write!(f, "bset{}\t{}, {}", size, src, dest), - Instruction::BTST(src, dest, size) => write!(f, "btst{}\t{}, {}", size, src, dest), - //Instruction::BKPT(value), - - Instruction::CHK(target, reg, size) => write!(f, "chk{}\t{}, %d{}", size, target, reg), - Instruction::CLR(target, size) => write!(f, "clr{}\t{}", size, target), - Instruction::CMP(src, dest, size) => write!(f, "cmp{}\t{}, {}", size, src, dest), - Instruction::CMPA(target, reg, size) => write!(f, "cmpa{}\t{}, %a{}", size, target, reg), - - Instruction::DBcc(cond, reg, offset) => write!(f, "db{}\t%d{}, {}", cond, reg, offset), - Instruction::DIV(src, dest, size, sign) => write!(f, "div{}{}\t{}, {}", sign, size, src, dest), - - Instruction::EOR(src, dest, size) => write!(f, "eor{}\t{}, {}", size, src, dest), - Instruction::EORtoCCR(value) => write!(f, "eorb\t{:02x}, %ccr", value), - Instruction::EORtoSR(value) => write!(f, "eorw\t{:04x}, %sr", value), - Instruction::EXG(src, dest) => write!(f, "exg\t{}, {}", src, dest), - Instruction::EXT(reg, from_size, to_size) => write!(f, "ext{}{}\t%d{}", from_size, to_size, reg), - - Instruction::ILLEGAL => write!(f, "illegal"), - - Instruction::JMP(target) => write!(f, "jmp\t{}", target), - Instruction::JSR(target) => write!(f, "jsr\t{}", target), - - Instruction::LEA(target, reg) => write!(f, "lea\t{}, %a{}", target, reg), - Instruction::LINK(reg, offset) => write!(f, "link\t%a{}, {}", reg, offset), - Instruction::LSd(src, dest, size, dir) => write!(f, "ls{}{}\t{}, {}", dir, size, src, dest), - - Instruction::MOVE(src, dest, size) => write!(f, "move{}\t{}, {}", size, src, dest), - Instruction::MOVEA(target, reg, size) => write!(f, "movea{}\t{}, %a{}", size, target, reg), - Instruction::MOVEfromSR(target) => write!(f, "movew\t%sr, {}", target), - Instruction::MOVEtoSR(target) => write!(f, "movew\t{}, %sr", target), - Instruction::MOVEfromCCR(target) => write!(f, "moveb\t%ccr, {}", target), - Instruction::MOVEtoCCR(target) => write!(f, "moveb\t{}, %ccr", target), - Instruction::MOVEC(target, reg, dir) => match dir { - Direction::ToTarget => write!(f, "movec\t{}, {}", reg, target), - Direction::FromTarget => write!(f, "movec\t{}, {}", target, reg), - }, - Instruction::MOVEM(target, size, dir, mask) => match dir { - Direction::ToTarget => write!(f, "movem{}\t{}, {}", size, fmt_movem_mask(*mask), target), - Direction::FromTarget => write!(f, "movem{}\t{}, {}", size, target, fmt_movem_mask(*mask)), - }, - Instruction::MOVEP(reg, target, size, dir) => match dir { - Direction::ToTarget => write!(f, "movep{}\t%d{}, {}", size, reg, target), - Direction::FromTarget => write!(f, "movep{}\t{}, %d{}", size, target, reg), - }, - Instruction::MOVEQ(value, reg) => write!(f, "moveq\t#{:02x}, %d{}", value, reg), - Instruction::MOVEUSP(target, dir) => match dir { - Direction::ToTarget => write!(f, "movel\t%usp, {}", target), - Direction::FromTarget => write!(f, "movel\t{}, %usp", target), - }, - Instruction::MUL(src, dest, size, sign) => write!(f, "mul{}{}\t{}, {}", sign, size, src, dest), - - Instruction::NBCD(target) => write!(f, "nbcd\t{}", target), - Instruction::NEG(target, size) => write!(f, "neg{}\t{}", size, target), - Instruction::NEGX(target, size) => write!(f, "negx{}\t{}", size, target), - - Instruction::NOP => write!(f, "nop"), - Instruction::NOT(target, size) => write!(f, "not{}\t{}", size, target), - - Instruction::OR(src, dest, size) => write!(f, "or{}\t{}, {}", size, src, dest), - Instruction::ORtoCCR(value) => write!(f, "orb\t{:02x}, %ccr", value), - Instruction::ORtoSR(value) => write!(f, "orw\t{:04x}, %sr", value), - - Instruction::PEA(target) => write!(f, "pea\t{}", target), - - Instruction::RESET => write!(f, "reset"), - Instruction::ROd(src, dest, size, dir) => write!(f, "ro{}{}\t{}, {}", dir, size, src, dest), - Instruction::ROXd(src, dest, size, dir) => write!(f, "rox{}{}\t{}, {}", dir, size, src, dest), - Instruction::RTE => write!(f, "rte"), - Instruction::RTR => write!(f, "rtr"), - Instruction::RTS => write!(f, "rts"), - Instruction::RTD(offset) => write!(f, "rtd\t{}", offset), - - Instruction::SBCD(src, dest) => write!(f, "sbcd\t{}, {}", src, dest), - Instruction::Scc(cond, target) => write!(f, "s{}\t{}", cond, target), - Instruction::STOP(value) => write!(f, "stop\t#{:04x}", value), - Instruction::SUB(src, dest, size) => write!(f, "sub{}\t{}, {}", size, src, dest), - Instruction::SWAP(reg) => write!(f, "swap\t%d{}", reg), - - Instruction::TAS(target) => write!(f, "tas\t{}", target), - Instruction::TST(target, size) => write!(f, "tst{}\t{}", size, target), - Instruction::TRAP(num) => write!(f, "trap\t{}", num), - Instruction::TRAPV => write!(f, "trapv"), - - Instruction::UNLK(reg) => write!(f, "unlk\t%a{}", reg), - _ => write!(f, "UNIMPL"), - } - } -} - diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 01e8173..8b1f7c9 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -3,21 +3,22 @@ use crate::system::System; use crate::error::{ErrorType, Error}; use crate::devices::{Clock, Address, Steppable, Interruptable, Addressable, Transmutable}; -use super::decode::{ - Instruction, - Target, +use super::instructions::{ + Register, Size, Sign, Direction, - Condition, ShiftDirection, - ControlRegister, - Register, XRegister, RegOrImmediate, - sign_extend_to_long + ControlRegister, + Condition, + Target, + Instruction, + sign_extend_to_long, }; + const DEV_NAME: &'static str = "m68k-cpu"; use super::state::{M68k, Status, Flags, Exceptions, InterruptPriority}; diff --git a/src/cpus/m68k/instructions.rs b/src/cpus/m68k/instructions.rs new file mode 100644 index 0000000..5e95be2 --- /dev/null +++ b/src/cpus/m68k/instructions.rs @@ -0,0 +1,408 @@ + +use std::fmt; + + +pub type Register = u8; + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Size { + Byte, + Word, + Long, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Sign { + Signed, + Unsigned, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Direction { + FromTarget, + ToTarget, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ShiftDirection { + Right, + Left, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum XRegister { + Data(u8), + Address(u8), +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum RegOrImmediate { + DReg(u8), + Immediate(u8), +} + + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ControlRegister { + VBR, +} +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Condition { + True, + False, + High, + LowOrSame, + CarryClear, + CarrySet, + NotEqual, + Equal, + OverflowClear, + OverflowSet, + Plus, + Minus, + GreaterThanOrEqual, + LessThan, + GreaterThan, + LessThanOrEqual, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Target { + Immediate(u32), + DirectDReg(Register), + DirectAReg(Register), + IndirectAReg(Register), + IndirectARegInc(Register), + IndirectARegDec(Register), + IndirectARegOffset(Register, i32), + IndirectARegXRegOffset(Register, XRegister, i32, u8, Size), + IndirectMemory(u32), + IndirectPCOffset(i32), + IndirectPCXRegOffset(XRegister, i32, u8, Size), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Instruction { + ABCD(Target, Target), + ADD(Target, Target, Size), + AND(Target, Target, Size), + ANDtoCCR(u8), + ANDtoSR(u16), + ASd(Target, Target, Size, ShiftDirection), + + Bcc(Condition, i32), + BRA(i32), + BSR(i32), + BCHG(Target, Target, Size), + BCLR(Target, Target, Size), + BSET(Target, Target, Size), + BTST(Target, Target, Size), + BFCHG(Target, RegOrImmediate, RegOrImmediate), + BFCLR(Target, RegOrImmediate, RegOrImmediate), + BFEXTS(Target, RegOrImmediate, RegOrImmediate, Register), + BFEXTU(Target, RegOrImmediate, RegOrImmediate, Register), + BFFFO(Target, RegOrImmediate, RegOrImmediate, Register), + BFINS(Register, Target, RegOrImmediate, RegOrImmediate), + BFSET(Target, RegOrImmediate, RegOrImmediate), + BFTST(Target, RegOrImmediate, RegOrImmediate), + BKPT(u8), + + CHK(Target, Register, Size), + CLR(Target, Size), + CMP(Target, Target, Size), + CMPA(Target, Register, Size), + + DBcc(Condition, Register, i16), + DIV(Target, Target, Size, Sign), + + EOR(Target, Target, Size), + EORtoCCR(u8), + EORtoSR(u16), + EXG(Target, Target), + EXT(Register, Size, Size), + + ILLEGAL, + + JMP(Target), + JSR(Target), + + LEA(Target, Register), + LINK(Register, i16), + LSd(Target, Target, Size, ShiftDirection), + + MOVE(Target, Target, Size), + MOVEA(Target, Register, Size), + MOVEfromSR(Target), + MOVEtoSR(Target), + MOVEfromCCR(Target), + MOVEtoCCR(Target), + MOVEC(Target, ControlRegister, Direction), + MOVEM(Target, Size, Direction, u16), + MOVEP(Register, Target, Size, Direction), + MOVEQ(u8, Register), + MOVEUSP(Target, Direction), + MUL(Target, Target, Size, Sign), + + NBCD(Target), + NEG(Target, Size), + NEGX(Target, Size), + + NOP, + NOT(Target, Size), + + OR(Target, Target, Size), + ORtoCCR(u8), + ORtoSR(u16), + + PEA(Target), + + RESET, + ROd(Target, Target, Size, ShiftDirection), + ROXd(Target, Target, Size, ShiftDirection), + RTE, + RTR, + RTS, + RTD(i16), + + SBCD(Target, Target), + Scc(Condition, Target), + STOP(u16), + SUB(Target, Target, Size), + SWAP(Register), + + TAS(Target), + TST(Target, Size), + TRAP(u8), + TRAPV, + + UNLK(Register), +} + +pub fn sign_extend_to_long(value: u32, from: Size) -> i32 { + match from { + Size::Byte => ((value as u8) as i8) as i32, + Size::Word => ((value as u16) as i16) as i32, + Size::Long => value as i32, + } +} + +impl Size { + pub fn in_bytes(&self) -> u32 { + match self { + Size::Byte => 1, + Size::Word => 2, + Size::Long => 4, + } + } + + pub fn in_bits(&self) -> u32 { + match self { + Size::Byte => 8, + Size::Word => 16, + Size::Long => 32, + } + } +} + + +impl fmt::Display for Sign { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Sign::Signed => write!(f, "s"), + Sign::Unsigned => write!(f, "u"), + } + } +} + +impl fmt::Display for ShiftDirection { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ShiftDirection::Right => write!(f, "r"), + ShiftDirection::Left => write!(f, "l"), + } + } +} + +impl fmt::Display for Size { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Size::Byte => write!(f, "b"), + Size::Word => write!(f, "w"), + Size::Long => write!(f, "l"), + } + } +} + +impl fmt::Display for Condition { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Condition::True => write!(f, "t"), + Condition::False => write!(f, "f"), + Condition::High => write!(f, "hi"), + Condition::LowOrSame => write!(f, "ls"), + Condition::CarryClear => write!(f, "cc"), + Condition::CarrySet => write!(f, "cs"), + Condition::NotEqual => write!(f, "ne"), + Condition::Equal => write!(f, "eq"), + Condition::OverflowClear => write!(f, "oc"), + Condition::OverflowSet => write!(f, "os"), + Condition::Plus => write!(f, "p"), + Condition::Minus => write!(f, "m"), + Condition::GreaterThanOrEqual => write!(f, "ge"), + Condition::LessThan => write!(f, "lt"), + Condition::GreaterThan => write!(f, "gt"), + Condition::LessThanOrEqual => write!(f, "le"), + } + } +} + +impl fmt::Display for ControlRegister { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ControlRegister::VBR => write!(f, "%vbr"), + } + } +} + +impl fmt::Display for XRegister { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + XRegister::Data(reg) => write!(f, "d{}", reg), + XRegister::Address(reg) => write!(f, "a{}", reg), + } + } +} + +impl fmt::Display for Target { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Target::Immediate(value) => write!(f, "#{:08x}", value), + Target::DirectDReg(reg) => write!(f, "%d{}", reg), + Target::DirectAReg(reg) => write!(f, "%a{}", reg), + Target::IndirectAReg(reg) => write!(f, "(%a{})", reg), + Target::IndirectARegInc(reg) => write!(f, "(%a{})+", reg), + Target::IndirectARegDec(reg) => write!(f, "-(%a{})", reg), + Target::IndirectARegOffset(reg, offset) => write!(f, "(%a{} + #{:04x})", reg, offset), + Target::IndirectARegXRegOffset(reg, xreg, offset, scale, _) => { + let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() }; + write!(f, "(%a{} + %{} + #{:04x}{})", reg, xreg, offset, scale_str) + }, + Target::IndirectMemory(value) => write!(f, "(#{:08x})", value), + Target::IndirectPCOffset(offset) => write!(f, "(%pc + #{:04x})", offset), + Target::IndirectPCXRegOffset(xreg, offset, scale, _) => { + let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() }; + write!(f, "(%pc + %{} + #{:04x}{})", xreg, offset, scale_str) + }, + } + } +} + +fn fmt_movem_mask(mask: u16) -> String { + format!("something") +} + +impl fmt::Display for Instruction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Instruction::ABCD(src, dest) => write!(f, "abcd\t{}, {}", src, dest), + Instruction::ADD(src, dest, size) => write!(f, "add{}\t{}, {}", size, src, dest), + Instruction::AND(src, dest, size) => write!(f, "and{}\t{}, {}", size, src, dest), + Instruction::ANDtoCCR(value) => write!(f, "andb\t{:02x}, %ccr", value), + Instruction::ANDtoSR(value) => write!(f, "andw\t{:04x}, %sr", value), + Instruction::ASd(src, dest, size, dir) => write!(f, "as{}{}\t{}, {}", dir, size, src, dest), + + Instruction::Bcc(cond, offset) => write!(f, "b{}\t{}", cond, offset), + Instruction::BRA(offset) => write!(f, "bra\t{}", offset), + Instruction::BSR(offset) => write!(f, "bra\t{}", offset), + Instruction::BCHG(src, dest, size) => write!(f, "bchg{}\t{}, {}", size, src, dest), + Instruction::BCLR(src, dest, size) => write!(f, "bclr{}\t{}, {}", size, src, dest), + Instruction::BSET(src, dest, size) => write!(f, "bset{}\t{}, {}", size, src, dest), + Instruction::BTST(src, dest, size) => write!(f, "btst{}\t{}, {}", size, src, dest), + //Instruction::BKPT(value), + + Instruction::CHK(target, reg, size) => write!(f, "chk{}\t{}, %d{}", size, target, reg), + Instruction::CLR(target, size) => write!(f, "clr{}\t{}", size, target), + Instruction::CMP(src, dest, size) => write!(f, "cmp{}\t{}, {}", size, src, dest), + Instruction::CMPA(target, reg, size) => write!(f, "cmpa{}\t{}, %a{}", size, target, reg), + + Instruction::DBcc(cond, reg, offset) => write!(f, "db{}\t%d{}, {}", cond, reg, offset), + Instruction::DIV(src, dest, size, sign) => write!(f, "div{}{}\t{}, {}", sign, size, src, dest), + + Instruction::EOR(src, dest, size) => write!(f, "eor{}\t{}, {}", size, src, dest), + Instruction::EORtoCCR(value) => write!(f, "eorb\t{:02x}, %ccr", value), + Instruction::EORtoSR(value) => write!(f, "eorw\t{:04x}, %sr", value), + Instruction::EXG(src, dest) => write!(f, "exg\t{}, {}", src, dest), + Instruction::EXT(reg, from_size, to_size) => write!(f, "ext{}{}\t%d{}", from_size, to_size, reg), + + Instruction::ILLEGAL => write!(f, "illegal"), + + Instruction::JMP(target) => write!(f, "jmp\t{}", target), + Instruction::JSR(target) => write!(f, "jsr\t{}", target), + + Instruction::LEA(target, reg) => write!(f, "lea\t{}, %a{}", target, reg), + Instruction::LINK(reg, offset) => write!(f, "link\t%a{}, {}", reg, offset), + Instruction::LSd(src, dest, size, dir) => write!(f, "ls{}{}\t{}, {}", dir, size, src, dest), + + Instruction::MOVE(src, dest, size) => write!(f, "move{}\t{}, {}", size, src, dest), + Instruction::MOVEA(target, reg, size) => write!(f, "movea{}\t{}, %a{}", size, target, reg), + Instruction::MOVEfromSR(target) => write!(f, "movew\t%sr, {}", target), + Instruction::MOVEtoSR(target) => write!(f, "movew\t{}, %sr", target), + Instruction::MOVEfromCCR(target) => write!(f, "moveb\t%ccr, {}", target), + Instruction::MOVEtoCCR(target) => write!(f, "moveb\t{}, %ccr", target), + Instruction::MOVEC(target, reg, dir) => match dir { + Direction::ToTarget => write!(f, "movec\t{}, {}", reg, target), + Direction::FromTarget => write!(f, "movec\t{}, {}", target, reg), + }, + Instruction::MOVEM(target, size, dir, mask) => match dir { + Direction::ToTarget => write!(f, "movem{}\t{}, {}", size, fmt_movem_mask(*mask), target), + Direction::FromTarget => write!(f, "movem{}\t{}, {}", size, target, fmt_movem_mask(*mask)), + }, + Instruction::MOVEP(reg, target, size, dir) => match dir { + Direction::ToTarget => write!(f, "movep{}\t%d{}, {}", size, reg, target), + Direction::FromTarget => write!(f, "movep{}\t{}, %d{}", size, target, reg), + }, + Instruction::MOVEQ(value, reg) => write!(f, "moveq\t#{:02x}, %d{}", value, reg), + Instruction::MOVEUSP(target, dir) => match dir { + Direction::ToTarget => write!(f, "movel\t%usp, {}", target), + Direction::FromTarget => write!(f, "movel\t{}, %usp", target), + }, + Instruction::MUL(src, dest, size, sign) => write!(f, "mul{}{}\t{}, {}", sign, size, src, dest), + + Instruction::NBCD(target) => write!(f, "nbcd\t{}", target), + Instruction::NEG(target, size) => write!(f, "neg{}\t{}", size, target), + Instruction::NEGX(target, size) => write!(f, "negx{}\t{}", size, target), + + Instruction::NOP => write!(f, "nop"), + Instruction::NOT(target, size) => write!(f, "not{}\t{}", size, target), + + Instruction::OR(src, dest, size) => write!(f, "or{}\t{}, {}", size, src, dest), + Instruction::ORtoCCR(value) => write!(f, "orb\t{:02x}, %ccr", value), + Instruction::ORtoSR(value) => write!(f, "orw\t{:04x}, %sr", value), + + Instruction::PEA(target) => write!(f, "pea\t{}", target), + + Instruction::RESET => write!(f, "reset"), + Instruction::ROd(src, dest, size, dir) => write!(f, "ro{}{}\t{}, {}", dir, size, src, dest), + Instruction::ROXd(src, dest, size, dir) => write!(f, "rox{}{}\t{}, {}", dir, size, src, dest), + Instruction::RTE => write!(f, "rte"), + Instruction::RTR => write!(f, "rtr"), + Instruction::RTS => write!(f, "rts"), + Instruction::RTD(offset) => write!(f, "rtd\t{}", offset), + + Instruction::SBCD(src, dest) => write!(f, "sbcd\t{}, {}", src, dest), + Instruction::Scc(cond, target) => write!(f, "s{}\t{}", cond, target), + Instruction::STOP(value) => write!(f, "stop\t#{:04x}", value), + Instruction::SUB(src, dest, size) => write!(f, "sub{}\t{}, {}", size, src, dest), + Instruction::SWAP(reg) => write!(f, "swap\t%d{}", reg), + + Instruction::TAS(target) => write!(f, "tas\t{}", target), + Instruction::TST(target, size) => write!(f, "tst{}\t{}", size, target), + Instruction::TRAP(num) => write!(f, "trap\t{}", num), + Instruction::TRAPV => write!(f, "trapv"), + + Instruction::UNLK(reg) => write!(f, "unlk\t%a{}", reg), + _ => write!(f, "UNIMPL"), + } + } +} + diff --git a/src/cpus/m68k/mod.rs b/src/cpus/m68k/mod.rs index 1811369..f1e48f9 100644 --- a/src/cpus/m68k/mod.rs +++ b/src/cpus/m68k/mod.rs @@ -3,6 +3,7 @@ pub mod state; pub mod decode; pub mod execute; pub mod debugger; +pub mod instructions; pub mod tests; pub use self::state::{M68k, M68kType}; diff --git a/src/cpus/m68k/tests.rs b/src/cpus/m68k/tests.rs index 1151cf0..093ec67 100644 --- a/src/cpus/m68k/tests.rs +++ b/src/cpus/m68k/tests.rs @@ -3,10 +3,10 @@ mod decode_tests { use crate::system::System; use crate::memory::MemoryBlock; - use crate::devices::{Address, Addressable, Steppable, AddressableDeviceBox, wrap_addressable, MAX_READ}; + use crate::devices::{Address, Addressable, Steppable, TransmutableBox, wrap_transmutable, MAX_READ}; use crate::cpus::m68k::{M68k, M68kType}; - use crate::cpus::m68k::decode::{Instruction, Target, Size, Sign, XRegister, ShiftDirection}; + use crate::cpus::m68k::instructions::{Instruction, Target, Size, Sign, XRegister, ShiftDirection}; const INIT_STACK: Address = 0x00002000; const INIT_ADDR: Address = 0x00000010; @@ -17,7 +17,7 @@ mod decode_tests { // Insert basic initialization let data = vec![0; 0x00100000]; let mem = MemoryBlock::new(data); - system.add_addressable_device(0x00000000, wrap_addressable(mem)).unwrap(); + system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap(); system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap(); system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap(); @@ -30,7 +30,7 @@ mod decode_tests { (cpu, system) } - fn get_decode_memory(cpu: &mut M68k, system: &System) -> AddressableDeviceBox { + fn get_decode_memory(cpu: &mut M68k, system: &System) -> TransmutableBox { let (memory, relative_addr) = system.get_bus().get_device_at(INIT_ADDR, 12).unwrap(); cpu.decoder.init((INIT_ADDR - relative_addr) as u32, INIT_ADDR as u32); memory @@ -48,7 +48,7 @@ mod decode_tests { let expected = 0x1234; let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b000, 0b001, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b000, 0b001, Some(size)).unwrap(); assert_eq!(target, Target::DirectDReg(1)); } @@ -60,7 +60,7 @@ mod decode_tests { let expected = 0x1234; let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b001, 0b010, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b001, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::DirectAReg(2)); } @@ -75,7 +75,7 @@ mod decode_tests { system.get_bus().write_beu32(INIT_ADDR, expected).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b010, 0b010, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b010, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectAReg(2)); } @@ -90,7 +90,7 @@ mod decode_tests { system.get_bus().write_beu32(INIT_ADDR, expected).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b011, 0b010, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b011, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectARegInc(2)); } @@ -105,7 +105,7 @@ mod decode_tests { system.get_bus().write_beu32(INIT_ADDR, expected).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b100, 0b010, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b100, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectARegDec(2)); } @@ -119,7 +119,7 @@ mod decode_tests { system.get_bus().write_beu16(INIT_ADDR, (offset as i16) as u16).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b101, 0b100, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b101, 0b100, Some(size)).unwrap(); assert_eq!(target, Target::IndirectARegOffset(4, offset)); } @@ -135,7 +135,7 @@ mod decode_tests { system.get_bus().write_beu16(INIT_ADDR + 2, (offset as i16) as u16).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b110, 0b010, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b110, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectARegXRegOffset(2, XRegister::Data(3), offset, 0, size)); } @@ -149,7 +149,7 @@ mod decode_tests { system.get_bus().write_beu16(INIT_ADDR, expected as u16).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b000, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b111, 0b000, Some(size)).unwrap(); assert_eq!(target, Target::IndirectMemory(expected)); } @@ -163,7 +163,7 @@ mod decode_tests { system.get_bus().write_beu32(INIT_ADDR, expected).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b001, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b111, 0b001, Some(size)).unwrap(); assert_eq!(target, Target::IndirectMemory(expected)); } @@ -177,7 +177,7 @@ mod decode_tests { system.get_bus().write_beu16(INIT_ADDR, (offset as i16) as u16).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b010, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b111, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectPCOffset(offset)); } @@ -193,7 +193,7 @@ mod decode_tests { system.get_bus().write_beu16(INIT_ADDR + 2, (offset as i16) as u16).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b011, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b111, 0b011, Some(size)).unwrap(); assert_eq!(target, Target::IndirectPCXRegOffset(XRegister::Data(3), offset, 0, size)); } @@ -207,7 +207,7 @@ mod decode_tests { system.get_bus().write_beu16(INIT_ADDR, expected as u16).unwrap(); let memory = get_decode_memory(&mut cpu, &system); - let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b100, Some(size)).unwrap(); + let target = cpu.decoder.get_mode_as_target(memory.borrow_mut().as_addressable().unwrap(), 0b111, 0b100, Some(size)).unwrap(); assert_eq!(target, Target::Immediate(expected)); } @@ -332,10 +332,10 @@ mod decode_tests { mod execute_tests { use crate::system::System; use crate::memory::MemoryBlock; - use crate::devices::{Address, Addressable, Steppable, wrap_addressable}; + use crate::devices::{Address, Addressable, Steppable, wrap_transmutable}; use crate::cpus::m68k::{M68k, M68kType}; - use crate::cpus::m68k::decode::{Instruction, Target, Size, Sign, ShiftDirection}; + use crate::cpus::m68k::instructions::{Instruction, Target, Size, Sign, ShiftDirection}; const INIT_STACK: Address = 0x00002000; const INIT_ADDR: Address = 0x00000010; @@ -346,7 +346,7 @@ mod execute_tests { // Insert basic initialization let data = vec![0; 0x00100000]; let mem = MemoryBlock::new(data); - system.add_addressable_device(0x00000000, wrap_addressable(mem)).unwrap(); + system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap(); system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap(); system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap(); diff --git a/src/devices.rs b/src/devices.rs index b540467..74defd5 100644 --- a/src/devices.rs +++ b/src/devices.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use std::cell::{RefCell, RefMut}; +use std::cell::RefCell; use crate::error::Error; use crate::system::System; diff --git a/src/memory.rs b/src/memory.rs index 323dfd5..dca0e32 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -2,8 +2,7 @@ use std::fs; use crate::error::Error; -use crate::system::System; -use crate::devices::{Clock, Address, Steppable, Addressable, Transmutable, TransmutableBox, MAX_READ}; +use crate::devices::{Address, Addressable, Transmutable, TransmutableBox, MAX_READ}; pub struct MemoryBlock { diff --git a/src/peripherals/ata.rs b/src/peripherals/ata.rs index 603ff49..d5769bd 100644 --- a/src/peripherals/ata.rs +++ b/src/peripherals/ata.rs @@ -2,8 +2,7 @@ use std::fs; use crate::error::Error; -use crate::system::System; -use crate::devices::{Clock, Address, Addressable, Transmutable, MAX_READ}; +use crate::devices::{Address, Addressable, Transmutable, MAX_READ}; const ATA_REG_DATA_WORD: Address = 0x20; diff --git a/src/system.rs b/src/system.rs index c68ed6e..ba790f2 100644 --- a/src/system.rs +++ b/src/system.rs @@ -4,7 +4,7 @@ use std::cell::{RefCell, RefMut}; use crate::error::Error; use crate::memory::Bus; use crate::interrupts::InterruptController; -use crate::devices::{Clock, Address, Transmutable, TransmutableBox}; +use crate::devices::{Clock, Address, TransmutableBox}; pub struct System {