Added A and F instructions to m68k

This commit is contained in:
transistor 2021-11-23 11:45:11 -08:00
parent f601290771
commit 03f23da544
9 changed files with 57 additions and 43 deletions

View File

@ -30,15 +30,12 @@ const OPCG_BRANCH: u8 = 0x6;
const OPCG_MOVEQ: u8 = 0x7;
const OPCG_DIV_OR: u8 = 0x8;
const OPCG_SUB: u8 = 0x9;
const OPCG_ALINE: u8 = 0xA;
const OPCG_CMP_EOR: u8 = 0xB;
const OPCG_MUL_AND: u8 = 0xC;
const OPCG_ADD: u8 = 0xD;
const OPCG_SHIFT: u8 = 0xE;
#[allow(dead_code)]
const OPCG_RESERVED1: u8 = 0xA;
#[allow(dead_code)]
const OPCG_RESERVED2: u8 = 0xF;
const OPCG_FLINE: u8 = 0xF;
pub struct M68kDecoder {
@ -597,6 +594,12 @@ impl M68kDecoder {
},
}
},
OPCG_ALINE => {
Ok(Instruction::UnimplementedA(ins))
},
OPCG_FLINE => {
Ok(Instruction::UnimplementedF(ins))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}

View File

@ -706,6 +706,14 @@ impl M68k {
let addr = self.get_a_reg_mut(reg);
*addr = new_value;
},
Instruction::UnimplementedA(ins) => {
self.state.pc -= 2;
self.exception(Exceptions::LineAEmulator as u8, false)?;
},
Instruction::UnimplementedF(ins) => {
self.state.pc -= 2;
self.exception(Exceptions::LineFEmulator as u8, false)?;
},
_ => { return Err(Error::new("Unsupported instruction")); },
}
@ -716,7 +724,6 @@ impl M68k {
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mut mask: u16) -> Result<(), Error> {
let mut addr = self.get_target_address(target)?;
// If we're using a MC68020 or higher, and it was Post-Inc/Pre-Dec target, then update the value before it's stored
if self.cputype >= M68kType::MC68020 {
match target {

View File

@ -195,6 +195,8 @@ pub enum Instruction {
TRAPV,
UNLK(Register),
UnimplementedA(u16),
UnimplementedF(u16),
}
pub fn sign_extend_to_long(value: u32, from: Size) -> i32 {

View File

@ -45,6 +45,9 @@ pub enum Exceptions {
ChkInstruction = 6,
TrapvInstruction = 7,
PrivilegeViolation = 8,
Trace = 9,
LineAEmulator = 10,
LineFEmulator = 11,
}

View File

@ -46,6 +46,8 @@ mod decode_tests {
TestCase { cpu: M68kType::MC68000, data: &[0xE200], ins: Some(Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right)) },
TestCase { cpu: M68kType::MC68000, data: &[0xE318], ins: Some(Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left)) },
TestCase { cpu: M68kType::MC68000, data: &[0xE218], ins: Some(Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right)) },
TestCase { cpu: M68kType::MC68000, data: &[0xA000], ins: Some(Instruction::UnimplementedA(0xA000)) },
TestCase { cpu: M68kType::MC68000, data: &[0xFFFF], ins: Some(Instruction::UnimplementedF(0xFFFF)) },
// MC68030
TestCase { cpu: M68kType::MC68030, data: &[0x4C3C, 0x0800, 0x0000, 0x0097], ins: Some(Instruction::MULL(Target::Immediate(0x97), None, 0, Sign::Signed)) },
@ -53,7 +55,6 @@ mod decode_tests {
// Should Fail
TestCase { cpu: M68kType::MC68000, data: &[0x21BC, 0x0010, 0x14C4, 0x09B0, 0x0010, 0xDF40], ins: None },
TestCase { cpu: M68kType::MC68000, data: &[0xA000], ins: None },
];
@ -373,8 +374,8 @@ mod execute_tests {
d1: u32,
a0: u32,
a1: u32,
mem: u32,
sr: u16,
mem: u32,
}
struct TestCase {

View File

@ -3,31 +3,9 @@ use std::io::Write;
use crate::error::Error;
use crate::system::System;
use crate::devices::{Address, Debuggable, TransmutableBox};
use crate::devices::{Address, Addressable, Debuggable, TransmutableBox};
/*
pub struct StackTracer {
pub calls: Vec<u32>,
}
impl StackTracer {
pub fn new() -> StackTracer {
StackTracer {
calls: vec![],
}
}
pub fn push_return(&mut self, addr: u32) {
self.calls.push(addr);
}
pub fn pop_return(&mut self) {
self.calls.pop();
}
}
*/
pub struct Debugger {
pub last_command: Option<String>,
pub repeat: u32,
@ -98,7 +76,7 @@ impl Debugger {
},
"r" | "remove" => {
if args.len() != 2 {
println!("Usage: breakpoint <addr>");
println!("Usage: remove <addr>");
} else {
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse breakpoint address"))?;
debug_obj.remove_breakpoint(addr as Address);
@ -142,6 +120,20 @@ impl Debugger {
self.trace_only = true;
return Ok(true);
}
"setb" | "setw" | "setl" => {
if args.len() != 3 {
println!("Usage: set[b|w|l] <addr> <data>");
} else {
let addr = u64::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse set address"))?;
let data = u32::from_str_radix(args[2], 16).map_err(|_| Error::new("Unable to parse data"))?;
match args[0] {
"setb" => system.get_bus().write_u8(addr, data as u8)?,
"setw" => system.get_bus().write_beu16(addr, data as u16)?,
"setl" => system.get_bus().write_beu32(addr, data)?,
_ => panic!("Unimplemented: {:?}", args[0]),
}
}
},
//"ds" | "stack" | "dumpstack" => {
// println!("Stack:");
// for addr in &self.debugger.stack_tracer.calls {

View File

@ -130,7 +130,7 @@ impl Bus {
pub fn insert(&mut self, base: Address, length: usize, dev: TransmutableBox) {
let block = Block { base, length, dev };
let i = self.blocks.iter().position(|cur| cur.base > block.base).unwrap_or(0);
let i = self.blocks.iter().position(|cur| cur.base > block.base).unwrap_or(self.blocks.len());
self.blocks.insert(i, block);
}
@ -145,7 +145,7 @@ impl Bus {
}
}
}
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
return Err(Error::new(&format!("No segment found at {:#010x}", addr)));
}
pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) {

View File

@ -7,13 +7,13 @@ use crate::memory::Bus;
use crate::debugger::Debugger;
use crate::error::{Error, ErrorType};
use crate::interrupts::InterruptController;
use crate::devices::{Clock, Address, TransmutableBox};
use crate::devices::{Clock, ClockElapsed, Address, TransmutableBox};
pub struct System {
pub clock: Clock,
pub devices: HashMap<String, TransmutableBox>,
pub event_queue: Vec<DeviceStep>,
pub event_queue: Vec<NextStep>,
pub debug_enabled: Cell<bool>,
pub debugger: RefCell<Debugger>,
@ -89,12 +89,12 @@ impl System {
result
}
pub fn run_for(&mut self, clocks: Clock) -> Result<(), Error> {
let target = self.clock + clocks;
pub fn run_for(&mut self, elapsed: ClockElapsed) -> Result<(), Error> {
let target = self.clock + elapsed;
while self.clock < target {
if self.debug_enabled.get() && self.event_queue[self.event_queue.len() - 1].device.borrow_mut().as_debuggable().is_some() {
self.debugger.borrow_mut().run_debugger(&self, self.event_queue[self.event_queue.len() - 1].device.clone()).unwrap();
self.debugger.borrow_mut().run_debugger(&self, self.event_queue[self.event_queue.len() - 1].device.clone());
}
match self.step() {
@ -129,11 +129,11 @@ impl System {
fn try_queue_device(&mut self, device: TransmutableBox) {
if device.borrow_mut().as_steppable().is_some() {
self.queue_device(DeviceStep::new(device));
self.queue_device(NextStep::new(device));
}
}
fn queue_device(&mut self, device_step: DeviceStep) {
fn queue_device(&mut self, device_step: NextStep) {
for i in (0..self.event_queue.len()).rev() {
if self.event_queue[i].next_clock > device_step.next_clock {
self.event_queue.insert(i + 1, device_step);
@ -145,12 +145,12 @@ impl System {
}
pub struct DeviceStep {
pub struct NextStep {
pub next_clock: Clock,
pub device: TransmutableBox,
}
impl DeviceStep {
impl NextStep {
pub fn new(device: TransmutableBox) -> Self {
Self {
next_clock: 0,

View File

@ -1,4 +1,10 @@
* movem still isn't working (for genesis)
* fix movem tests
* modify the frame swapper and frontend to avoid the extra buffer copy
* I had to remove the mask colour from blit because it doesn't work with the mac... need a new solution
* add more m68k tests and try to test against a working impl
* maybe see about a Mac 128k or something