mirror of
https://github.com/transistorfet/moa.git
synced 2025-02-02 11:31:20 +00:00
Reorganized and started working on the execution code
This commit is contained in:
parent
f22aa23dfa
commit
9095333793
@ -2,72 +2,47 @@
|
||||
use crate::error::Error;
|
||||
use crate::memory::{Address, AddressSpace};
|
||||
|
||||
pub trait Processor {
|
||||
fn reset();
|
||||
fn step();
|
||||
}
|
||||
|
||||
|
||||
use super::execute::MC68010;
|
||||
use super::execute::ERR_ILLEGAL_INSTRUCTION;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum State {
|
||||
Init,
|
||||
Running,
|
||||
Halted,
|
||||
}
|
||||
|
||||
pub struct MC68010 {
|
||||
pub state: State,
|
||||
|
||||
pub pc: u32,
|
||||
pub msp: u32,
|
||||
pub usp: u32,
|
||||
pub flags: u16,
|
||||
pub d_reg: [u32; 8],
|
||||
pub a_reg: [u32; 8],
|
||||
|
||||
pub vbr: u32,
|
||||
}
|
||||
|
||||
const FLAGS_ON_RESET: u16 = 0x2700;
|
||||
|
||||
const FLAGS_SUPERVISOR: u16 = 0x2000;
|
||||
|
||||
const ERR_BUS_ERROR: u32 = 2;
|
||||
const ERR_ADDRESS_ERROR: u32 = 3;
|
||||
const ERR_ILLEGAL_INSTRUCTION: u32 = 4;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum Sign {
|
||||
pub enum Sign {
|
||||
Signed,
|
||||
Unsigned,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum Direction {
|
||||
pub enum Direction {
|
||||
FromTarget,
|
||||
ToTarget,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum ShiftDirection {
|
||||
pub enum ShiftDirection {
|
||||
Right,
|
||||
Left,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum ControlRegister {
|
||||
pub enum RegisterType {
|
||||
Data,
|
||||
Address,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ControlRegister {
|
||||
VBR,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum Size {
|
||||
pub enum Size {
|
||||
Byte,
|
||||
Word,
|
||||
Long,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum Condition {
|
||||
pub enum Condition {
|
||||
True,
|
||||
False,
|
||||
High,
|
||||
@ -87,22 +62,22 @@ enum Condition {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum Target {
|
||||
pub enum Target {
|
||||
Immediate(u32),
|
||||
DirectDReg(u8),
|
||||
DirectAReg(u8),
|
||||
IndirectAReg(u8),
|
||||
IndirectARegInc(u8),
|
||||
IndirectARegDec(u8),
|
||||
IndirectARegOffset(u8, u16),
|
||||
IndirectARegXRegOffset(u8, Box<Target>, u16, Size),
|
||||
IndirectARegOffset(u8, i32),
|
||||
IndirectARegXRegOffset(u8, RegisterType, u8, i32, Size),
|
||||
IndirectMemory(u32),
|
||||
IndirectPCOffset(u16),
|
||||
IndirectPCXRegOffset(Box<Target>, u16, Size),
|
||||
IndirectPCOffset(i32),
|
||||
IndirectPCXRegOffset(RegisterType, u8, i32, Size),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum Instruction {
|
||||
pub enum Instruction {
|
||||
//ABCD
|
||||
ADD(Target, Target, Size),
|
||||
AND(Target, Target, Size),
|
||||
@ -110,9 +85,9 @@ enum Instruction {
|
||||
ANDtoSR(u16),
|
||||
ASd(Target, Target, Size, ShiftDirection),
|
||||
|
||||
Bcc(Condition, u16),
|
||||
BRA(u16),
|
||||
BSR(u16),
|
||||
Bcc(Condition, i16),
|
||||
BRA(i16),
|
||||
BSR(i16),
|
||||
BTST(Target, Target, Size),
|
||||
BCHG(Target, Target, Size),
|
||||
BCLR(Target, Target, Size),
|
||||
@ -203,57 +178,6 @@ const OPCG_RESERVED2: u8 = 0xF;
|
||||
|
||||
|
||||
impl MC68010 {
|
||||
pub fn new() -> MC68010 {
|
||||
MC68010 {
|
||||
state: State::Init,
|
||||
pc: 0,
|
||||
msp: 0,
|
||||
usp: 0,
|
||||
flags: FLAGS_ON_RESET,
|
||||
d_reg: [0; 8],
|
||||
a_reg: [0; 8],
|
||||
vbr: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.state = State::Init;
|
||||
self.pc = 0;
|
||||
self.msp = 0;
|
||||
self.usp = 0;
|
||||
self.flags = FLAGS_ON_RESET;
|
||||
self.d_reg = [0; 8];
|
||||
self.a_reg = [0; 8];
|
||||
self.vbr = 0;
|
||||
}
|
||||
|
||||
pub fn is_running(&self) -> bool {
|
||||
self.state != State::Halted
|
||||
}
|
||||
|
||||
|
||||
pub fn init(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
println!("Initializing CPU");
|
||||
|
||||
self.msp = space.read_beu32(0)?;
|
||||
self.pc = space.read_beu32(4)?;
|
||||
self.state = State::Running;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn step(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
match self.state {
|
||||
State::Init => self.init(space),
|
||||
State::Halted => Err(Error::new("CPU halted")),
|
||||
State::Running => self.execute_one(space),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_supervisor(&self) -> bool {
|
||||
self.flags & FLAGS_SUPERVISOR != 0
|
||||
}
|
||||
|
||||
fn read_instruction_word(&mut self, space: &mut AddressSpace) -> Result<u16, Error> {
|
||||
let word = space.read_beu16(self.pc as Address)?;
|
||||
println!("{:08x} {:04x?}", self.pc, word);
|
||||
@ -268,39 +192,7 @@ impl MC68010 {
|
||||
Ok(word)
|
||||
}
|
||||
|
||||
fn push_long(&mut self, space: &mut AddressSpace, value: u32) -> Result<(), Error> {
|
||||
let reg = if self.is_supervisor() { &mut self.msp } else { &mut self.usp };
|
||||
*reg -= 4;
|
||||
space.write_beu32(*reg as Address, value)
|
||||
}
|
||||
|
||||
fn execute_one(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
let addr = self.pc;
|
||||
let ins = self.decode_one(space)?;
|
||||
|
||||
println!("{:08x}: {:?}", addr, ins);
|
||||
match ins {
|
||||
/*
|
||||
Instruction::JSR(target) => {
|
||||
self.push_long(space, self.pc)?;
|
||||
self.pc = self.get_target_value(space, target)?;
|
||||
},
|
||||
*/
|
||||
_ => { /* panic!(""); */ },
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_target_value(&mut self, space: &mut AddressSpace, target: Target) -> Result<u32, Error> {
|
||||
match target {
|
||||
Target::Immediate(value) => Ok(value),
|
||||
Target::DirectDReg(reg) => Ok(self.d_reg[reg as usize]),
|
||||
_ => Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))),
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_one(&mut self, space: &mut AddressSpace) -> Result<Instruction, Error> {
|
||||
pub fn decode_one(&mut self, space: &mut AddressSpace) -> Result<Instruction, Error> {
|
||||
let ins = self.read_instruction_word(space)?;
|
||||
|
||||
match ((ins & 0xF000) >> 12) as u8 {
|
||||
@ -355,7 +247,7 @@ impl MC68010 {
|
||||
let target = self.decode_lower_effective_address(space, ins, size)?;
|
||||
let data = match size {
|
||||
Some(Size::Long) => self.read_instruction_long(space)?,
|
||||
Some(size) => self.read_instruction_word(space)? as u32,
|
||||
Some(_) => self.read_instruction_word(space)? as u32,
|
||||
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||
};
|
||||
|
||||
@ -444,14 +336,14 @@ impl MC68010 {
|
||||
(0b011, 0b000) => {
|
||||
Ok(Instruction::EXT(get_low_reg(ins), Size::Long))
|
||||
},
|
||||
(0b000, mode) => {
|
||||
(0b000, _) => {
|
||||
let target = self.decode_lower_effective_address(space, ins, Some(Size::Byte))?;
|
||||
Ok(Instruction::NBCD(target))
|
||||
},
|
||||
(0b001, 0b000) => {
|
||||
Ok(Instruction::SWAP(get_low_reg(ins)))
|
||||
},
|
||||
(0b001, mode) => {
|
||||
(0b001, _) => {
|
||||
let target = self.decode_lower_effective_address(space, ins, None)?;
|
||||
Ok(Instruction::PEA(target))
|
||||
},
|
||||
@ -464,6 +356,8 @@ impl MC68010 {
|
||||
} else {
|
||||
Ok(Instruction::JMP(target))
|
||||
}
|
||||
} else if (ins & 0b111111110000) == 0b111001000000 {
|
||||
Ok(Instruction::TRAP((ins & 0x000F) as u8))
|
||||
} else if (ins & 0b111111110000) == 0b111001010000 {
|
||||
let reg = get_low_reg(ins);
|
||||
if (ins & 0b1000) == 0 {
|
||||
@ -525,15 +419,15 @@ impl MC68010 {
|
||||
}
|
||||
},
|
||||
OPCG_BRANCH => {
|
||||
let mut disp = (ins & 0xFF);
|
||||
let mut disp = ins & 0xFF;
|
||||
if disp == 0 {
|
||||
disp = self.read_instruction_word(space)?;
|
||||
}
|
||||
let condition = get_condition(ins);
|
||||
match condition {
|
||||
Condition::True => Ok(Instruction::BRA(disp)),
|
||||
Condition::False => Ok(Instruction::BSR(disp)),
|
||||
_ => Ok(Instruction::Bcc(condition, disp)),
|
||||
Condition::True => Ok(Instruction::BRA(disp as i16)),
|
||||
Condition::False => Ok(Instruction::BSR(disp as i16)),
|
||||
_ => Ok(Instruction::Bcc(condition, disp as i16)),
|
||||
}
|
||||
},
|
||||
OPCG_MOVEQ => {
|
||||
@ -595,7 +489,7 @@ impl MC68010 {
|
||||
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
|
||||
Ok(Instruction::CMP(Target::DirectDReg(reg), target, size))
|
||||
},
|
||||
(size, None) => {
|
||||
(_, None) => {
|
||||
let size = if optype == 0 { Size::Word } else { Size::Long };
|
||||
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
|
||||
Ok(Instruction::CMP(target, Target::DirectAReg(reg), size))
|
||||
@ -692,18 +586,14 @@ impl MC68010 {
|
||||
self.get_mode_as_target(space, mode, reg, size)
|
||||
}
|
||||
|
||||
fn decode_brief_extension_word(&self, brief_extension: u16) -> (Target, u16, Size) {
|
||||
fn decode_brief_extension_word(&self, brief_extension: u16) -> (RegisterType, u8, u16, Size) {
|
||||
let data = brief_extension & 0x00FF;
|
||||
let reg = ((brief_extension & 0x7000) >> 12) as u8;
|
||||
let xreg = ((brief_extension & 0x7000) >> 12) as u8;
|
||||
let size = if (brief_extension & 0x0800) == 0 { Size::Word } else { Size::Long };
|
||||
|
||||
let target = if (brief_extension & 0x8000) == 0 {
|
||||
Target::DirectDReg(reg)
|
||||
} else {
|
||||
Target::DirectAReg(reg)
|
||||
};
|
||||
let rtype = if (brief_extension & 0x8000) == 0 { RegisterType::Data } else { RegisterType::Address };
|
||||
|
||||
(target, data, size)
|
||||
(rtype, xreg, data, size)
|
||||
}
|
||||
|
||||
fn get_mode_as_target(&mut self, space: &mut AddressSpace, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
|
||||
@ -714,13 +604,13 @@ impl MC68010 {
|
||||
0b011 => Target::IndirectARegInc(reg),
|
||||
0b100 => Target::IndirectARegDec(reg),
|
||||
0b101 => {
|
||||
let d16 = self.read_instruction_word(space)?;
|
||||
Target::IndirectARegOffset(reg, d16)
|
||||
let data = self.read_instruction_word(space)?;
|
||||
Target::IndirectARegOffset(reg, (data as i16) as i32)
|
||||
},
|
||||
0b110 => {
|
||||
let brief_extension = self.read_instruction_word(space)?;
|
||||
let (target, data, size) = self.decode_brief_extension_word(brief_extension);
|
||||
Target::IndirectARegXRegOffset(reg, Box::new(target), data, size)
|
||||
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
|
||||
Target::IndirectARegXRegOffset(reg, rtype, xreg, (data as i16) as i32, size)
|
||||
},
|
||||
0b111 => {
|
||||
match reg {
|
||||
@ -733,13 +623,13 @@ impl MC68010 {
|
||||
Target::IndirectMemory(value)
|
||||
},
|
||||
0b010 => {
|
||||
let d16 = self.read_instruction_word(space)?;
|
||||
Target::IndirectPCOffset(d16)
|
||||
let data = self.read_instruction_word(space)?;
|
||||
Target::IndirectPCOffset((data as i16) as i32)
|
||||
},
|
||||
0b011 => {
|
||||
let brief_extension = self.read_instruction_word(space)?;
|
||||
let (target, data, size) = self.decode_brief_extension_word(brief_extension);
|
||||
Target::IndirectPCXRegOffset(Box::new(target), data, size)
|
||||
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
|
||||
Target::IndirectPCXRegOffset(rtype, xreg, (data as i16) as i32, size)
|
||||
},
|
||||
0b100 => {
|
||||
let data = match size {
|
||||
@ -813,8 +703,14 @@ fn get_condition(ins: u16) -> Condition {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl Processor for MC68010 {
|
||||
|
||||
impl Size {
|
||||
pub fn in_bytes(&self) -> u32 {
|
||||
match self {
|
||||
Size::Byte => 1,
|
||||
Size::Word => 2,
|
||||
Size::Long => 4,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
407
src/cpus/m68k/execute.rs
Normal file
407
src/cpus/m68k/execute.rs
Normal file
@ -0,0 +1,407 @@
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::memory::{Address, AddressSpace};
|
||||
|
||||
use super::decode::{Instruction, Target, Size, Direction, ControlRegister, RegisterType};
|
||||
|
||||
pub trait Processor {
|
||||
fn reset();
|
||||
fn step();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum State {
|
||||
Init,
|
||||
Running,
|
||||
Halted,
|
||||
}
|
||||
|
||||
pub struct MC68010 {
|
||||
pub state: State,
|
||||
|
||||
pub pc: u32,
|
||||
pub sr: u16,
|
||||
pub d_reg: [u32; 8],
|
||||
pub a_reg: [u32; 7],
|
||||
pub msp: u32,
|
||||
pub usp: u32,
|
||||
|
||||
pub vbr: u32,
|
||||
}
|
||||
|
||||
const FLAGS_ON_RESET: u16 = 0x2700;
|
||||
|
||||
pub const FLAGS_SUPERVISOR: u16 = 0x2000;
|
||||
|
||||
pub const ERR_BUS_ERROR: u32 = 2;
|
||||
pub const ERR_ADDRESS_ERROR: u32 = 3;
|
||||
pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4;
|
||||
|
||||
impl MC68010 {
|
||||
pub fn new() -> MC68010 {
|
||||
MC68010 {
|
||||
state: State::Init,
|
||||
|
||||
pc: 0,
|
||||
sr: FLAGS_ON_RESET,
|
||||
d_reg: [0; 8],
|
||||
a_reg: [0; 7],
|
||||
msp: 0,
|
||||
usp: 0,
|
||||
|
||||
vbr: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.state = State::Init;
|
||||
self.pc = 0;
|
||||
self.sr = FLAGS_ON_RESET;
|
||||
self.d_reg = [0; 8];
|
||||
self.a_reg = [0; 7];
|
||||
self.msp = 0;
|
||||
self.usp = 0;
|
||||
|
||||
self.vbr = 0;
|
||||
}
|
||||
|
||||
pub fn is_running(&self) -> bool {
|
||||
self.state != State::Halted
|
||||
}
|
||||
|
||||
|
||||
pub fn init(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
println!("Initializing CPU");
|
||||
|
||||
self.msp = space.read_beu32(0)?;
|
||||
self.pc = space.read_beu32(4)?;
|
||||
self.state = State::Running;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn step(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
match self.state {
|
||||
State::Init => self.init(space),
|
||||
State::Halted => Err(Error::new("CPU halted")),
|
||||
State::Running => self.execute_one(space),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_supervisor(&self) -> bool {
|
||||
self.sr & FLAGS_SUPERVISOR != 0
|
||||
}
|
||||
|
||||
fn push_long(&mut self, space: &mut AddressSpace, value: u32) -> Result<(), Error> {
|
||||
let reg = if self.is_supervisor() { &mut self.msp } else { &mut self.usp };
|
||||
*reg -= 4;
|
||||
space.write_beu32(*reg as Address, value)
|
||||
}
|
||||
|
||||
fn execute_one(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
let addr = self.pc;
|
||||
let ins = self.decode_one(space)?;
|
||||
|
||||
println!("{:08x}: {:?}", addr, ins);
|
||||
match ins {
|
||||
//Instruction::ADD(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::AND(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::ANDtoCCR(u8) => {
|
||||
//},
|
||||
//Instruction::ANDtoSR(u16) => {
|
||||
//},
|
||||
//Instruction::ASd(Target, Target, Size, ShiftDirection) => {
|
||||
//},
|
||||
//Instruction::Bcc(Condition, u16) => {
|
||||
//},
|
||||
Instruction::BRA(offset) => {
|
||||
self.pc = self.pc.wrapping_add(offset as u32) - 2;
|
||||
},
|
||||
Instruction::BSR(offset) => {
|
||||
self.push_long(space, self.pc)?;
|
||||
self.pc = self.pc.wrapping_add(offset as u32) - 2;
|
||||
},
|
||||
//Instruction::BTST(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::BCHG(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::BCLR(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::BSET(Target, Target, Size) => {
|
||||
//},
|
||||
Instruction::CLR(target, size) => {
|
||||
self.set_target_value(space, target, 0, size)?;
|
||||
},
|
||||
//Instruction::CMP(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::DBcc(Condition, u16) => {
|
||||
//},
|
||||
//Instruction::DIV(Target, Target, Size, Sign) => {
|
||||
//},
|
||||
//Instruction::EOR(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::EORtoCCR(u8) => {
|
||||
//},
|
||||
//Instruction::EORtoSR(u16) => {
|
||||
//},
|
||||
//Instruction::EXG(Target, Target) => {
|
||||
//},
|
||||
//Instruction::EXT(u8, Size) => {
|
||||
//},
|
||||
//Instruction::ILLEGAL => {
|
||||
//},
|
||||
Instruction::JMP(target) => {
|
||||
self.pc = self.get_target_address(target)?;
|
||||
},
|
||||
Instruction::JSR(target) => {
|
||||
self.push_long(space, self.pc)?;
|
||||
self.pc = self.get_target_address(target)?;
|
||||
},
|
||||
Instruction::LEA(target, reg) => {
|
||||
let value = self.get_target_address(target)?;
|
||||
let addr = self.get_a_reg(reg);
|
||||
*addr = value;
|
||||
},
|
||||
//Instruction::LINK(u8, u16) => {
|
||||
//},
|
||||
//Instruction::LSd(Target, Target, Size, ShiftDirection) => {
|
||||
//},
|
||||
Instruction::MOVE(src, dest, size) => {
|
||||
let value = self.get_target_value(space, src, size)?;
|
||||
self.set_target_value(space, dest, value, size)?;
|
||||
},
|
||||
Instruction::MOVEfromSR(target) => {
|
||||
self.set_target_value(space, target, self.sr as u32, Size::Word)?;
|
||||
},
|
||||
Instruction::MOVEtoSR(target) => {
|
||||
self.sr = self.get_target_value(space, target, Size::Word)? as u16;
|
||||
},
|
||||
//Instruction::MOVEtoCCR(Target) => {
|
||||
//},
|
||||
Instruction::MOVEC(target, control_reg, dir) => {
|
||||
match dir {
|
||||
Direction::FromTarget => {
|
||||
let value = self.get_target_value(space, target, Size::Long)?;
|
||||
let addr = self.get_control_reg_mut(control_reg);
|
||||
*addr = value;
|
||||
},
|
||||
Direction::ToTarget => {
|
||||
let addr = self.get_control_reg_mut(control_reg);
|
||||
let value = *addr;
|
||||
self.set_target_value(space, target, value, Size::Long)?;
|
||||
},
|
||||
}
|
||||
},
|
||||
//Instruction::MOVEUSP(Target, Direction) => {
|
||||
//},
|
||||
//Instruction::MOVEM(Target, Size, Direction, u16) => {
|
||||
//},
|
||||
//Instruction::MOVEQ(u8, u8) => {
|
||||
//},
|
||||
//Instruction::MUL(Target, Target, Size, Sign) => {
|
||||
//},
|
||||
//Instruction::NBCD(Target) => {
|
||||
//},
|
||||
//Instruction::NEG(Target, Size) => {
|
||||
//},
|
||||
//Instruction::NEGX(Target, Size) => {
|
||||
//},
|
||||
Instruction::NOP => { },
|
||||
//Instruction::NOT(Target, Size) => {
|
||||
//},
|
||||
//Instruction::OR(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::ORtoCCR(u8) => {
|
||||
//},
|
||||
Instruction::ORtoSR(value) => {
|
||||
self.sr = self.sr | value;
|
||||
},
|
||||
//Instruction::PEA(Target) => {
|
||||
//},
|
||||
//Instruction::RESET => {
|
||||
//},
|
||||
//Instruction::ROd(Target, Target, Size, ShiftDirection) => {
|
||||
//},
|
||||
//Instruction::ROXd(Target, Target, Size, ShiftDirection) => {
|
||||
//},
|
||||
//Instruction::RTE => {
|
||||
//},
|
||||
//Instruction::RTR => {
|
||||
//},
|
||||
//Instruction::RTS => {
|
||||
//},
|
||||
//Instruction::STOP(u16) => {
|
||||
//},
|
||||
//Instruction::SUB(Target, Target, Size) => {
|
||||
//},
|
||||
//Instruction::SWAP(u8) => {
|
||||
//},
|
||||
//Instruction::TAS(Target) => {
|
||||
//},
|
||||
//Instruction::TST(Target, Size) => {
|
||||
//},
|
||||
//Instruction::TRAP(u8) => {
|
||||
//},
|
||||
//Instruction::TRAPV => {
|
||||
//},
|
||||
//Instruction::UNLK(u8) => {
|
||||
//},
|
||||
_ => { panic!(""); },
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_target_value(&mut self, space: &mut AddressSpace, target: Target, size: Size) -> Result<u32, Error> {
|
||||
match target {
|
||||
Target::Immediate(value) => Ok(value),
|
||||
Target::DirectDReg(reg) => Ok(get_value_sized(self.d_reg[reg as usize], size)),
|
||||
Target::DirectAReg(reg) => Ok(get_value_sized(*self.get_a_reg(reg), size)),
|
||||
Target::IndirectAReg(reg) => get_address_sized(space, *self.get_a_reg(reg) as Address, size),
|
||||
Target::IndirectARegInc(reg) => {
|
||||
let addr = self.get_a_reg(reg);
|
||||
let value = get_address_sized(space, *addr as Address, size);
|
||||
*addr += size.in_bytes();
|
||||
value
|
||||
},
|
||||
Target::IndirectARegDec(reg) => {
|
||||
let addr = self.get_a_reg(reg);
|
||||
*addr -= size.in_bytes();
|
||||
get_address_sized(space, *addr as Address, size)
|
||||
},
|
||||
Target::IndirectARegOffset(reg, offset) => {
|
||||
let addr = self.get_a_reg(reg);
|
||||
get_address_sized(space, (*addr).wrapping_add(offset as u32) as Address, size)
|
||||
},
|
||||
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => {
|
||||
let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size);
|
||||
let addr = self.get_a_reg(reg);
|
||||
get_address_sized(space, (*addr).wrapping_add(reg_offset).wrapping_add(offset as u32) as Address, size)
|
||||
},
|
||||
Target::IndirectMemory(addr) => {
|
||||
get_address_sized(space, addr as Address, size)
|
||||
},
|
||||
Target::IndirectPCOffset(offset) => {
|
||||
get_address_sized(space, self.pc.wrapping_add(offset as u32) as Address, size)
|
||||
},
|
||||
Target::IndirectPCXRegOffset(rtype, xreg, offset, target_size) => {
|
||||
let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size);
|
||||
get_address_sized(space, self.pc.wrapping_add(reg_offset).wrapping_add(offset as u32) as Address, size)
|
||||
},
|
||||
_ => Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_target_value(&mut self, space: &mut AddressSpace, target: Target, value: u32, size: Size) -> Result<(), Error> {
|
||||
match target {
|
||||
Target::DirectDReg(reg) => {
|
||||
set_value_sized(&mut self.d_reg[reg as usize], value, size);
|
||||
},
|
||||
Target::DirectAReg(reg) => {
|
||||
set_value_sized(self.get_a_reg(reg), value, size);
|
||||
},
|
||||
Target::IndirectAReg(reg) => {
|
||||
set_address_sized(space, *self.get_a_reg(reg) as Address, value, size)?;
|
||||
},
|
||||
_ => return Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_target_address(&mut self, target: Target) -> Result<u32, Error> {
|
||||
let addr = match target {
|
||||
Target::IndirectAReg(reg) => *self.get_a_reg(reg),
|
||||
Target::IndirectARegOffset(reg, offset) => {
|
||||
let addr = self.get_a_reg(reg);
|
||||
(*addr).wrapping_add(offset as u32)
|
||||
},
|
||||
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => {
|
||||
let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size);
|
||||
let addr = self.get_a_reg(reg);
|
||||
(*addr).wrapping_add(reg_offset).wrapping_add(offset as u32)
|
||||
},
|
||||
Target::IndirectMemory(addr) => {
|
||||
addr
|
||||
},
|
||||
Target::IndirectPCOffset(offset) => {
|
||||
self.pc.wrapping_add(offset as u32)
|
||||
},
|
||||
Target::IndirectPCXRegOffset(rtype, xreg, offset, target_size) => {
|
||||
let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size);
|
||||
self.pc.wrapping_add(reg_offset).wrapping_add(offset as u32)
|
||||
},
|
||||
_ => return Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))),
|
||||
};
|
||||
Ok(addr)
|
||||
}
|
||||
|
||||
fn get_control_reg_mut(&mut self, control_reg: ControlRegister) -> &mut u32 {
|
||||
match control_reg {
|
||||
ControlRegister::VBR => &mut self.vbr,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_stack_pointer(&mut self) -> &mut u32 {
|
||||
if self.is_supervisor() { &mut self.msp } else { &mut self.usp }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_a_reg(&mut self, reg: u8) -> &mut u32 {
|
||||
if reg == 7 {
|
||||
if self.is_supervisor() { &mut self.msp } else { &mut self.usp }
|
||||
} else {
|
||||
&mut self.a_reg[reg as usize]
|
||||
}
|
||||
}
|
||||
|
||||
fn get_x_reg_value(&self, rtype: RegisterType, reg: u8) -> u32 {
|
||||
match rtype {
|
||||
RegisterType::Data => self.d_reg[reg as usize],
|
||||
RegisterType::Address => self.d_reg[reg as usize],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_value_sized(value: u32, size: Size) -> u32 {
|
||||
match size {
|
||||
Size::Byte => { 0x000000FF & value },
|
||||
Size::Word => { 0x0000FFFF & value },
|
||||
Size::Long => { value },
|
||||
}
|
||||
}
|
||||
|
||||
fn get_address_sized(space: &mut AddressSpace, addr: Address, size: Size) -> Result<u32, Error> {
|
||||
match size {
|
||||
Size::Byte => space.read_u8(addr).map(|value| value as u32),
|
||||
Size::Word => space.read_beu16(addr).map(|value| value as u32),
|
||||
Size::Long => space.read_beu32(addr),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_value_sized(addr: &mut u32, value: u32, size: Size) {
|
||||
match size {
|
||||
Size::Byte => { *addr = (*addr & 0xFFFFFF00) | (0x000000FF & value); }
|
||||
Size::Word => { *addr = (*addr & 0xFFFF0000) | (0x0000FFFF & value); }
|
||||
Size::Long => { *addr = value; }
|
||||
}
|
||||
}
|
||||
|
||||
fn set_address_sized(space: &mut AddressSpace, addr: Address, value: u32, size: Size) -> Result<(), Error> {
|
||||
match size {
|
||||
Size::Byte => space.write_u8(addr, value as u8),
|
||||
Size::Word => space.write_beu16(addr, value as u16),
|
||||
Size::Long => space.write_beu32(addr, value),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
impl Processor for MC68010 {
|
||||
|
||||
}
|
||||
*/
|
6
src/cpus/m68k/mod.rs
Normal file
6
src/cpus/m68k/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
mod decode;
|
||||
mod execute;
|
||||
|
||||
pub use self::execute::MC68010;
|
||||
|
3
src/cpus/mod.rs
Normal file
3
src/cpus/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
pub mod m68k;
|
||||
|
@ -2,10 +2,10 @@
|
||||
#[macro_use]
|
||||
mod error;
|
||||
mod memory;
|
||||
mod m68k;
|
||||
mod cpus;
|
||||
|
||||
use crate::memory::{AddressSpace, Segment};
|
||||
use crate::m68k::MC68010;
|
||||
use crate::cpus::m68k::MC68010;
|
||||
|
||||
fn main() {
|
||||
let mut space = AddressSpace::new();
|
||||
@ -15,6 +15,8 @@ fn main() {
|
||||
}
|
||||
space.insert(monitor);
|
||||
|
||||
let ram = Segment::new(0x00100000, vec![0; 0x00100000]);
|
||||
space.insert(ram);
|
||||
|
||||
let mut cpu = MC68010::new();
|
||||
while cpu.is_running() {
|
||||
|
@ -88,6 +88,11 @@ impl AddressSpace {
|
||||
}
|
||||
|
||||
|
||||
pub fn read_u8(&self, addr: Address) -> Result<u8, Error> {
|
||||
let seg = self.get_segment(addr)?;
|
||||
Ok(*seg.read(addr).next().unwrap())
|
||||
}
|
||||
|
||||
pub fn read_beu16(&self, addr: Address) -> Result<u16, Error> {
|
||||
let seg = self.get_segment(addr)?;
|
||||
Ok(read_beu16(seg.read(addr)))
|
||||
@ -98,6 +103,12 @@ impl AddressSpace {
|
||||
Ok(read_beu32(seg.read(addr)))
|
||||
}
|
||||
|
||||
pub fn write_u8(&mut self, addr: Address, value: u8) -> Result<(), Error> {
|
||||
let seg = self.get_segment_mut(addr)?;
|
||||
let data = [value];
|
||||
Ok(seg.write(addr, &data))
|
||||
}
|
||||
|
||||
pub fn write_beu16(&mut self, addr: Address, value: u16) -> Result<(), Error> {
|
||||
let seg = self.get_segment_mut(addr)?;
|
||||
let data = [
|
||||
|
Loading…
x
Reference in New Issue
Block a user