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;
}
if (ins & 0x0100) == 0 {
Ok(Instruction::ADD(Target::Immediate(data), target, size))
if let Target::DirectAReg(reg) = target {
if (ins & 0x0100) == 0 {
Ok(Instruction::ADDA(Target::Immediate(data), reg, size))
} else {
Ok(Instruction::SUBA(Target::Immediate(data), reg, size))
}
} 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 => {

View File

@ -97,6 +97,7 @@ impl M68k {
//}
self.check_pending_interrupts(system)?;
self.check_breakpoints(system);
Ok(())
}
@ -129,7 +130,7 @@ impl M68k {
}
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;
if self.cputype >= M68kType::MC68010 {
self.push_word(system, offset)?;
@ -150,8 +151,6 @@ impl M68k {
}
pub fn decode_next(&mut self, system: &System) -> Result<(), Error> {
self.check_breakpoints(system);
self.timer.decode.start();
self.decoder.decode_at(&mut self.port, self.state.pc)?;
self.timer.decode.end();
@ -161,12 +160,15 @@ impl M68k {
}
self.state.pc = self.decoder.end;
Ok(())
}
pub fn execute_current(&mut self, system: &System) -> Result<(), Error> {
self.timer.execute.start();
match self.decoder.instruction {
//Instruction::ABCD(Target) => {
//},
Instruction::ADD(src, dest, size) => {
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
@ -175,11 +177,13 @@ impl M68k {
self.set_target_value(system, dest, result, 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 (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;
},
//Instruction::ADDX(Target) => {
//},
Instruction::AND(src, dest, size) => {
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
@ -188,7 +192,7 @@ impl M68k {
self.set_logic_flags(result, size);
},
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) => {
self.require_supervisor()?;
@ -226,32 +230,32 @@ impl M68k {
self.debugger.stack_tracer.push_return(sp);
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) => {
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 mask = self.set_bit_test_flags(value, bitnum, size);
value = (value & !mask) | (!(value & mask) & mask);
self.set_target_value(system, target, value, 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 mask = self.set_bit_test_flags(value, bitnum, size);
value = value & !mask;
self.set_target_value(system, target, value, 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 mask = self.set_bit_test_flags(value, bitnum, size);
value = value | mask;
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) => {
let (offset, width) = self.get_bit_field_args(offset, width);
let mask = get_bit_field_mask(offset, width);
@ -311,6 +315,8 @@ impl M68k {
},
//Instruction::BKPT(u8) => {
//},
//Instruction::CHK(Target, Size) => {
//},
Instruction::CLR(target, size) => {
self.set_target_value(system, target, 0, size)?;
// Clear flags except Zero flag
@ -396,18 +402,18 @@ impl M68k {
self.set_logic_flags(result, size);
},
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) => {
self.require_supervisor()?;
self.state.sr = self.state.sr ^ value;
},
//Instruction::EXG(target1, target2) => {
// let value1 = self.get_target_value(system, target1, 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, target2, value1, Size::Long)?;
//},
Instruction::EXG(target1, target2) => {
let value1 = self.get_target_value(system, target1, 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, target2, value1, Size::Long)?;
},
Instruction::EXT(reg, from_size, to_size) => {
let input = self.state.d_reg[reg as usize];
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) => {
self.require_supervisor()?;
match dir {
@ -501,14 +517,6 @@ impl M68k {
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) => {
let value = self.get_target_value(system, src, 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);
},
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) => {
self.require_supervisor()?;
@ -611,6 +619,8 @@ impl M68k {
self.debugger.stack_tracer.pop_return();
self.state.pc = self.pop_long(system)?;
},
//Instruction::RTD(i16) => {
//},
Instruction::Scc(cond, target) => {
let condition_true = self.get_current_condition(cond);
if condition_true {
@ -624,6 +634,8 @@ impl M68k {
self.state.sr = flags;
self.state.status = Status::Stopped;
},
//Instruction::SBCD(Target) => {
//},
Instruction::SUB(src, dest, size) => {
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
@ -632,11 +644,13 @@ impl M68k {
self.set_target_value(system, dest, result, 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 (result, carry) = overflowing_sub_sized(existing, value, size);
let (result, _) = overflowing_sub_sized(existing, value, Size::Long);
*self.get_a_reg_mut(dest) = result;
},
//Instruction::SUBX(Target) => {
//},
Instruction::SWAP(reg) => {
let value = self.state.d_reg[reg as usize];
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 {
let mut mask = 0;
for _ in 0..width {

View File

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

View File

@ -531,7 +531,7 @@ mod execute_tests {
use crate::devices::{Address, Addressable, Steppable, wrap_transmutable};
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_ADDR: Address = 0x00000010;
@ -553,6 +553,7 @@ mod execute_tests {
};
let mut cpu = M68k::new(cputype, 10_000_000, port);
cpu.step(&system).unwrap();
cpu.decoder.init(cpu.state.pc);
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
assert_eq!(cpu.state.msp, INIT_STACK as u32);
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
@ -616,6 +617,39 @@ mod execute_tests {
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]
fn instruction_cmpi_less() {
let (mut cpu, system) = init_test(M68kType::MC68010);

View File

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