Fixed a number of instruction bugs with m68k

This commit is contained in:
transistor
2021-11-03 23:55:50 -07:00
parent b6cccea437
commit 2cb21d7b8d
5 changed files with 125 additions and 44 deletions

View File

@@ -347,10 +347,18 @@ impl M68kDecoder {
data = 8; data = 8;
} }
if (ins & 0x0100) == 0 { if let Target::DirectAReg(reg) = target {
Ok(Instruction::ADD(Target::Immediate(data), target, size)) if (ins & 0x0100) == 0 {
Ok(Instruction::ADDA(Target::Immediate(data), reg, size))
} else {
Ok(Instruction::SUBA(Target::Immediate(data), reg, size))
}
} else { } else {
Ok(Instruction::SUB(Target::Immediate(data), target, size)) if (ins & 0x0100) == 0 {
Ok(Instruction::ADD(Target::Immediate(data), target, size))
} else {
Ok(Instruction::SUB(Target::Immediate(data), target, size))
}
} }
}, },
None => { None => {

View File

@@ -97,6 +97,7 @@ impl M68k {
//} //}
self.check_pending_interrupts(system)?; self.check_pending_interrupts(system)?;
self.check_breakpoints(system);
Ok(()) Ok(())
} }
@@ -129,7 +130,7 @@ impl M68k {
} }
pub fn exception(&mut self, system: &System, number: u8, is_interrupt: bool) -> Result<(), Error> { pub fn exception(&mut self, system: &System, number: u8, is_interrupt: bool) -> Result<(), Error> {
debug!("{}: raising exception {}", DEV_NAME, number); info!("{}: raising exception {}", DEV_NAME, number);
let offset = (number as u16) << 2; let offset = (number as u16) << 2;
if self.cputype >= M68kType::MC68010 { if self.cputype >= M68kType::MC68010 {
self.push_word(system, offset)?; self.push_word(system, offset)?;
@@ -150,8 +151,6 @@ impl M68k {
} }
pub fn decode_next(&mut self, system: &System) -> Result<(), Error> { pub fn decode_next(&mut self, system: &System) -> Result<(), Error> {
self.check_breakpoints(system);
self.timer.decode.start(); self.timer.decode.start();
self.decoder.decode_at(&mut self.port, self.state.pc)?; self.decoder.decode_at(&mut self.port, self.state.pc)?;
self.timer.decode.end(); self.timer.decode.end();
@@ -161,12 +160,15 @@ impl M68k {
} }
self.state.pc = self.decoder.end; self.state.pc = self.decoder.end;
Ok(()) Ok(())
} }
pub fn execute_current(&mut self, system: &System) -> Result<(), Error> { pub fn execute_current(&mut self, system: &System) -> Result<(), Error> {
self.timer.execute.start(); self.timer.execute.start();
match self.decoder.instruction { match self.decoder.instruction {
//Instruction::ABCD(Target) => {
//},
Instruction::ADD(src, dest, size) => { Instruction::ADD(src, dest, size) => {
let value = self.get_target_value(system, src, size)?; let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?; let existing = self.get_target_value(system, dest, size)?;
@@ -175,11 +177,13 @@ impl M68k {
self.set_target_value(system, dest, result, size)?; self.set_target_value(system, dest, result, size)?;
}, },
Instruction::ADDA(src, dest, size) => { Instruction::ADDA(src, dest, size) => {
let value = self.get_target_value(system, src, size)?; let value = sign_extend_to_long(self.get_target_value(system, src, size)?, size) as u32;
let existing = *self.get_a_reg_mut(dest); let existing = *self.get_a_reg_mut(dest);
let (result, carry) = overflowing_add_sized(existing, value, Size::Long); let (result, _) = overflowing_add_sized(existing, value, Size::Long);
*self.get_a_reg_mut(dest) = result; *self.get_a_reg_mut(dest) = result;
}, },
//Instruction::ADDX(Target) => {
//},
Instruction::AND(src, dest, size) => { Instruction::AND(src, dest, size) => {
let value = self.get_target_value(system, src, size)?; let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?; let existing = self.get_target_value(system, dest, size)?;
@@ -188,7 +192,7 @@ impl M68k {
self.set_logic_flags(result, size); self.set_logic_flags(result, size);
}, },
Instruction::ANDtoCCR(value) => { Instruction::ANDtoCCR(value) => {
self.state.sr = self.state.sr & (value as u16); self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) & (value as u16));
}, },
Instruction::ANDtoSR(value) => { Instruction::ANDtoSR(value) => {
self.require_supervisor()?; self.require_supervisor()?;
@@ -226,32 +230,32 @@ impl M68k {
self.debugger.stack_tracer.push_return(sp); self.debugger.stack_tracer.push_return(sp);
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32); self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
}, },
Instruction::BTST(bitnum, target, size) => {
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
let value = self.get_target_value(system, target, size)?;
self.set_bit_test_flags(value, bitnum, size);
},
Instruction::BCHG(bitnum, target, size) => { Instruction::BCHG(bitnum, target, size) => {
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?; let bitnum = self.get_target_value(system, bitnum, Size::Byte)? % get_bit_op_max(size);
let mut value = self.get_target_value(system, target, size)?; let mut value = self.get_target_value(system, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size); let mask = self.set_bit_test_flags(value, bitnum, size);
value = (value & !mask) | (!(value & mask) & mask); value = (value & !mask) | (!(value & mask) & mask);
self.set_target_value(system, target, value, size)?; self.set_target_value(system, target, value, size)?;
}, },
Instruction::BCLR(bitnum, target, size) => { Instruction::BCLR(bitnum, target, size) => {
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?; let bitnum = self.get_target_value(system, bitnum, Size::Byte)? % get_bit_op_max(size);
let mut value = self.get_target_value(system, target, size)?; let mut value = self.get_target_value(system, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size); let mask = self.set_bit_test_flags(value, bitnum, size);
value = value & !mask; value = value & !mask;
self.set_target_value(system, target, value, size)?; self.set_target_value(system, target, value, size)?;
}, },
Instruction::BSET(bitnum, target, size) => { Instruction::BSET(bitnum, target, size) => {
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?; let bitnum = self.get_target_value(system, bitnum, Size::Byte)? % get_bit_op_max(size);
let mut value = self.get_target_value(system, target, size)?; let mut value = self.get_target_value(system, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size); let mask = self.set_bit_test_flags(value, bitnum, size);
value = value | mask; value = value | mask;
self.set_target_value(system, target, value, size)?; self.set_target_value(system, target, value, size)?;
}, },
Instruction::BTST(bitnum, target, size) => {
let bitnum = self.get_target_value(system, bitnum, Size::Byte)? % get_bit_op_max(size);
let value = self.get_target_value(system, target, size)?;
self.set_bit_test_flags(value, bitnum, size);
},
Instruction::BFCHG(target, offset, width) => { Instruction::BFCHG(target, offset, width) => {
let (offset, width) = self.get_bit_field_args(offset, width); let (offset, width) = self.get_bit_field_args(offset, width);
let mask = get_bit_field_mask(offset, width); let mask = get_bit_field_mask(offset, width);
@@ -311,6 +315,8 @@ impl M68k {
}, },
//Instruction::BKPT(u8) => { //Instruction::BKPT(u8) => {
//}, //},
//Instruction::CHK(Target, Size) => {
//},
Instruction::CLR(target, size) => { Instruction::CLR(target, size) => {
self.set_target_value(system, target, 0, size)?; self.set_target_value(system, target, 0, size)?;
// Clear flags except Zero flag // Clear flags except Zero flag
@@ -396,18 +402,18 @@ impl M68k {
self.set_logic_flags(result, size); self.set_logic_flags(result, size);
}, },
Instruction::EORtoCCR(value) => { Instruction::EORtoCCR(value) => {
self.state.sr = self.state.sr ^ (value as u16); self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16));
}, },
Instruction::EORtoSR(value) => { Instruction::EORtoSR(value) => {
self.require_supervisor()?; self.require_supervisor()?;
self.state.sr = self.state.sr ^ value; self.state.sr = self.state.sr ^ value;
}, },
//Instruction::EXG(target1, target2) => { Instruction::EXG(target1, target2) => {
// let value1 = self.get_target_value(system, target1, Size::Long)?; let value1 = self.get_target_value(system, target1, Size::Long)?;
// let value2 = self.get_target_value(system, target2, Size::Long)?; let value2 = self.get_target_value(system, target2, Size::Long)?;
// self.set_target_value(system, target1, value2, Size::Long)?; self.set_target_value(system, target1, value2, Size::Long)?;
// self.set_target_value(system, target2, value1, Size::Long)?; self.set_target_value(system, target2, value1, Size::Long)?;
//}, },
Instruction::EXT(reg, from_size, to_size) => { Instruction::EXT(reg, from_size, to_size) => {
let input = self.state.d_reg[reg as usize]; let input = self.state.d_reg[reg as usize];
let result = match (from_size, to_size) { let result = match (from_size, to_size) {
@@ -494,6 +500,16 @@ impl M68k {
}, },
} }
}, },
Instruction::MOVEM(target, size, dir, mask) => {
self.execute_movem(system, target, size, dir, mask)?;
},
//Instruction::MOVEP(Register, Target, Size, Direction) => {
//},
Instruction::MOVEQ(data, reg) => {
let value = sign_extend_to_long(data as u32, Size::Byte) as u32;
self.state.d_reg[reg as usize] = value;
self.set_logic_flags(value, Size::Long);
},
Instruction::MOVEUSP(target, dir) => { Instruction::MOVEUSP(target, dir) => {
self.require_supervisor()?; self.require_supervisor()?;
match dir { match dir {
@@ -501,14 +517,6 @@ impl M68k {
Direction::FromTarget => { self.state.usp = self.get_target_value(system, target, Size::Long)?; }, Direction::FromTarget => { self.state.usp = self.get_target_value(system, target, Size::Long)?; },
} }
}, },
Instruction::MOVEM(target, size, dir, mask) => {
self.execute_movem(system, target, size, dir, mask)?;
},
Instruction::MOVEQ(data, reg) => {
let value = sign_extend_to_long(data as u32, Size::Byte) as u32;
self.state.d_reg[reg as usize] = value;
self.set_logic_flags(value, Size::Long);
},
Instruction::MULW(src, dest, sign) => { Instruction::MULW(src, dest, sign) => {
let value = self.get_target_value(system, src, Size::Word)?; let value = self.get_target_value(system, src, Size::Word)?;
let existing = get_value_sized(self.state.d_reg[dest as usize], Size::Word); let existing = get_value_sized(self.state.d_reg[dest as usize], Size::Word);
@@ -559,7 +567,7 @@ impl M68k {
self.set_logic_flags(result, size); self.set_logic_flags(result, size);
}, },
Instruction::ORtoCCR(value) => { Instruction::ORtoCCR(value) => {
self.state.sr = self.state.sr | (value as u16); self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) | (value as u16));
}, },
Instruction::ORtoSR(value) => { Instruction::ORtoSR(value) => {
self.require_supervisor()?; self.require_supervisor()?;
@@ -611,6 +619,8 @@ impl M68k {
self.debugger.stack_tracer.pop_return(); self.debugger.stack_tracer.pop_return();
self.state.pc = self.pop_long(system)?; self.state.pc = self.pop_long(system)?;
}, },
//Instruction::RTD(i16) => {
//},
Instruction::Scc(cond, target) => { Instruction::Scc(cond, target) => {
let condition_true = self.get_current_condition(cond); let condition_true = self.get_current_condition(cond);
if condition_true { if condition_true {
@@ -624,6 +634,8 @@ impl M68k {
self.state.sr = flags; self.state.sr = flags;
self.state.status = Status::Stopped; self.state.status = Status::Stopped;
}, },
//Instruction::SBCD(Target) => {
//},
Instruction::SUB(src, dest, size) => { Instruction::SUB(src, dest, size) => {
let value = self.get_target_value(system, src, size)?; let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?; let existing = self.get_target_value(system, dest, size)?;
@@ -632,11 +644,13 @@ impl M68k {
self.set_target_value(system, dest, result, size)?; self.set_target_value(system, dest, result, size)?;
}, },
Instruction::SUBA(src, dest, size) => { Instruction::SUBA(src, dest, size) => {
let value = self.get_target_value(system, src, size)?; let value = sign_extend_to_long(self.get_target_value(system, src, size)?, size) as u32;
let existing = *self.get_a_reg_mut(dest); let existing = *self.get_a_reg_mut(dest);
let (result, carry) = overflowing_sub_sized(existing, value, size); let (result, _) = overflowing_sub_sized(existing, value, Size::Long);
*self.get_a_reg_mut(dest) = result; *self.get_a_reg_mut(dest) = result;
}, },
//Instruction::SUBX(Target) => {
//},
Instruction::SWAP(reg) => { Instruction::SWAP(reg) => {
let value = self.state.d_reg[reg as usize]; let value = self.state.d_reg[reg as usize];
self.state.d_reg[reg as usize] = ((value & 0x0000FFFF) << 16) | ((value & 0xFFFF0000) >> 16); self.state.d_reg[reg as usize] = ((value & 0x0000FFFF) << 16) | ((value & 0xFFFF0000) >> 16);
@@ -1156,6 +1170,14 @@ fn get_msb_mask(value: u32, size: Size) -> u32 {
} }
} }
fn get_bit_op_max(size: Size) -> u32 {
match size {
Size::Byte => 8,
Size::Long => 32,
Size::Word => panic!("bit ops cannot be word size"),
}
}
fn get_bit_field_mask(offset: u32, width: u32) -> u32 { fn get_bit_field_mask(offset: u32, width: u32) -> u32 {
let mut mask = 0; let mut mask = 0;
for _ in 0..width { for _ in 0..width {

View File

@@ -181,9 +181,9 @@ pub enum Instruction {
RTS, RTS,
RTD(i16), RTD(i16),
SBCD(Target, Target),
Scc(Condition, Target), Scc(Condition, Target),
STOP(u16), STOP(u16),
SBCD(Target, Target),
SUB(Target, Target, Size), SUB(Target, Target, Size),
SUBA(Target, Register, Size), SUBA(Target, Register, Size),
SUBX(Target, Target, Size), SUBX(Target, Target, Size),

View File

@@ -531,7 +531,7 @@ mod execute_tests {
use crate::devices::{Address, Addressable, Steppable, wrap_transmutable}; use crate::devices::{Address, Addressable, Steppable, wrap_transmutable};
use crate::cpus::m68k::{M68k, M68kType}; use crate::cpus::m68k::{M68k, M68kType};
use crate::cpus::m68k::instructions::{Instruction, Target, Size, Sign, ShiftDirection}; use crate::cpus::m68k::instructions::{Instruction, Target, Size, Sign, ShiftDirection, Condition};
const INIT_STACK: Address = 0x00002000; const INIT_STACK: Address = 0x00002000;
const INIT_ADDR: Address = 0x00000010; const INIT_ADDR: Address = 0x00000010;
@@ -553,6 +553,7 @@ mod execute_tests {
}; };
let mut cpu = M68k::new(cputype, 10_000_000, port); let mut cpu = M68k::new(cputype, 10_000_000, port);
cpu.step(&system).unwrap(); cpu.step(&system).unwrap();
cpu.decoder.init(cpu.state.pc);
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);
assert_eq!(cpu.decoder.instruction, Instruction::NOP); assert_eq!(cpu.decoder.instruction, Instruction::NOP);
@@ -616,6 +617,39 @@ mod execute_tests {
assert_eq!(cpu.state, expected_state); assert_eq!(cpu.state, expected_state);
} }
#[test]
fn instruction_blt() {
let (mut cpu, system) = init_test(M68kType::MC68010);
cpu.state.d_reg[0] = 0x20;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte);
cpu.execute_current(&system).unwrap();
cpu.decoder.instruction = Instruction::Bcc(Condition::LessThan, 8);
let mut expected_state = cpu.state.clone();
expected_state.pc = expected_state.pc + 8 + 2;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state, expected_state);
}
#[test]
fn instruction_blt_not() {
let (mut cpu, system) = init_test(M68kType::MC68010);
cpu.state.d_reg[0] = 0x30;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte);
cpu.execute_current(&system).unwrap();
cpu.decoder.instruction = Instruction::Bcc(Condition::LessThan, 8);
let mut expected_state = cpu.state.clone();
expected_state.pc = expected_state.pc + 8 + 2;
cpu.execute_current(&system).unwrap();
assert_ne!(cpu.state, expected_state);
}
#[test] #[test]
fn instruction_cmpi_less() { fn instruction_cmpi_less() {
let (mut cpu, system) = init_test(M68kType::MC68010); let (mut cpu, system) = init_test(M68kType::MC68010);

View File

@@ -1,4 +1,6 @@
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, Debuggable, TransmutableBox};
@@ -55,6 +57,7 @@ impl Debugger {
loop { loop {
let mut buffer = String::new(); let mut buffer = String::new();
std::io::stdout().write_all(b"> ");
std::io::stdin().read_line(&mut buffer).unwrap(); std::io::stdin().read_line(&mut buffer).unwrap();
let args: Vec<&str> = buffer.split_whitespace().collect(); let args: Vec<&str> = buffer.split_whitespace().collect();
match self.run_debugger_command(system, debug_obj, &args) { match self.run_debugger_command(system, debug_obj, &args) {
@@ -83,14 +86,14 @@ impl Debugger {
println!("Breakpoint set for {:08x}", addr); println!("Breakpoint set for {:08x}", addr);
} }
}, },
"c" | "continue" => { "r" | "remove" => {
if args.len() > 1 { if args.len() != 2 {
self.repeat = u32::from_str_radix(args[1], 10).map_err(|_| Error::new("Unable to parse repeat number"))?; println!("Usage: breakpoint <addr>");
self.last_command = Some("c".to_string()); } 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);
println!("Breakpoint removed for {:08x}", addr);
} }
system.disable_debugging();
return Ok(true);
}, },
"d" | "dump" => { "d" | "dump" => {
if args.len() > 1 { if args.len() > 1 {
@@ -104,7 +107,13 @@ impl Debugger {
"dis" | "disassemble" => { "dis" | "disassemble" => {
debug_obj.print_disassembly(0, 0); debug_obj.print_disassembly(0, 0);
}, },
"c" | "continue" => {
self.check_repeat_arg(args)?;
system.disable_debugging();
return Ok(true);
},
"s" | "step" => { "s" | "step" => {
self.check_repeat_arg(args)?;
return Ok(true); return Ok(true);
}, },
//"ds" | "stack" | "dumpstack" => { //"ds" | "stack" | "dumpstack" => {
@@ -125,5 +134,13 @@ impl Debugger {
} }
Ok(false) Ok(false)
} }
fn check_repeat_arg(&mut self, args: &[&str]) -> Result<(), Error> {
if args.len() > 1 {
self.repeat = u32::from_str_radix(args[1], 10).map_err(|_| Error::new("Unable to parse repeat number"))?;
self.last_command = Some("c".to_string());
}
Ok(())
}
} }