mirror of
https://github.com/transistorfet/moa.git
synced 2024-05-29 04:41:29 +00:00
Reorganized decode and add some support for other m68k processors
This commit is contained in:
parent
b588563acc
commit
94141e112e
|
@ -3,7 +3,7 @@ use crate::error::Error;
|
||||||
use crate::system::System;
|
use crate::system::System;
|
||||||
use crate::memory::{Address, Addressable};
|
use crate::memory::{Address, Addressable};
|
||||||
|
|
||||||
use super::state::MC68010;
|
use super::state::M68k;
|
||||||
|
|
||||||
pub struct StackTracer {
|
pub struct StackTracer {
|
||||||
pub calls: Vec<u32>,
|
pub calls: Vec<u32>,
|
||||||
|
@ -46,7 +46,7 @@ impl M68kDebugger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MC68010 {
|
impl M68k {
|
||||||
pub fn enable_tracing(&mut self) {
|
pub fn enable_tracing(&mut self) {
|
||||||
self.debugger.use_tracing = true;
|
self.debugger.use_tracing = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::system::System;
|
||||||
use crate::memory::Address;
|
use crate::memory::Address;
|
||||||
use crate::devices::AddressableDeviceRefMut;
|
use crate::devices::AddressableDeviceRefMut;
|
||||||
|
|
||||||
use super::state::ERR_ILLEGAL_INSTRUCTION;
|
use super::state::{M68kType, ERR_ILLEGAL_INSTRUCTION};
|
||||||
|
|
||||||
|
|
||||||
const OPCG_BIT_OPS: u8 = 0x0;
|
const OPCG_BIT_OPS: u8 = 0x0;
|
||||||
|
@ -107,14 +107,16 @@ pub enum Instruction {
|
||||||
ANDtoSR(u16),
|
ANDtoSR(u16),
|
||||||
ASd(Target, Target, Size, ShiftDirection),
|
ASd(Target, Target, Size, ShiftDirection),
|
||||||
|
|
||||||
Bcc(Condition, i16),
|
Bcc(Condition, i32),
|
||||||
BRA(i16),
|
BRA(i32),
|
||||||
BSR(i16),
|
BSR(i32),
|
||||||
BTST(Target, Target, Size),
|
|
||||||
BCHG(Target, Target, Size),
|
BCHG(Target, Target, Size),
|
||||||
BCLR(Target, Target, Size),
|
BCLR(Target, Target, Size),
|
||||||
BSET(Target, Target, Size),
|
BSET(Target, Target, Size),
|
||||||
|
BTST(Target, Target, Size),
|
||||||
|
BKPT(u8),
|
||||||
|
|
||||||
|
CHK(Target, u8, Size),
|
||||||
CLR(Target, Size),
|
CLR(Target, Size),
|
||||||
CMP(Target, Target, Size),
|
CMP(Target, Target, Size),
|
||||||
CMPA(Target, u8, Size),
|
CMPA(Target, u8, Size),
|
||||||
|
@ -141,11 +143,13 @@ pub enum Instruction {
|
||||||
MOVEA(Target, u8, Size),
|
MOVEA(Target, u8, Size),
|
||||||
MOVEfromSR(Target),
|
MOVEfromSR(Target),
|
||||||
MOVEtoSR(Target),
|
MOVEtoSR(Target),
|
||||||
|
MOVEfromCCR(Target),
|
||||||
MOVEtoCCR(Target),
|
MOVEtoCCR(Target),
|
||||||
MOVEC(Target, ControlRegister, Direction),
|
MOVEC(Target, ControlRegister, Direction),
|
||||||
MOVEUSP(Target, Direction),
|
|
||||||
MOVEM(Target, Size, Direction, u16),
|
MOVEM(Target, Size, Direction, u16),
|
||||||
|
MOVEP(u8, Target, Size, Direction),
|
||||||
MOVEQ(u8, u8),
|
MOVEQ(u8, u8),
|
||||||
|
MOVEUSP(Target, Direction),
|
||||||
MUL(Target, Target, Size, Sign),
|
MUL(Target, Target, Size, Sign),
|
||||||
|
|
||||||
NBCD(Target),
|
NBCD(Target),
|
||||||
|
@ -167,6 +171,7 @@ pub enum Instruction {
|
||||||
RTE,
|
RTE,
|
||||||
RTR,
|
RTR,
|
||||||
RTS,
|
RTS,
|
||||||
|
RTD(i16),
|
||||||
|
|
||||||
//SBCD
|
//SBCD
|
||||||
Scc(Condition, Target),
|
Scc(Condition, Target),
|
||||||
|
@ -184,6 +189,7 @@ pub enum Instruction {
|
||||||
|
|
||||||
|
|
||||||
pub struct M68kDecoder {
|
pub struct M68kDecoder {
|
||||||
|
pub cputype: M68kType,
|
||||||
pub base: u32,
|
pub base: u32,
|
||||||
pub start: u32,
|
pub start: u32,
|
||||||
pub end: u32,
|
pub end: u32,
|
||||||
|
@ -191,8 +197,9 @@ pub struct M68kDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl M68kDecoder {
|
impl M68kDecoder {
|
||||||
pub fn new(base: u32, start: u32) -> M68kDecoder {
|
pub fn new(cputype: M68kType, base: u32, start: u32) -> M68kDecoder {
|
||||||
M68kDecoder {
|
M68kDecoder {
|
||||||
|
cputype,
|
||||||
base: base,
|
base: base,
|
||||||
start: start,
|
start: start,
|
||||||
end: start,
|
end: start,
|
||||||
|
@ -200,11 +207,18 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_at(system: &System, start: u32) -> Result<M68kDecoder, Error> {
|
#[inline(always)]
|
||||||
|
pub fn init(&mut self, base: u32, start: u32) {
|
||||||
|
self.base = base;
|
||||||
|
self.start = start;
|
||||||
|
self.end = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_at(&mut self, system: &System, start: u32) -> Result<(), Error> {
|
||||||
let (memory, relative_addr) = system.get_bus().get_device_at(start as Address, 12)?;
|
let (memory, relative_addr) = system.get_bus().get_device_at(start as Address, 12)?;
|
||||||
let mut decoder = M68kDecoder::new(start - relative_addr as u32, start);
|
self.init(start - relative_addr as u32, start);
|
||||||
decoder.instruction = decoder.decode_one(&mut memory.borrow_mut())?;
|
self.instruction = self.decode_one(&mut memory.borrow_mut())?;
|
||||||
Ok(decoder)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_one(&mut self, system: &mut AddressableDeviceRefMut<'_>) -> Result<Instruction, Error> {
|
pub fn decode_one(&mut self, system: &mut AddressableDeviceRefMut<'_>) -> Result<Instruction, Error> {
|
||||||
|
@ -236,6 +250,13 @@ impl M68kDecoder {
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
}
|
}
|
||||||
|
} else if (ins & 0x138) == 0x108 {
|
||||||
|
let dreg = get_high_reg(ins);
|
||||||
|
let areg = get_low_reg(ins);
|
||||||
|
let dir = if (ins & 0x0800) == 0 { Direction::FromTarget } else { Direction::ToTarget };
|
||||||
|
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
|
||||||
|
let offset = sign_extend_to_long(self.read_instruction_word(system)? as u32, Size::Word);
|
||||||
|
Ok(Instruction::MOVEP(dreg, Target::IndirectARegOffset(areg, offset), size, dir))
|
||||||
} else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 {
|
} else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 {
|
||||||
let bitnum = if (ins & 0x0100) == 0x0100 {
|
let bitnum = if (ins & 0x0100) == 0x0100 {
|
||||||
Target::DirectDReg(get_high_reg(ins))
|
Target::DirectDReg(get_high_reg(ins))
|
||||||
|
@ -256,7 +277,6 @@ impl M68kDecoder {
|
||||||
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
|
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
let data = match size {
|
let data = match size {
|
||||||
|
@ -302,14 +322,34 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_MISC => {
|
OPCG_MISC => {
|
||||||
if (ins & 0b000101000000) == 0b000100000000 {
|
let ins_0f00 = ins & 0xF00;
|
||||||
// CHK Instruction
|
let ins_00f0 = ins & 0x0F0;
|
||||||
panic!("Not Implemented");
|
|
||||||
} else if (ins & 0b000111000000) == 0b000111000000 {
|
if (ins & 0x180) == 0x180 {
|
||||||
let src = self.decode_lower_effective_address(system, ins, None)?;
|
if (ins & 0x040) == 0 {
|
||||||
let dest = get_high_reg(ins);
|
let size = match get_size(ins) {
|
||||||
Ok(Instruction::LEA(src, dest))
|
Some(Size::Word) => Size::Word,
|
||||||
} else if (ins & 0b100000000000) == 0b000000000000 {
|
Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long,
|
||||||
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let reg = get_high_reg(ins);
|
||||||
|
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
||||||
|
Ok(Instruction::CHK(target, reg, size))
|
||||||
|
} else {
|
||||||
|
let src = self.decode_lower_effective_address(system, ins, None)?;
|
||||||
|
let dest = get_high_reg(ins);
|
||||||
|
Ok(Instruction::LEA(src, dest))
|
||||||
|
}
|
||||||
|
} else if (ins & 0xB80) == 0x880 && (ins & 0x038) != 0 {
|
||||||
|
let mode = get_low_mode(ins);
|
||||||
|
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
|
||||||
|
|
||||||
|
let data = self.read_instruction_word(system)?;
|
||||||
|
let target = self.decode_lower_effective_address(system, ins, None)?;
|
||||||
|
let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget };
|
||||||
|
Ok(Instruction::MOVEM(target, size, dir, data))
|
||||||
|
} else if (ins & 0x800) == 0 {
|
||||||
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
|
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
|
||||||
match (ins & 0x0700) >> 8 {
|
match (ins & 0x0700) >> 8 {
|
||||||
0b000 => {
|
0b000 => {
|
||||||
|
@ -321,6 +361,7 @@ impl M68kDecoder {
|
||||||
0b010 => {
|
0b010 => {
|
||||||
match get_size(ins) {
|
match get_size(ins) {
|
||||||
Some(size) => Ok(Instruction::CLR(target, size)),
|
Some(size) => Ok(Instruction::CLR(target, size)),
|
||||||
|
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
|
||||||
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -338,19 +379,7 @@ impl M68kDecoder {
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
}
|
}
|
||||||
} else if (ins & 0b101110000000) == 0b100010000000 {
|
} else if ins_0f00 == 0x800 {
|
||||||
let mode = get_low_mode(ins);
|
|
||||||
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
|
|
||||||
|
|
||||||
if mode == 0b000 {
|
|
||||||
Ok(Instruction::EXT(get_low_reg(ins), size))
|
|
||||||
} else {
|
|
||||||
let data = self.read_instruction_word(system)?;
|
|
||||||
let target = self.decode_lower_effective_address(system, ins, None)?;
|
|
||||||
let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget };
|
|
||||||
Ok(Instruction::MOVEM(target, size, dir, data))
|
|
||||||
}
|
|
||||||
} else if (ins & 0b111100000000) == 0b100000000000 {
|
|
||||||
let subselect = (ins & 0x01C0) >> 6;
|
let subselect = (ins & 0x01C0) >> 6;
|
||||||
let mode = get_low_mode(ins);
|
let mode = get_low_mode(ins);
|
||||||
match (subselect, mode) {
|
match (subselect, mode) {
|
||||||
|
@ -361,67 +390,86 @@ impl M68kDecoder {
|
||||||
(0b001, 0b000) => {
|
(0b001, 0b000) => {
|
||||||
Ok(Instruction::SWAP(get_low_reg(ins)))
|
Ok(Instruction::SWAP(get_low_reg(ins)))
|
||||||
},
|
},
|
||||||
|
(0b001, 0b001) => {
|
||||||
|
Ok(Instruction::BKPT(get_low_reg(ins)))
|
||||||
|
},
|
||||||
(0b001, _) => {
|
(0b001, _) => {
|
||||||
let target = self.decode_lower_effective_address(system, ins, None)?;
|
let target = self.decode_lower_effective_address(system, ins, None)?;
|
||||||
Ok(Instruction::PEA(target))
|
Ok(Instruction::PEA(target))
|
||||||
},
|
},
|
||||||
|
(0b010, 0b000) |
|
||||||
|
(0b011, 0b000) => {
|
||||||
|
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
|
||||||
|
Ok(Instruction::EXT(get_low_reg(ins), size))
|
||||||
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
}
|
}
|
||||||
} else if (ins & 0b111100000000) == 0b101000000000 {
|
} else if ins_0f00 == 0xA00 {
|
||||||
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
|
if (ins & 0x0FF) == 0xFC {
|
||||||
match get_size(ins) {
|
Ok(Instruction::ILLEGAL)
|
||||||
Some(size) => Ok(Instruction::TST(target, size)),
|
|
||||||
None => Ok(Instruction::TAS(target)),
|
|
||||||
}
|
|
||||||
} else if (ins & 0b111110000000) == 0b111010000000 {
|
|
||||||
let target = self.decode_lower_effective_address(system, ins, None)?;
|
|
||||||
if (ins & 0b01000000) == 0 {
|
|
||||||
Ok(Instruction::JSR(target))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(Instruction::JMP(target))
|
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
|
||||||
|
match get_size(ins) {
|
||||||
|
Some(size) => Ok(Instruction::TST(target, size)),
|
||||||
|
None => Ok(Instruction::TAS(target)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (ins & 0b111111110000) == 0b111001000000 {
|
} else if ins_0f00 == 0xE00 {
|
||||||
Ok(Instruction::TRAP((ins & 0x000F) as u8))
|
if (ins & 0x80) == 0x80 {
|
||||||
} else if (ins & 0b111111110000) == 0b111001010000 {
|
let target = self.decode_lower_effective_address(system, ins, None)?;
|
||||||
let reg = get_low_reg(ins);
|
if (ins & 0b01000000) == 0 {
|
||||||
if (ins & 0b1000) == 0 {
|
Ok(Instruction::JSR(target))
|
||||||
let data = self.read_instruction_word(system)?;
|
} else {
|
||||||
Ok(Instruction::LINK(reg, data as i16))
|
Ok(Instruction::JMP(target))
|
||||||
} else {
|
}
|
||||||
Ok(Instruction::UNLK(reg))
|
} else if ins_00f0 == 0x40 {
|
||||||
}
|
Ok(Instruction::TRAP((ins & 0x000F) as u8))
|
||||||
} else if (ins & 0b111111110000) == 0b111001100000 {
|
} else if ins_00f0 == 0x50 {
|
||||||
let reg = get_low_reg(ins);
|
let reg = get_low_reg(ins);
|
||||||
let dir = if (ins & 0b1000) == 0 { Direction::FromTarget } else { Direction::ToTarget };
|
if (ins & 0b1000) == 0 {
|
||||||
Ok(Instruction::MOVEUSP(Target::DirectAReg(reg), dir))
|
|
||||||
} else {
|
|
||||||
match ins & 0x0FFF {
|
|
||||||
0xAFC => Ok(Instruction::ILLEGAL),
|
|
||||||
0xE70 => Ok(Instruction::RESET),
|
|
||||||
0xE71 => Ok(Instruction::NOP),
|
|
||||||
0xE72 => {
|
|
||||||
let data = self.read_instruction_word(system)?;
|
let data = self.read_instruction_word(system)?;
|
||||||
Ok(Instruction::STOP(data))
|
Ok(Instruction::LINK(reg, data as i16))
|
||||||
},
|
} else {
|
||||||
0xE73 => Ok(Instruction::RTE),
|
Ok(Instruction::UNLK(reg))
|
||||||
0xE75 => Ok(Instruction::RTS),
|
}
|
||||||
0xE76 => Ok(Instruction::TRAPV),
|
} else if ins_00f0 == 0x60 {
|
||||||
0xE77 => Ok(Instruction::RTR),
|
let reg = get_low_reg(ins);
|
||||||
0xE7A | 0xE7B => {
|
let dir = if (ins & 0b1000) == 0 { Direction::FromTarget } else { Direction::ToTarget };
|
||||||
let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget };
|
Ok(Instruction::MOVEUSP(Target::DirectAReg(reg), dir))
|
||||||
let ins2 = self.read_instruction_word(system)?;
|
} else {
|
||||||
let target = match ins2 & 0x8000 {
|
match ins & 0x00FF {
|
||||||
0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8),
|
0x70 => Ok(Instruction::RESET),
|
||||||
_ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8),
|
0x71 => Ok(Instruction::NOP),
|
||||||
};
|
0x72 => {
|
||||||
let creg = match ins2 & 0xFFF {
|
let data = self.read_instruction_word(system)?;
|
||||||
0x801 => ControlRegister::VBR,
|
Ok(Instruction::STOP(data))
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
},
|
||||||
};
|
0x73 => Ok(Instruction::RTE),
|
||||||
Ok(Instruction::MOVEC(target, creg, dir))
|
0x74 if self.cputype >= M68kType::MC68010 => {
|
||||||
},
|
let offset = self.read_instruction_word(system)? as i16;
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
Ok(Instruction::RTD(offset))
|
||||||
|
},
|
||||||
|
0x75 => Ok(Instruction::RTS),
|
||||||
|
0x76 => Ok(Instruction::TRAPV),
|
||||||
|
0x77 => Ok(Instruction::RTR),
|
||||||
|
0x7A | 0x7B if self.cputype >= M68kType::MC68010 => {
|
||||||
|
let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget };
|
||||||
|
let ins2 = self.read_instruction_word(system)?;
|
||||||
|
let target = match ins2 & 0x8000 {
|
||||||
|
0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8),
|
||||||
|
_ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8),
|
||||||
|
};
|
||||||
|
let creg = match ins2 & 0xFFF {
|
||||||
|
0x801 => ControlRegister::VBR,
|
||||||
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
|
};
|
||||||
|
Ok(Instruction::MOVEC(target, creg, dir))
|
||||||
|
},
|
||||||
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_ADDQ_SUBQ => {
|
OPCG_ADDQ_SUBQ => {
|
||||||
|
@ -455,9 +503,11 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_BRANCH => {
|
OPCG_BRANCH => {
|
||||||
let mut disp = ((ins & 0xFF) as i8) as i16;
|
let mut disp = ((ins & 0xFF) as i8) as i32;
|
||||||
if disp == 0 {
|
if disp == 0 {
|
||||||
disp = self.read_instruction_word(system)? as i16;
|
disp = (self.read_instruction_word(system)? as i16) as i32;
|
||||||
|
} else if disp == 0xff && self.cputype >= M68kType::MC68020 {
|
||||||
|
disp = self.read_instruction_long(system)? as i32;
|
||||||
}
|
}
|
||||||
let condition = get_condition(ins);
|
let condition = get_condition(ins);
|
||||||
match condition {
|
match condition {
|
||||||
|
@ -467,7 +517,9 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_MOVEQ => {
|
OPCG_MOVEQ => {
|
||||||
// TODO make sure the 9th bit is 0
|
if (ins & 0x0100) != 0 {
|
||||||
|
return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION));
|
||||||
|
}
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let data = (ins & 0xFF) as u8;
|
let data = (ins & 0xFF) as u8;
|
||||||
Ok(Instruction::MOVEQ(data, reg))
|
Ok(Instruction::MOVEQ(data, reg))
|
||||||
|
@ -491,17 +543,21 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_SUB => {
|
OPCG_SUB => {
|
||||||
// TODO need to decode the SUBX instruction (would likely be erroneously decoded atm)
|
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let dir = (ins & 0x0100) >> 8;
|
let dir = (ins & 0x0100) >> 8;
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
match size {
|
match size {
|
||||||
Some(size) => {
|
Some(size) => {
|
||||||
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
if (ins & 0b100110000) == 0b100000000 {
|
||||||
if dir == 0 {
|
// TODO implement SUBX
|
||||||
Ok(Instruction::SUB(target, Target::DirectDReg(reg), size))
|
panic!("Not Implemented");
|
||||||
} else {
|
} else {
|
||||||
Ok(Instruction::SUB(Target::DirectDReg(reg), target, size))
|
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
||||||
|
if dir == 0 {
|
||||||
|
Ok(Instruction::SUB(target, Target::DirectDReg(reg), size))
|
||||||
|
} else {
|
||||||
|
Ok(Instruction::SUB(Target::DirectDReg(reg), target, size))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
@ -517,9 +573,12 @@ impl M68kDecoder {
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
match (optype, size) {
|
match (optype, size) {
|
||||||
(0b1, Some(size)) => {
|
(0b1, Some(size)) => {
|
||||||
// TODO need to decode the CMPM instruction (mode == 0b001) (would likely be erroneously decoded atm)
|
if get_low_mode(ins) == 0b001 {
|
||||||
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
Ok(Instruction::CMP(Target::IndirectARegInc(get_low_reg(ins)), Target::IndirectARegInc(reg), size))
|
||||||
Ok(Instruction::EOR(Target::DirectDReg(reg), target, size))
|
} else {
|
||||||
|
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
||||||
|
Ok(Instruction::EOR(Target::DirectDReg(reg), target, size))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
(0b0, Some(size)) => {
|
(0b0, Some(size)) => {
|
||||||
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
||||||
|
@ -536,14 +595,23 @@ impl M68kDecoder {
|
||||||
OPCG_MUL_AND => {
|
OPCG_MUL_AND => {
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
|
|
||||||
if size.is_none() {
|
if (ins & 0b000111110000) == 0b000100000000 {
|
||||||
|
// TODO ABCD
|
||||||
|
panic!("Not Implemented");
|
||||||
|
} else if (ins & 0b000100110000) == 0b000100000000 {
|
||||||
|
let regx = get_high_reg(ins);
|
||||||
|
let regy = get_low_reg(ins);
|
||||||
|
match (ins & 0x00F8) >> 3 {
|
||||||
|
0b01000 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectDReg(regy))),
|
||||||
|
0b01001 => Ok(Instruction::EXG(Target::DirectAReg(regx), Target::DirectAReg(regy))),
|
||||||
|
0b10001 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectAReg(regy))),
|
||||||
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
|
}
|
||||||
|
} else if size.is_none() {
|
||||||
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
|
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
|
||||||
let data_reg = Target::DirectDReg(get_high_reg(ins));
|
let data_reg = Target::DirectDReg(get_high_reg(ins));
|
||||||
let effective_addr = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
|
let effective_addr = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
|
||||||
Ok(Instruction::MUL(effective_addr, data_reg, Size::Word, sign))
|
Ok(Instruction::MUL(effective_addr, data_reg, Size::Word, sign))
|
||||||
} else if (ins & 0b000111110000) == 0b000100000000 {
|
|
||||||
// TODO ABCD or EXG
|
|
||||||
panic!("Not Implemented");
|
|
||||||
} else {
|
} else {
|
||||||
let data_reg = Target::DirectDReg(get_high_reg(ins));
|
let data_reg = Target::DirectDReg(get_high_reg(ins));
|
||||||
let effective_addr = self.decode_lower_effective_address(system, ins, size)?;
|
let effective_addr = self.decode_lower_effective_address(system, ins, size)?;
|
||||||
|
@ -552,17 +620,21 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_ADD => {
|
OPCG_ADD => {
|
||||||
// TODO need to decode the ADDX instruction (would likely be erroneously decoded atm)
|
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let dir = (ins & 0x0100) >> 8;
|
let dir = (ins & 0x0100) >> 8;
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
match size {
|
match size {
|
||||||
Some(size) => {
|
Some(size) => {
|
||||||
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
if (ins & 0b100110000) == 0b100000000 {
|
||||||
if dir == 0 {
|
// TODO implement ADDX
|
||||||
Ok(Instruction::ADD(target, Target::DirectDReg(reg), size))
|
panic!("Not Implemented");
|
||||||
} else {
|
} else {
|
||||||
Ok(Instruction::ADD(Target::DirectDReg(reg), target, size))
|
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
||||||
|
if dir == 0 {
|
||||||
|
Ok(Instruction::ADD(target, Target::DirectDReg(reg), size))
|
||||||
|
} else {
|
||||||
|
Ok(Instruction::ADD(Target::DirectDReg(reg), target, size))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
@ -636,14 +708,28 @@ impl M68kDecoder {
|
||||||
self.get_mode_as_target(system, mode, reg, size)
|
self.get_mode_as_target(system, mode, reg, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_brief_extension_word(&self, brief_extension: u16) -> (RegisterType, u8, i32, Size) {
|
fn decode_extension_word(&mut self, system: &mut AddressableDeviceRefMut<'_>, areg: Option<u8>) -> Result<Target, Error> {
|
||||||
let data = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte);
|
let brief_extension = self.read_instruction_word(system)?;
|
||||||
|
let rtype = if (brief_extension & 0x8000) == 0 { RegisterType::Data } else { RegisterType::Address };
|
||||||
let xreg = ((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 size = if (brief_extension & 0x0800) == 0 { Size::Word } else { Size::Long };
|
||||||
|
let use_full = (brief_extension & 0x0100) == 1;
|
||||||
|
let scale = (brief_extension & 0x0600) >> 9 as u8;
|
||||||
|
|
||||||
let rtype = if (brief_extension & 0x8000) == 0 { RegisterType::Data } else { RegisterType::Address };
|
if !use_full {
|
||||||
|
let displacement = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte);
|
||||||
|
match areg {
|
||||||
|
Some(areg) => Ok(Target::IndirectARegXRegOffset(areg, rtype, xreg, displacement, size)),
|
||||||
|
None => Ok(Target::IndirectPCXRegOffset(rtype, xreg, displacement, size)),
|
||||||
|
}
|
||||||
|
} else if self.cputype >= M68kType::MC68020 {
|
||||||
|
let use_base = (brief_extension & 0x0080) == 0;
|
||||||
|
let use_index = (brief_extension & 0x0040) == 0;
|
||||||
|
|
||||||
(rtype, xreg, data, size)
|
panic!("Not Implemented");
|
||||||
|
} else {
|
||||||
|
Err(Error::processor(ERR_ILLEGAL_INSTRUCTION))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mode_as_target(&mut self, system: &mut AddressableDeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
|
pub fn get_mode_as_target(&mut self, system: &mut AddressableDeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
|
||||||
|
@ -658,9 +744,7 @@ impl M68kDecoder {
|
||||||
Target::IndirectARegOffset(reg, data)
|
Target::IndirectARegOffset(reg, data)
|
||||||
},
|
},
|
||||||
0b110 => {
|
0b110 => {
|
||||||
let brief_extension = self.read_instruction_word(system)?;
|
self.decode_extension_word(system, Some(reg))?
|
||||||
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
|
|
||||||
Target::IndirectARegXRegOffset(reg, rtype, xreg, data, size)
|
|
||||||
},
|
},
|
||||||
0b111 => {
|
0b111 => {
|
||||||
match reg {
|
match reg {
|
||||||
|
@ -677,9 +761,7 @@ impl M68kDecoder {
|
||||||
Target::IndirectPCOffset(data)
|
Target::IndirectPCOffset(data)
|
||||||
},
|
},
|
||||||
0b011 => {
|
0b011 => {
|
||||||
let brief_extension = self.read_instruction_word(system)?;
|
self.decode_extension_word(system, None)?
|
||||||
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
|
|
||||||
Target::IndirectPCXRegOffset(rtype, xreg, data, size)
|
|
||||||
},
|
},
|
||||||
0b100 => {
|
0b100 => {
|
||||||
let data = match size {
|
let data = match size {
|
||||||
|
|
|
@ -18,9 +18,9 @@ use super::decode::{
|
||||||
sign_extend_to_long
|
sign_extend_to_long
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::state::{MC68010, Status, Flags, InterruptPriority};
|
use super::state::{M68k, Status, Flags, InterruptPriority};
|
||||||
|
|
||||||
impl Steppable for MC68010 {
|
impl Steppable for M68k {
|
||||||
fn step(&mut self, system: &System) -> Result<Clock, Error> {
|
fn step(&mut self, system: &System) -> Result<Clock, Error> {
|
||||||
self.step_internal(system)?;
|
self.step_internal(system)?;
|
||||||
Ok(1)
|
Ok(1)
|
||||||
|
@ -31,7 +31,7 @@ impl Steppable for MC68010 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interruptable for MC68010 {
|
impl Interruptable for M68k {
|
||||||
fn interrupt_state_change(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error> {
|
fn interrupt_state_change(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error> {
|
||||||
let ipl = if state {
|
let ipl = if state {
|
||||||
InterruptPriority::from_u8(priority)
|
InterruptPriority::from_u8(priority)
|
||||||
|
@ -49,7 +49,7 @@ impl Interruptable for MC68010 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MC68010 {
|
impl M68k {
|
||||||
pub fn is_running(&self) -> bool {
|
pub fn is_running(&self) -> bool {
|
||||||
self.state.status != Status::Stopped
|
self.state.status != Status::Stopped
|
||||||
}
|
}
|
||||||
|
@ -74,9 +74,9 @@ impl MC68010 {
|
||||||
self.execute_current(system)?;
|
self.execute_current(system)?;
|
||||||
self.timer.cycle.end(timer);
|
self.timer.cycle.end(timer);
|
||||||
|
|
||||||
//if (self.timer.cycle.events % 500) == 0 {
|
if (self.timer.cycle.events % 500) == 0 {
|
||||||
// println!("{}", self.timer);
|
println!("{}", self.timer);
|
||||||
//}
|
}
|
||||||
|
|
||||||
self.check_pending_interrupts(system)?;
|
self.check_pending_interrupts(system)?;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ impl MC68010 {
|
||||||
let pending_ipl = self.state.pending_ipl as u8;
|
let pending_ipl = self.state.pending_ipl as u8;
|
||||||
|
|
||||||
if self.state.pending_ipl != InterruptPriority::NoInterrupt {
|
if self.state.pending_ipl != InterruptPriority::NoInterrupt {
|
||||||
let priority_mask = ((self.state.sr & 0x700) >> 8) as u8;
|
let priority_mask = ((self.state.sr & Flags::IntMask as u16) >> 8) as u8;
|
||||||
|
|
||||||
if (pending_ipl >= priority_mask || pending_ipl == 7) && pending_ipl >= current_ipl {
|
if (pending_ipl >= priority_mask || pending_ipl == 7) && pending_ipl >= current_ipl {
|
||||||
self.state.current_ipl = self.state.pending_ipl;
|
self.state.current_ipl = self.state.pending_ipl;
|
||||||
|
@ -122,7 +122,7 @@ impl MC68010 {
|
||||||
self.check_breakpoints();
|
self.check_breakpoints();
|
||||||
|
|
||||||
let timer = self.timer.decode.start();
|
let timer = self.timer.decode.start();
|
||||||
self.decoder = M68kDecoder::decode_at(system, self.state.pc)?;
|
self.decoder.decode_at(system, self.state.pc)?;
|
||||||
self.timer.decode.end(timer);
|
self.timer.decode.end(timer);
|
||||||
|
|
||||||
if self.debugger.use_tracing {
|
if self.debugger.use_tracing {
|
||||||
|
|
|
@ -5,5 +5,5 @@ pub mod execute;
|
||||||
pub mod debugger;
|
pub mod debugger;
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
||||||
pub use self::state::MC68010;
|
pub use self::state::{M68k, M68kType};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,15 @@ use crate::timers::CpuTimer;
|
||||||
use super::decode::M68kDecoder;
|
use super::decode::M68kDecoder;
|
||||||
use super::debugger::M68kDebugger;
|
use super::debugger::M68kDebugger;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum M68kType {
|
||||||
|
MC68000,
|
||||||
|
MC68010,
|
||||||
|
MC68020,
|
||||||
|
MC68030,
|
||||||
|
}
|
||||||
|
|
||||||
const FLAGS_ON_RESET: u16 = 0x2700;
|
const FLAGS_ON_RESET: u16 = 0x2700;
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
@ -16,6 +25,8 @@ pub enum Flags {
|
||||||
Zero = 0x0004,
|
Zero = 0x0004,
|
||||||
Negative = 0x0008,
|
Negative = 0x0008,
|
||||||
Extend = 0x0010,
|
Extend = 0x0010,
|
||||||
|
IntMask = 0x0700,
|
||||||
|
Interrupt = 0x1000,
|
||||||
Supervisor = 0x2000,
|
Supervisor = 0x2000,
|
||||||
Tracing = 0x8000,
|
Tracing = 0x8000,
|
||||||
}
|
}
|
||||||
|
@ -61,7 +72,7 @@ impl InterruptPriority {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MC68010State {
|
pub struct M68kState {
|
||||||
pub status: Status,
|
pub status: Status,
|
||||||
pub current_ipl: InterruptPriority,
|
pub current_ipl: InterruptPriority,
|
||||||
pub pending_ipl: InterruptPriority,
|
pub pending_ipl: InterruptPriority,
|
||||||
|
@ -77,9 +88,9 @@ pub struct MC68010State {
|
||||||
pub vbr: u32,
|
pub vbr: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MC68010State {
|
impl M68kState {
|
||||||
pub fn new() -> MC68010State {
|
pub fn new() -> M68kState {
|
||||||
MC68010State {
|
M68kState {
|
||||||
status: Status::Init,
|
status: Status::Init,
|
||||||
current_ipl: InterruptPriority::NoInterrupt,
|
current_ipl: InterruptPriority::NoInterrupt,
|
||||||
pending_ipl: InterruptPriority::NoInterrupt,
|
pending_ipl: InterruptPriority::NoInterrupt,
|
||||||
|
@ -97,26 +108,28 @@ impl MC68010State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MC68010 {
|
pub struct M68k {
|
||||||
pub state: MC68010State,
|
pub cputype: M68kType,
|
||||||
|
pub state: M68kState,
|
||||||
pub decoder: M68kDecoder,
|
pub decoder: M68kDecoder,
|
||||||
pub debugger: M68kDebugger,
|
pub debugger: M68kDebugger,
|
||||||
pub timer: CpuTimer,
|
pub timer: CpuTimer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MC68010 {
|
impl M68k {
|
||||||
pub fn new() -> MC68010 {
|
pub fn new(cputype: M68kType) -> M68k {
|
||||||
MC68010 {
|
M68k {
|
||||||
state: MC68010State::new(),
|
cputype,
|
||||||
decoder: M68kDecoder::new(0, 0),
|
state: M68kState::new(),
|
||||||
|
decoder: M68kDecoder::new(cputype, 0, 0),
|
||||||
debugger: M68kDebugger::new(),
|
debugger: M68kDebugger::new(),
|
||||||
timer: CpuTimer::new(),
|
timer: CpuTimer::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.state = MC68010State::new();
|
self.state = M68kState::new();
|
||||||
self.decoder = M68kDecoder::new(0, 0);
|
self.decoder = M68kDecoder::new(self.cputype, 0, 0);
|
||||||
self.debugger = M68kDebugger::new();
|
self.debugger = M68kDebugger::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,13 @@ use crate::system::System;
|
||||||
use crate::devices::{Steppable, wrap_addressable};
|
use crate::devices::{Steppable, wrap_addressable};
|
||||||
use crate::memory::{Address, Addressable, MemoryBlock};
|
use crate::memory::{Address, Addressable, MemoryBlock};
|
||||||
|
|
||||||
use super::state::MC68010;
|
|
||||||
use super::decode::Instruction;
|
use super::decode::Instruction;
|
||||||
|
use super::state::{M68k, M68kType};
|
||||||
|
|
||||||
const INIT_STACK: Address = 0x00002000;
|
const INIT_STACK: Address = 0x00002000;
|
||||||
const INIT_ADDR: Address = 0x00000010;
|
const INIT_ADDR: Address = 0x00000010;
|
||||||
|
|
||||||
fn init_test() -> (MC68010, System) {
|
fn init_test() -> (M68k, System) {
|
||||||
let mut system = System::new();
|
let mut system = System::new();
|
||||||
|
|
||||||
// Insert basic initialization
|
// Insert basic initialization
|
||||||
|
@ -19,7 +19,7 @@ fn init_test() -> (MC68010, System) {
|
||||||
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
|
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
|
||||||
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
|
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
|
||||||
|
|
||||||
let mut cpu = MC68010::new();
|
let mut cpu = M68k::new(M68kType::MC68010);
|
||||||
cpu.step(&system).unwrap();
|
cpu.step(&system).unwrap();
|
||||||
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
|
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
|
||||||
assert_eq!(cpu.state.msp, INIT_STACK as u32);
|
assert_eq!(cpu.state.msp, INIT_STACK as u32);
|
||||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -11,8 +11,8 @@ mod system;
|
||||||
|
|
||||||
use crate::system::System;
|
use crate::system::System;
|
||||||
use crate::memory::MemoryBlock;
|
use crate::memory::MemoryBlock;
|
||||||
use crate::cpus::m68k::MC68010;
|
|
||||||
use crate::peripherals::ata::AtaDevice;
|
use crate::peripherals::ata::AtaDevice;
|
||||||
|
use crate::cpus::m68k::{M68k, M68kType};
|
||||||
use crate::peripherals::mc68681::MC68681;
|
use crate::peripherals::mc68681::MC68681;
|
||||||
use crate::devices::{wrap_addressable, wrap_interruptable};
|
use crate::devices::{wrap_addressable, wrap_interruptable};
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ fn main() {
|
||||||
system.add_addressable_device(0x00700000, wrap_addressable(serial)).unwrap();
|
system.add_addressable_device(0x00700000, wrap_addressable(serial)).unwrap();
|
||||||
|
|
||||||
|
|
||||||
let mut cpu = MC68010::new();
|
let mut cpu = M68k::new(M68kType::MC68010);
|
||||||
|
|
||||||
//cpu.enable_tracing();
|
//cpu.enable_tracing();
|
||||||
//cpu.add_breakpoint(0x10781a);
|
//cpu.add_breakpoint(0x10781a);
|
||||||
|
@ -87,26 +87,11 @@ pub fn launch_slip_connection(name: String) {
|
||||||
use nix::unistd::sleep;
|
use nix::unistd::sleep;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
//Command::new("x-terminal-emulator").arg("-e").arg(&format!("pyserial-miniterm {}", name)).spawn().unwrap();
|
|
||||||
|
|
||||||
Command::new("sudo").args(["slattach", "-s", "38400", "-p", "slip", &name]).spawn().unwrap();
|
Command::new("sudo").args(["slattach", "-s", "38400", "-p", "slip", &name]).spawn().unwrap();
|
||||||
Command::new("sudo").args(["ifconfig", "sl0", "192.168.1.2", "pointopoint", "192.168.1.200", "up"]).status().unwrap();
|
Command::new("sudo").args(["ifconfig", "sl0", "192.168.1.2", "pointopoint", "192.168.1.200", "up"]).status().unwrap();
|
||||||
Command::new("sudo").args(["arp", "-Ds", "192.168.1.200", "enp4s0", "pub"]).status().unwrap();
|
Command::new("sudo").args(["arp", "-Ds", "192.168.1.200", "enp4s0", "pub"]).status().unwrap();
|
||||||
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-i", "sl0", "-j", "ACCEPT"]).status().unwrap();
|
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-i", "sl0", "-j", "ACCEPT"]).status().unwrap();
|
||||||
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-o", "sl0", "-j", "ACCEPT"]).status().unwrap();
|
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-o", "sl0", "-j", "ACCEPT"]).status().unwrap();
|
||||||
Command::new("sudo").args(["sh", "-c", "echo 1 > /proc/sys/net/ipv4/ip_forward"]).status().unwrap();
|
Command::new("sudo").args(["sh", "-c", "echo 1 > /proc/sys/net/ipv4/ip_forward"]).status().unwrap();
|
||||||
/*
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
sudo slattach -s 38400 -p slip /dev/ttyUSB1
|
|
||||||
sudo ifconfig sl0 192.168.1.2 pointopoint 192.168.1.200 up
|
|
||||||
// (this is automatically added on my machine) >> sudo route add -host 192.168.1.200 sl0
|
|
||||||
sudo arp -Ds 192.168.1.200 enp3s0 pub
|
|
||||||
sudo iptables -A FORWARD -i sl0 -j ACCEPT
|
|
||||||
sudo iptables -A FORWARD -o sl0 -j ACCEPT
|
|
||||||
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
|
|
||||||
*/
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
todo.txt
14
todo.txt
|
@ -1,10 +1,22 @@
|
||||||
|
|
||||||
|
* make functions to print assembly out
|
||||||
* how can you add 68030 support? Should it be all one module that checks maybe during decode if the instruction is supported? Should it 'inherit' from the MC68010 object
|
* how can you add 68030 support? Should it be all one module that checks maybe during decode if the instruction is supported? Should it 'inherit' from the MC68010 object
|
||||||
|
* make tests for each instruction
|
||||||
|
|
||||||
|
* unimplemented: ADDX, BKPT, CHK, EXG, ILLEGAL, MOVEfromCCR, MOVEP, RTR, RTD, SUBX
|
||||||
|
* undecoded: ADDX, SUBX, ABCD, SBCD
|
||||||
|
* modify execution for >=MC68020: DIVSL, DIVUL, EXTB, LINK, MOVEM, MULSL, MULUL, RTM, TRAPcc, UNPK
|
||||||
|
* implement the full extension word for MC68020+
|
||||||
|
|
||||||
|
* >=MC68020 instructions: BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, CALLM, CAS, CAS2, CHK2, CMP2, PACK
|
||||||
|
* Coprocessor instructions: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc
|
||||||
|
|
||||||
|
|
||||||
|
* should you simulate clock ticks, and only step devices when they next request it
|
||||||
* how can you have multple CPUs
|
* how can you have multple CPUs
|
||||||
* should you simulate bus arbitration?
|
* should you simulate bus arbitration?
|
||||||
|
|
||||||
|
|
||||||
* check all instructions in the docs
|
* check all instructions in the docs
|
||||||
* make tests for each instruction
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user