mirror of
https://github.com/transistorfet/moa.git
synced 2024-09-29 15:56:19 +00:00
Added A and F instructions to m68k
This commit is contained in:
parent
f601290771
commit
03f23da544
@ -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)),
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -45,6 +45,9 @@ pub enum Exceptions {
|
||||
ChkInstruction = 6,
|
||||
TrapvInstruction = 7,
|
||||
PrivilegeViolation = 8,
|
||||
Trace = 9,
|
||||
LineAEmulator = 10,
|
||||
LineFEmulator = 11,
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
6
todo.txt
6
todo.txt
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user