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_MOVEQ: u8 = 0x7;
|
||||||
const OPCG_DIV_OR: u8 = 0x8;
|
const OPCG_DIV_OR: u8 = 0x8;
|
||||||
const OPCG_SUB: u8 = 0x9;
|
const OPCG_SUB: u8 = 0x9;
|
||||||
|
const OPCG_ALINE: u8 = 0xA;
|
||||||
const OPCG_CMP_EOR: u8 = 0xB;
|
const OPCG_CMP_EOR: u8 = 0xB;
|
||||||
const OPCG_MUL_AND: u8 = 0xC;
|
const OPCG_MUL_AND: u8 = 0xC;
|
||||||
const OPCG_ADD: u8 = 0xD;
|
const OPCG_ADD: u8 = 0xD;
|
||||||
const OPCG_SHIFT: u8 = 0xE;
|
const OPCG_SHIFT: u8 = 0xE;
|
||||||
|
const OPCG_FLINE: u8 = 0xF;
|
||||||
#[allow(dead_code)]
|
|
||||||
const OPCG_RESERVED1: u8 = 0xA;
|
|
||||||
#[allow(dead_code)]
|
|
||||||
const OPCG_RESERVED2: u8 = 0xF;
|
|
||||||
|
|
||||||
|
|
||||||
pub struct M68kDecoder {
|
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)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -706,6 +706,14 @@ impl M68k {
|
|||||||
let addr = self.get_a_reg_mut(reg);
|
let addr = self.get_a_reg_mut(reg);
|
||||||
*addr = new_value;
|
*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")); },
|
_ => { 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> {
|
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mut mask: u16) -> Result<(), Error> {
|
||||||
let mut addr = self.get_target_address(target)?;
|
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 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 {
|
if self.cputype >= M68kType::MC68020 {
|
||||||
match target {
|
match target {
|
||||||
|
@ -195,6 +195,8 @@ pub enum Instruction {
|
|||||||
TRAPV,
|
TRAPV,
|
||||||
|
|
||||||
UNLK(Register),
|
UNLK(Register),
|
||||||
|
UnimplementedA(u16),
|
||||||
|
UnimplementedF(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign_extend_to_long(value: u32, from: Size) -> i32 {
|
pub fn sign_extend_to_long(value: u32, from: Size) -> i32 {
|
||||||
|
@ -45,6 +45,9 @@ pub enum Exceptions {
|
|||||||
ChkInstruction = 6,
|
ChkInstruction = 6,
|
||||||
TrapvInstruction = 7,
|
TrapvInstruction = 7,
|
||||||
PrivilegeViolation = 8,
|
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: &[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: &[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: &[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
|
// MC68030
|
||||||
TestCase { cpu: M68kType::MC68030, data: &[0x4C3C, 0x0800, 0x0000, 0x0097], ins: Some(Instruction::MULL(Target::Immediate(0x97), None, 0, Sign::Signed)) },
|
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
|
// Should Fail
|
||||||
TestCase { cpu: M68kType::MC68000, data: &[0x21BC, 0x0010, 0x14C4, 0x09B0, 0x0010, 0xDF40], ins: None },
|
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,
|
d1: u32,
|
||||||
a0: u32,
|
a0: u32,
|
||||||
a1: u32,
|
a1: u32,
|
||||||
mem: u32,
|
|
||||||
sr: u16,
|
sr: u16,
|
||||||
|
mem: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestCase {
|
struct TestCase {
|
||||||
|
@ -3,31 +3,9 @@ use std::io::Write;
|
|||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::system::System;
|
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 struct Debugger {
|
||||||
pub last_command: Option<String>,
|
pub last_command: Option<String>,
|
||||||
pub repeat: u32,
|
pub repeat: u32,
|
||||||
@ -98,7 +76,7 @@ impl Debugger {
|
|||||||
},
|
},
|
||||||
"r" | "remove" => {
|
"r" | "remove" => {
|
||||||
if args.len() != 2 {
|
if args.len() != 2 {
|
||||||
println!("Usage: breakpoint <addr>");
|
println!("Usage: remove <addr>");
|
||||||
} else {
|
} else {
|
||||||
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse breakpoint address"))?;
|
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);
|
debug_obj.remove_breakpoint(addr as Address);
|
||||||
@ -142,6 +120,20 @@ impl Debugger {
|
|||||||
self.trace_only = true;
|
self.trace_only = true;
|
||||||
return Ok(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" => {
|
//"ds" | "stack" | "dumpstack" => {
|
||||||
// println!("Stack:");
|
// println!("Stack:");
|
||||||
// for addr in &self.debugger.stack_tracer.calls {
|
// 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) {
|
pub fn insert(&mut self, base: Address, length: usize, dev: TransmutableBox) {
|
||||||
let block = Block { base, length, dev };
|
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);
|
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) {
|
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::debugger::Debugger;
|
||||||
use crate::error::{Error, ErrorType};
|
use crate::error::{Error, ErrorType};
|
||||||
use crate::interrupts::InterruptController;
|
use crate::interrupts::InterruptController;
|
||||||
use crate::devices::{Clock, Address, TransmutableBox};
|
use crate::devices::{Clock, ClockElapsed, Address, TransmutableBox};
|
||||||
|
|
||||||
|
|
||||||
pub struct System {
|
pub struct System {
|
||||||
pub clock: Clock,
|
pub clock: Clock,
|
||||||
pub devices: HashMap<String, TransmutableBox>,
|
pub devices: HashMap<String, TransmutableBox>,
|
||||||
pub event_queue: Vec<DeviceStep>,
|
pub event_queue: Vec<NextStep>,
|
||||||
|
|
||||||
pub debug_enabled: Cell<bool>,
|
pub debug_enabled: Cell<bool>,
|
||||||
pub debugger: RefCell<Debugger>,
|
pub debugger: RefCell<Debugger>,
|
||||||
@ -89,12 +89,12 @@ impl System {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_for(&mut self, clocks: Clock) -> Result<(), Error> {
|
pub fn run_for(&mut self, elapsed: ClockElapsed) -> Result<(), Error> {
|
||||||
let target = self.clock + clocks;
|
let target = self.clock + elapsed;
|
||||||
|
|
||||||
while self.clock < target {
|
while self.clock < target {
|
||||||
if self.debug_enabled.get() && self.event_queue[self.event_queue.len() - 1].device.borrow_mut().as_debuggable().is_some() {
|
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() {
|
match self.step() {
|
||||||
@ -129,11 +129,11 @@ impl System {
|
|||||||
|
|
||||||
fn try_queue_device(&mut self, device: TransmutableBox) {
|
fn try_queue_device(&mut self, device: TransmutableBox) {
|
||||||
if device.borrow_mut().as_steppable().is_some() {
|
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() {
|
for i in (0..self.event_queue.len()).rev() {
|
||||||
if self.event_queue[i].next_clock > device_step.next_clock {
|
if self.event_queue[i].next_clock > device_step.next_clock {
|
||||||
self.event_queue.insert(i + 1, device_step);
|
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 next_clock: Clock,
|
||||||
pub device: TransmutableBox,
|
pub device: TransmutableBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceStep {
|
impl NextStep {
|
||||||
pub fn new(device: TransmutableBox) -> Self {
|
pub fn new(device: TransmutableBox) -> Self {
|
||||||
Self {
|
Self {
|
||||||
next_clock: 0,
|
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
|
* add more m68k tests and try to test against a working impl
|
||||||
* maybe see about a Mac 128k or something
|
* maybe see about a Mac 128k or something
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user