mirror of
https://github.com/transistorfet/moa.git
synced 2025-08-07 20:25:11 +00:00
Fixed a number of instruction bugs with m68k
This commit is contained in:
@@ -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 => {
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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),
|
||||||
|
@@ -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);
|
||||||
|
@@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user