Moved m68k instruction types to their own file

This commit is contained in:
transistor 2021-10-18 12:05:10 -07:00
parent 32d2d591ce
commit 3fc76335d0
9 changed files with 453 additions and 441 deletions

View File

@ -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"),
}
}
}

View File

@ -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};

View File

@ -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"),
}
}
}

View File

@ -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};

View File

@ -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();

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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 {