mirror of
https://github.com/transistorfet/moa.git
synced 2024-06-09 01:29:32 +00:00
Fixed warnings
This commit is contained in:
parent
674f03c3b8
commit
a00d7b2f26
|
@ -68,7 +68,7 @@ impl Debuggable for M68k {
|
|||
decoder.dump_disassembly(&mut self.port, addr as u32, count as u32);
|
||||
}
|
||||
|
||||
fn execute_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {
|
||||
fn execute_command(&mut self, _system: &System, args: &[&str]) -> Result<bool, Error> {
|
||||
match args[0] {
|
||||
"ds" | "stack" | "dumpstack" => {
|
||||
println!("Stack:");
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
use crate::error::Error;
|
||||
use crate::system::System;
|
||||
use crate::devices::{Address, Addressable};
|
||||
|
||||
use super::state::{M68kType, Exceptions};
|
||||
|
|
|
@ -62,7 +62,7 @@ impl M68k {
|
|||
|
||||
pub fn step_internal(&mut self, system: &System) -> Result<(), Error> {
|
||||
match self.state.status {
|
||||
Status::Init => self.init(system),
|
||||
Status::Init => self.init(),
|
||||
Status::Stopped => Err(Error::new("CPU stopped")),
|
||||
Status::Running => {
|
||||
match self.cycle_one(system) {
|
||||
|
@ -70,7 +70,7 @@ impl M68k {
|
|||
//Err(Error { err: ErrorType::Processor, native, .. }) => {
|
||||
// TODO match arm conditional is temporary: illegal instructions generate a top level error in order to debug and fix issues with decode
|
||||
Err(Error { err: ErrorType::Processor, native, .. }) if native != Exceptions::IllegalInstruction as u32 => {
|
||||
self.exception(system, native as u8, false)?;
|
||||
self.exception(native as u8, false)?;
|
||||
Ok(())
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
|
@ -79,7 +79,7 @@ impl M68k {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self, system: &System) -> Result<(), Error> {
|
||||
pub fn init(&mut self) -> Result<(), Error> {
|
||||
self.state.msp = self.port.read_beu32(0)?;
|
||||
self.state.pc = self.port.read_beu32(4)?;
|
||||
self.state.status = Status::Running;
|
||||
|
@ -88,8 +88,8 @@ impl M68k {
|
|||
|
||||
pub fn cycle_one(&mut self, system: &System) -> Result<(), Error> {
|
||||
self.timer.cycle.start();
|
||||
self.decode_next(system)?;
|
||||
self.execute_current(system)?;
|
||||
self.decode_next()?;
|
||||
self.execute_current()?;
|
||||
self.timer.cycle.end();
|
||||
|
||||
//if (self.timer.cycle.events % 500) == 0 {
|
||||
|
@ -117,7 +117,7 @@ impl M68k {
|
|||
debug!("{} interrupt: {} {}", DEV_NAME, pending_ipl, priority_mask);
|
||||
self.state.current_ipl = self.state.pending_ipl;
|
||||
let ack_num = system.get_interrupt_controller().acknowledge(self.state.current_ipl as u8)?;
|
||||
self.exception(system, ack_num, true)?;
|
||||
self.exception(ack_num, true)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
@ -129,14 +129,14 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn exception(&mut self, system: &System, number: u8, is_interrupt: bool) -> Result<(), Error> {
|
||||
pub fn exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), Error> {
|
||||
debug!("{}: raising exception {}", DEV_NAME, number);
|
||||
let offset = (number as u16) << 2;
|
||||
if self.cputype >= M68kType::MC68010 {
|
||||
self.push_word(system, offset)?;
|
||||
self.push_word(offset)?;
|
||||
}
|
||||
self.push_long(system, self.state.pc)?;
|
||||
self.push_word(system, self.state.sr)?;
|
||||
self.push_long(self.state.pc)?;
|
||||
self.push_word(self.state.sr)?;
|
||||
|
||||
// Changes to the flags must happen after the previous value has been pushed to the stack
|
||||
self.set_flag(Flags::Supervisor, true);
|
||||
|
@ -150,7 +150,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_next(&mut self, system: &System) -> Result<(), Error> {
|
||||
pub fn decode_next(&mut self) -> Result<(), Error> {
|
||||
self.timer.decode.start();
|
||||
self.decoder.decode_at(&mut self.port, self.state.pc)?;
|
||||
self.timer.decode.end();
|
||||
|
@ -164,22 +164,22 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute_current(&mut self, system: &System) -> Result<(), Error> {
|
||||
pub fn execute_current(&mut self) -> 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)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
let existing = self.get_target_value(dest, size)?;
|
||||
let (result, carry) = overflowing_add_sized(existing, value, size);
|
||||
let overflow = get_add_overflow(existing, value, result, size);
|
||||
self.set_compare_flags(result, size, carry, overflow);
|
||||
self.set_flag(Flags::Extend, carry);
|
||||
self.set_target_value(system, dest, result, size)?;
|
||||
self.set_target_value(dest, result, size)?;
|
||||
},
|
||||
Instruction::ADDA(src, dest, size) => {
|
||||
let value = sign_extend_to_long(self.get_target_value(system, src, size)?, size) as u32;
|
||||
let value = sign_extend_to_long(self.get_target_value(src, size)?, size) as u32;
|
||||
let existing = *self.get_a_reg_mut(dest);
|
||||
let (result, _) = overflowing_add_sized(existing, value, Size::Long);
|
||||
*self.get_a_reg_mut(dest) = result;
|
||||
|
@ -187,10 +187,10 @@ impl M68k {
|
|||
//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)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
let existing = self.get_target_value(dest, size)?;
|
||||
let result = get_value_sized(existing & value, size);
|
||||
self.set_target_value(system, dest, result, size)?;
|
||||
self.set_target_value(dest, result, size)?;
|
||||
self.set_logic_flags(result, size);
|
||||
},
|
||||
Instruction::ANDtoCCR(value) => {
|
||||
|
@ -201,8 +201,8 @@ impl M68k {
|
|||
self.state.sr = self.state.sr & value;
|
||||
},
|
||||
Instruction::ASd(count, target, size, shift_dir) => {
|
||||
let count = self.get_target_value(system, count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(system, target, size)?, false);
|
||||
let count = self.get_target_value(count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size)?, false);
|
||||
let original = pair.0;
|
||||
for _ in 0..count {
|
||||
pair = shift_operation(pair.0, size, shift_dir, true);
|
||||
|
@ -215,7 +215,7 @@ impl M68k {
|
|||
if get_msb(pair.0, size) != get_msb(original, size) {
|
||||
self.set_flag(Flags::Overflow, true);
|
||||
}
|
||||
self.set_target_value(system, target, pair.0, size)?;
|
||||
self.set_target_value(target, pair.0, size)?;
|
||||
},
|
||||
Instruction::Bcc(cond, offset) => {
|
||||
let should_branch = self.get_current_condition(cond);
|
||||
|
@ -227,57 +227,57 @@ impl M68k {
|
|||
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
|
||||
},
|
||||
Instruction::BSR(offset) => {
|
||||
self.push_long(system, self.state.pc)?;
|
||||
self.push_long(self.state.pc)?;
|
||||
let sp = *self.get_stack_pointer_mut();
|
||||
self.debugger.stack_tracer.push_return(sp);
|
||||
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
|
||||
},
|
||||
Instruction::BCHG(bitnum, target, size) => {
|
||||
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
|
||||
let mut value = self.get_target_value(system, target, size)?;
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte)?;
|
||||
let mut value = self.get_target_value(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)?;
|
||||
self.set_target_value(target, value, size)?;
|
||||
},
|
||||
Instruction::BCLR(bitnum, target, size) => {
|
||||
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
|
||||
let mut value = self.get_target_value(system, target, size)?;
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte)?;
|
||||
let mut value = self.get_target_value(target, size)?;
|
||||
let mask = self.set_bit_test_flags(value, bitnum, size);
|
||||
value = value & !mask;
|
||||
self.set_target_value(system, target, value, size)?;
|
||||
self.set_target_value(target, value, size)?;
|
||||
},
|
||||
Instruction::BSET(bitnum, target, size) => {
|
||||
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
|
||||
let mut value = self.get_target_value(system, target, size)?;
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte)?;
|
||||
let mut value = self.get_target_value(target, size)?;
|
||||
let mask = self.set_bit_test_flags(value, bitnum, size);
|
||||
value = value | mask;
|
||||
self.set_target_value(system, target, value, size)?;
|
||||
self.set_target_value(target, value, size)?;
|
||||
},
|
||||
Instruction::BTST(bitnum, target, size) => {
|
||||
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
|
||||
let value = self.get_target_value(system, target, size)?;
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte)?;
|
||||
let value = self.get_target_value(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);
|
||||
let value = self.get_target_value(system, target, Size::Long)?;
|
||||
let value = self.get_target_value(target, Size::Long)?;
|
||||
let field = value & mask;
|
||||
self.set_bit_field_test_flags(field, get_bit_field_msb(offset));
|
||||
self.set_target_value(system, target, (value & !mask) | (!field & mask), Size::Long)?;
|
||||
self.set_target_value(target, (value & !mask) | (!field & mask), Size::Long)?;
|
||||
},
|
||||
Instruction::BFCLR(target, offset, width) => {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(system, target, Size::Long)?;
|
||||
let value = self.get_target_value(target, Size::Long)?;
|
||||
let field = value & mask;
|
||||
self.set_bit_field_test_flags(field, get_bit_field_msb(offset));
|
||||
self.set_target_value(system, target, value & !mask, Size::Long)?;
|
||||
self.set_target_value(target, value & !mask, Size::Long)?;
|
||||
},
|
||||
Instruction::BFEXTS(target, offset, width, reg) => {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(system, target, Size::Long)?;
|
||||
let value = self.get_target_value(target, Size::Long)?;
|
||||
let field = value & mask;
|
||||
self.set_bit_field_test_flags(field, get_bit_field_msb(offset));
|
||||
|
||||
|
@ -291,7 +291,7 @@ impl M68k {
|
|||
Instruction::BFEXTU(target, offset, width, reg) => {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(system, target, Size::Long)?;
|
||||
let value = self.get_target_value(target, Size::Long)?;
|
||||
let field = value & mask;
|
||||
self.set_bit_field_test_flags(field, get_bit_field_msb(offset));
|
||||
self.state.d_reg[reg as usize] = field >> (32 - offset - width);
|
||||
|
@ -303,15 +303,15 @@ impl M68k {
|
|||
Instruction::BFSET(target, offset, width) => {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(system, target, Size::Long)?;
|
||||
let value = self.get_target_value(target, Size::Long)?;
|
||||
let field = value & mask;
|
||||
self.set_bit_field_test_flags(field, get_bit_field_msb(offset));
|
||||
self.set_target_value(system, target, value | mask, Size::Long)?;
|
||||
self.set_target_value(target, value | mask, Size::Long)?;
|
||||
},
|
||||
Instruction::BFTST(target, offset, width) => {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(system, target, Size::Long)?;
|
||||
let value = self.get_target_value(target, Size::Long)?;
|
||||
let field = value & mask;
|
||||
self.set_bit_field_test_flags(field, get_bit_field_msb(offset));
|
||||
},
|
||||
|
@ -320,19 +320,19 @@ impl M68k {
|
|||
//Instruction::CHK(Target, Size) => {
|
||||
//},
|
||||
Instruction::CLR(target, size) => {
|
||||
self.set_target_value(system, target, 0, size)?;
|
||||
self.set_target_value(target, 0, size)?;
|
||||
// Clear flags except Zero flag
|
||||
self.state.sr = (self.state.sr & 0xFFF0) | (Flags::Zero as u16);
|
||||
},
|
||||
Instruction::CMP(src, dest, size) => {
|
||||
let value = self.get_target_value(system, src, size)?;
|
||||
let existing = self.get_target_value(system, dest, size)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
let existing = self.get_target_value(dest, size)?;
|
||||
let (result, carry) = overflowing_sub_sized(existing, value, size);
|
||||
let overflow = get_sub_overflow(existing, value, result, size);
|
||||
self.set_compare_flags(result, size, carry, overflow);
|
||||
},
|
||||
Instruction::CMPA(src, reg, size) => {
|
||||
let value = sign_extend_to_long(self.get_target_value(system, src, size)?, size) as u32;
|
||||
let value = sign_extend_to_long(self.get_target_value(src, size)?, size) as u32;
|
||||
let existing = *self.get_a_reg_mut(reg);
|
||||
let (result, carry) = overflowing_sub_sized(existing, value, Size::Long);
|
||||
let overflow = get_sub_overflow(existing, value, result, size);
|
||||
|
@ -349,9 +349,9 @@ impl M68k {
|
|||
}
|
||||
},
|
||||
Instruction::DIVW(src, dest, sign) => {
|
||||
let value = self.get_target_value(system, src, Size::Word)?;
|
||||
let value = self.get_target_value(src, Size::Word)?;
|
||||
if value == 0 {
|
||||
self.exception(system, Exceptions::ZeroDivide as u8, false)?;
|
||||
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -368,9 +368,9 @@ impl M68k {
|
|||
self.state.d_reg[dest as usize] = (remainder << 16) | (0xFFFF & quotient);
|
||||
},
|
||||
Instruction::DIVL(src, dest_h, dest_l, sign) => {
|
||||
let value = self.get_target_value(system, src, Size::Long)?;
|
||||
let value = self.get_target_value(src, Size::Long)?;
|
||||
if value == 0 {
|
||||
self.exception(system, Exceptions::ZeroDivide as u8, false)?;
|
||||
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -399,10 +399,10 @@ impl M68k {
|
|||
self.state.d_reg[dest_l as usize] = quotient as u32;
|
||||
},
|
||||
Instruction::EOR(src, dest, size) => {
|
||||
let value = self.get_target_value(system, src, size)?;
|
||||
let existing = self.get_target_value(system, dest, size)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
let existing = self.get_target_value(dest, size)?;
|
||||
let result = get_value_sized(existing ^ value, size);
|
||||
self.set_target_value(system, dest, result, size)?;
|
||||
self.set_target_value(dest, result, size)?;
|
||||
self.set_logic_flags(result, size);
|
||||
},
|
||||
Instruction::EORtoCCR(value) => {
|
||||
|
@ -413,10 +413,10 @@ impl M68k {
|
|||
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)?;
|
||||
let value1 = self.get_target_value(target1, Size::Long)?;
|
||||
let value2 = self.get_target_value(target2, Size::Long)?;
|
||||
self.set_target_value(target1, value2, Size::Long)?;
|
||||
self.set_target_value(target2, value1, Size::Long)?;
|
||||
},
|
||||
Instruction::EXT(reg, from_size, to_size) => {
|
||||
let input = get_value_sized(self.state.d_reg[reg as usize], from_size);
|
||||
|
@ -432,30 +432,30 @@ impl M68k {
|
|||
//Instruction::ILLEGAL => {
|
||||
//},
|
||||
Instruction::JMP(target) => {
|
||||
self.state.pc = self.get_target_address(system, target)?;
|
||||
self.state.pc = self.get_target_address(target)?;
|
||||
},
|
||||
Instruction::JSR(target) => {
|
||||
self.push_long(system, self.state.pc)?;
|
||||
self.push_long(self.state.pc)?;
|
||||
let sp = *self.get_stack_pointer_mut();
|
||||
self.debugger.stack_tracer.push_return(sp);
|
||||
self.state.pc = self.get_target_address(system, target)?;
|
||||
self.state.pc = self.get_target_address(target)?;
|
||||
},
|
||||
Instruction::LEA(target, reg) => {
|
||||
let value = self.get_target_address(system, target)?;
|
||||
let value = self.get_target_address(target)?;
|
||||
let addr = self.get_a_reg_mut(reg);
|
||||
*addr = value;
|
||||
},
|
||||
Instruction::LINK(reg, offset) => {
|
||||
let value = *self.get_a_reg_mut(reg);
|
||||
self.push_long(system, value)?;
|
||||
self.push_long(value)?;
|
||||
let sp = *self.get_stack_pointer_mut();
|
||||
let addr = self.get_a_reg_mut(reg);
|
||||
*addr = sp;
|
||||
*self.get_stack_pointer_mut() = sp.wrapping_add((offset as i32) as u32);
|
||||
},
|
||||
Instruction::LSd(count, target, size, shift_dir) => {
|
||||
let count = self.get_target_value(system, count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(system, target, size)?, false);
|
||||
let count = self.get_target_value(count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size)?, false);
|
||||
for _ in 0..count {
|
||||
pair = shift_operation(pair.0, size, shift_dir, false);
|
||||
}
|
||||
|
@ -464,48 +464,48 @@ impl M68k {
|
|||
self.set_flag(Flags::Carry, true);
|
||||
self.set_flag(Flags::Extend, true);
|
||||
}
|
||||
self.set_target_value(system, target, pair.0, size)?;
|
||||
self.set_target_value(target, pair.0, size)?;
|
||||
},
|
||||
Instruction::MOVE(src, dest, size) => {
|
||||
let value = self.get_target_value(system, src, size)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
self.set_logic_flags(value, size);
|
||||
self.set_target_value(system, dest, value, size)?;
|
||||
self.set_target_value(dest, value, size)?;
|
||||
},
|
||||
Instruction::MOVEA(src, reg, size) => {
|
||||
let value = self.get_target_value(system, src, size)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
let value = sign_extend_to_long(value, size) as u32;
|
||||
let addr = self.get_a_reg_mut(reg);
|
||||
*addr = value;
|
||||
},
|
||||
Instruction::MOVEfromSR(target) => {
|
||||
self.require_supervisor()?;
|
||||
self.set_target_value(system, target, self.state.sr as u32, Size::Word)?;
|
||||
self.set_target_value(target, self.state.sr as u32, Size::Word)?;
|
||||
},
|
||||
Instruction::MOVEtoSR(target) => {
|
||||
self.require_supervisor()?;
|
||||
self.state.sr = self.get_target_value(system, target, Size::Word)? as u16;
|
||||
self.state.sr = self.get_target_value(target, Size::Word)? as u16;
|
||||
},
|
||||
Instruction::MOVEtoCCR(target) => {
|
||||
let value = self.get_target_value(system, target, Size::Word)? as u16;
|
||||
let value = self.get_target_value(target, Size::Word)? as u16;
|
||||
self.state.sr = (self.state.sr & 0xFF00) | (value & 0x00FF);
|
||||
},
|
||||
Instruction::MOVEC(target, control_reg, dir) => {
|
||||
self.require_supervisor()?;
|
||||
match dir {
|
||||
Direction::FromTarget => {
|
||||
let value = self.get_target_value(system, target, Size::Long)?;
|
||||
let value = self.get_target_value(target, Size::Long)?;
|
||||
let addr = self.get_control_reg_mut(control_reg);
|
||||
*addr = value;
|
||||
},
|
||||
Direction::ToTarget => {
|
||||
let addr = self.get_control_reg_mut(control_reg);
|
||||
let value = *addr;
|
||||
self.set_target_value(system, target, value, Size::Long)?;
|
||||
self.set_target_value(target, value, Size::Long)?;
|
||||
},
|
||||
}
|
||||
},
|
||||
Instruction::MOVEM(target, size, dir, mask) => {
|
||||
self.execute_movem(system, target, size, dir, mask)?;
|
||||
self.execute_movem(target, size, dir, mask)?;
|
||||
},
|
||||
//Instruction::MOVEP(reg, target, size, dir) => {
|
||||
//},
|
||||
|
@ -517,12 +517,12 @@ impl M68k {
|
|||
Instruction::MOVEUSP(target, dir) => {
|
||||
self.require_supervisor()?;
|
||||
match dir {
|
||||
Direction::ToTarget => self.set_target_value(system, target, self.state.usp, Size::Long)?,
|
||||
Direction::FromTarget => { self.state.usp = self.get_target_value(system, target, Size::Long)?; },
|
||||
Direction::ToTarget => self.set_target_value(target, self.state.usp, Size::Long)?,
|
||||
Direction::FromTarget => { self.state.usp = self.get_target_value(target, Size::Long)?; },
|
||||
}
|
||||
},
|
||||
Instruction::MULW(src, dest, sign) => {
|
||||
let value = self.get_target_value(system, src, Size::Word)?;
|
||||
let value = self.get_target_value(src, Size::Word)?;
|
||||
let existing = get_value_sized(self.state.d_reg[dest as usize], Size::Word);
|
||||
let result = match sign {
|
||||
Sign::Signed => ((((existing as u16) as i16) as i64) * (((value as u16) as i16) as i64)) as u64,
|
||||
|
@ -533,7 +533,7 @@ impl M68k {
|
|||
self.state.d_reg[dest as usize] = result as u32;
|
||||
},
|
||||
Instruction::MULL(src, dest_h, dest_l, sign) => {
|
||||
let value = self.get_target_value(system, src, Size::Long)?;
|
||||
let value = self.get_target_value(src, Size::Long)?;
|
||||
let existing = get_value_sized(self.state.d_reg[dest_l as usize], Size::Long);
|
||||
let result = match sign {
|
||||
Sign::Signed => (((existing as i32) as i64) * ((value as i32) as i64)) as u64,
|
||||
|
@ -549,10 +549,10 @@ impl M68k {
|
|||
//Instruction::NBCD(Target) => {
|
||||
//},
|
||||
Instruction::NEG(target, size) => {
|
||||
let original = self.get_target_value(system, target, size)?;
|
||||
let original = self.get_target_value(target, size)?;
|
||||
let (result, overflow) = overflowing_sub_signed_sized(0, original, size);
|
||||
let carry = result != 0;
|
||||
self.set_target_value(system, target, result, size)?;
|
||||
self.set_target_value(target, result, size)?;
|
||||
self.set_compare_flags(result, size, carry, overflow);
|
||||
self.set_flag(Flags::Extend, carry);
|
||||
},
|
||||
|
@ -560,16 +560,16 @@ impl M68k {
|
|||
//},
|
||||
Instruction::NOP => { },
|
||||
Instruction::NOT(target, size) => {
|
||||
let mut value = self.get_target_value(system, target, size)?;
|
||||
let mut value = self.get_target_value(target, size)?;
|
||||
value = get_value_sized(!value, size);
|
||||
self.set_target_value(system, target, value, size)?;
|
||||
self.set_target_value(target, value, size)?;
|
||||
self.set_logic_flags(value, size);
|
||||
},
|
||||
Instruction::OR(src, dest, size) => {
|
||||
let value = self.get_target_value(system, src, size)?;
|
||||
let existing = self.get_target_value(system, dest, size)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
let existing = self.get_target_value(dest, size)?;
|
||||
let result = get_value_sized(existing | value, size);
|
||||
self.set_target_value(system, dest, result, size)?;
|
||||
self.set_target_value(dest, result, size)?;
|
||||
self.set_logic_flags(result, size);
|
||||
},
|
||||
Instruction::ORtoCCR(value) => {
|
||||
|
@ -580,15 +580,15 @@ impl M68k {
|
|||
self.state.sr = self.state.sr | value;
|
||||
},
|
||||
Instruction::PEA(target) => {
|
||||
let value = self.get_target_address(system, target)?;
|
||||
self.push_long(system, value)?;
|
||||
let value = self.get_target_address(target)?;
|
||||
self.push_long(value)?;
|
||||
},
|
||||
//Instruction::RESET => {
|
||||
// self.require_supervisor()?;
|
||||
//},
|
||||
Instruction::ROd(count, target, size, shift_dir) => {
|
||||
let count = self.get_target_value(system, count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(system, target, size)?, false);
|
||||
let count = self.get_target_value(count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size)?, false);
|
||||
for _ in 0..count {
|
||||
pair = rotate_operation(pair.0, size, shift_dir, None);
|
||||
}
|
||||
|
@ -596,11 +596,11 @@ impl M68k {
|
|||
if pair.1 {
|
||||
self.set_flag(Flags::Carry, true);
|
||||
}
|
||||
self.set_target_value(system, target, pair.0, size)?;
|
||||
self.set_target_value(target, pair.0, size)?;
|
||||
},
|
||||
Instruction::ROXd(count, target, size, shift_dir) => {
|
||||
let count = self.get_target_value(system, count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(system, target, size)?, false);
|
||||
let count = self.get_target_value(count, size)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size)?, false);
|
||||
for _ in 0..count {
|
||||
pair = rotate_operation(pair.0, size, shift_dir, Some(self.get_flag(Flags::Extend)));
|
||||
self.set_flag(Flags::Extend, pair.1);
|
||||
|
@ -609,30 +609,30 @@ impl M68k {
|
|||
if pair.1 {
|
||||
self.set_flag(Flags::Carry, true);
|
||||
}
|
||||
self.set_target_value(system, target, pair.0, size)?;
|
||||
self.set_target_value(target, pair.0, size)?;
|
||||
},
|
||||
Instruction::RTE => {
|
||||
self.require_supervisor()?;
|
||||
self.state.sr = self.pop_word(system)?;
|
||||
self.state.pc = self.pop_long(system)?;
|
||||
self.state.sr = self.pop_word()?;
|
||||
self.state.pc = self.pop_long()?;
|
||||
if self.cputype >= M68kType::MC68010 {
|
||||
let _ = self.pop_word(system)?;
|
||||
let _ = self.pop_word()?;
|
||||
}
|
||||
},
|
||||
//Instruction::RTR => {
|
||||
//},
|
||||
Instruction::RTS => {
|
||||
self.debugger.stack_tracer.pop_return();
|
||||
self.state.pc = self.pop_long(system)?;
|
||||
self.state.pc = self.pop_long()?;
|
||||
},
|
||||
//Instruction::RTD(i16) => {
|
||||
//},
|
||||
Instruction::Scc(cond, target) => {
|
||||
let condition_true = self.get_current_condition(cond);
|
||||
if condition_true {
|
||||
self.set_target_value(system, target, 0xFF, Size::Byte)?;
|
||||
self.set_target_value(target, 0xFF, Size::Byte)?;
|
||||
} else {
|
||||
self.set_target_value(system, target, 0x00, Size::Byte)?;
|
||||
self.set_target_value(target, 0x00, Size::Byte)?;
|
||||
}
|
||||
},
|
||||
Instruction::STOP(flags) => {
|
||||
|
@ -643,16 +643,16 @@ impl M68k {
|
|||
//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)?;
|
||||
let value = self.get_target_value(src, size)?;
|
||||
let existing = self.get_target_value(dest, size)?;
|
||||
let (result, carry) = overflowing_sub_sized(existing, value, size);
|
||||
let overflow = get_sub_overflow(existing, value, result, size);
|
||||
self.set_compare_flags(result, size, carry, overflow);
|
||||
self.set_flag(Flags::Extend, carry);
|
||||
self.set_target_value(system, dest, result, size)?;
|
||||
self.set_target_value(dest, result, size)?;
|
||||
},
|
||||
Instruction::SUBA(src, dest, size) => {
|
||||
let value = sign_extend_to_long(self.get_target_value(system, src, size)?, size) as u32;
|
||||
let value = sign_extend_to_long(self.get_target_value(src, size)?, size) as u32;
|
||||
let existing = *self.get_a_reg_mut(dest);
|
||||
let (result, _) = overflowing_sub_sized(existing, value, Size::Long);
|
||||
*self.get_a_reg_mut(dest) = result;
|
||||
|
@ -666,21 +666,21 @@ impl M68k {
|
|||
//Instruction::TAS(Target) => {
|
||||
//},
|
||||
Instruction::TST(target, size) => {
|
||||
let value = self.get_target_value(system, target, size)?;
|
||||
let value = self.get_target_value(target, size)?;
|
||||
self.set_logic_flags(value, size);
|
||||
},
|
||||
Instruction::TRAP(number) => {
|
||||
self.exception(system, 32 + number, false)?;
|
||||
self.exception(32 + number, false)?;
|
||||
},
|
||||
Instruction::TRAPV => {
|
||||
if self.get_flag(Flags::Overflow) {
|
||||
self.exception(system, Exceptions::TrapvInstruction as u8, false)?;
|
||||
self.exception(Exceptions::TrapvInstruction as u8, false)?;
|
||||
}
|
||||
},
|
||||
Instruction::UNLK(reg) => {
|
||||
let value = *self.get_a_reg_mut(reg);
|
||||
*self.get_stack_pointer_mut() = value;
|
||||
let new_value = self.pop_long(system)?;
|
||||
let new_value = self.pop_long()?;
|
||||
let addr = self.get_a_reg_mut(reg);
|
||||
*addr = new_value;
|
||||
},
|
||||
|
@ -691,8 +691,8 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_movem(&mut self, system: &System, target: Target, size: Size, dir: Direction, mut mask: u16) -> Result<(), Error> {
|
||||
let mut addr = self.get_target_address(system, target)?;
|
||||
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 {
|
||||
|
@ -751,33 +751,33 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn push_word(&mut self, system: &System, value: u16) -> Result<(), Error> {
|
||||
fn push_word(&mut self, value: u16) -> Result<(), Error> {
|
||||
*self.get_stack_pointer_mut() -= 2;
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
self.port.write_beu16(addr as Address, value)
|
||||
}
|
||||
|
||||
fn pop_word(&mut self, system: &System) -> Result<u16, Error> {
|
||||
fn pop_word(&mut self) -> Result<u16, Error> {
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
let value = self.port.read_beu16(addr as Address)?;
|
||||
*self.get_stack_pointer_mut() += 2;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn push_long(&mut self, system: &System, value: u32) -> Result<(), Error> {
|
||||
fn push_long(&mut self, value: u32) -> Result<(), Error> {
|
||||
*self.get_stack_pointer_mut() -= 4;
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
self.port.write_beu32(addr as Address, value)
|
||||
}
|
||||
|
||||
fn pop_long(&mut self, system: &System) -> Result<u32, Error> {
|
||||
fn pop_long(&mut self) -> Result<u32, Error> {
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
let value = self.port.read_beu32(addr as Address)?;
|
||||
*self.get_stack_pointer_mut() += 4;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn get_target_value(&mut self, system: &System, target: Target, size: Size) -> Result<u32, Error> {
|
||||
pub fn get_target_value(&mut self, target: Target, size: Size) -> Result<u32, Error> {
|
||||
match target {
|
||||
Target::Immediate(value) => Ok(value),
|
||||
Target::DirectDReg(reg) => Ok(get_value_sized(self.state.d_reg[reg as usize], size)),
|
||||
|
@ -820,7 +820,7 @@ impl M68k {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_target_value(&mut self, system: &System, target: Target, value: u32, size: Size) -> Result<(), Error> {
|
||||
pub fn set_target_value(&mut self, target: Target, value: u32, size: Size) -> Result<(), Error> {
|
||||
match target {
|
||||
Target::DirectDReg(reg) => {
|
||||
set_value_sized(&mut self.state.d_reg[reg as usize], value, size);
|
||||
|
@ -869,7 +869,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_target_address(&mut self, system: &System, target: Target) -> Result<u32, Error> {
|
||||
pub fn get_target_address(&mut self, target: Target) -> Result<u32, Error> {
|
||||
let addr = match target {
|
||||
Target::IndirectAReg(reg) | Target::IndirectARegInc(reg) | Target::IndirectARegDec(reg) => *self.get_a_reg_mut(reg),
|
||||
Target::IndirectRegOffset(base_reg, index_reg, displacement) => {
|
||||
|
@ -1187,10 +1187,6 @@ fn get_sub_overflow(operand1: u32, operand2: u32, result: u32, size: Size) -> bo
|
|||
(msb1 && msb2 && !msb_res) || (!msb1 && !msb2 && msb_res)
|
||||
}
|
||||
|
||||
fn get_twos_complement(value: u32, size: Size) -> u32 {
|
||||
get_value_sized(!value + 1, size)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_msb(value: u32, size: Size) -> bool {
|
||||
match size {
|
||||
|
|
|
@ -148,7 +148,7 @@ impl M68k {
|
|||
self.debugger = M68kDebugger::new();
|
||||
}
|
||||
|
||||
pub fn dump_state(&mut self, system: &System) {
|
||||
pub fn dump_state(&mut self, _system: &System) {
|
||||
println!("Status: {:?}", self.state.status);
|
||||
println!("PC: {:#010x}", self.state.pc);
|
||||
println!("SR: {:#06x}", self.state.sr);
|
||||
|
|
|
@ -70,7 +70,7 @@ mod decode_tests {
|
|||
BusPort::new(0, 24, 16, system.bus.clone())
|
||||
};
|
||||
let mut cpu = M68k::new(cputype, 10_000_000, port);
|
||||
cpu.init(&system).unwrap();
|
||||
cpu.init().unwrap();
|
||||
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
|
||||
assert_eq!(cpu.state.msp, INIT_STACK as u32);
|
||||
|
||||
|
@ -93,11 +93,11 @@ mod decode_tests {
|
|||
load_memory(&system, case.data);
|
||||
match &case.ins {
|
||||
Some(ins) => {
|
||||
cpu.decode_next(&system).unwrap();
|
||||
cpu.decode_next().unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, ins.clone());
|
||||
},
|
||||
None => {
|
||||
assert_eq!(cpu.decode_next(&system).is_err(), true);
|
||||
assert_eq!(cpu.decode_next().is_err(), true);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,6 @@ mod decode_tests {
|
|||
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Word;
|
||||
let expected = 0x1234;
|
||||
|
||||
let target = cpu.decoder.get_mode_as_target(&mut cpu.port, 0b000, 0b001, Some(size)).unwrap();
|
||||
assert_eq!(target, Target::DirectDReg(1));
|
||||
|
@ -130,7 +129,6 @@ mod decode_tests {
|
|||
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Word;
|
||||
let expected = 0x1234;
|
||||
|
||||
let target = cpu.decoder.get_mode_as_target(&mut cpu.port, 0b001, 0b010, Some(size)).unwrap();
|
||||
assert_eq!(target, Target::DirectAReg(2));
|
||||
|
@ -141,7 +139,6 @@ mod decode_tests {
|
|||
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Long;
|
||||
let expected_addr = INIT_ADDR;
|
||||
let expected = 0x12345678;
|
||||
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
|
@ -155,7 +152,6 @@ mod decode_tests {
|
|||
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Long;
|
||||
let expected_addr = INIT_ADDR;
|
||||
let expected = 0x12345678;
|
||||
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
|
@ -169,7 +165,6 @@ mod decode_tests {
|
|||
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Long;
|
||||
let expected_addr = INIT_ADDR + 4;
|
||||
let expected = 0x12345678;
|
||||
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
|
@ -433,15 +428,15 @@ mod execute_tests {
|
|||
let (mut cpu, system) = init_execute_test(case.cputype);
|
||||
|
||||
let init_state = build_state(&case.init);
|
||||
let mut expected_state = build_state(&case.fini);
|
||||
let expected_state = build_state(&case.fini);
|
||||
|
||||
load_memory(&system, case.data);
|
||||
cpu.state = init_state;
|
||||
|
||||
cpu.decode_next(&system).unwrap();
|
||||
cpu.decode_next().unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, case.ins);
|
||||
|
||||
cpu.execute_current(&system).unwrap();
|
||||
cpu.execute_current().unwrap();
|
||||
assert_eq!(cpu.state, expected_state);
|
||||
}
|
||||
|
||||
|
@ -709,73 +704,70 @@ mod execute_tests {
|
|||
|
||||
#[test]
|
||||
fn target_value_direct_d() {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010);
|
||||
let (mut cpu, _) = init_execute_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Word;
|
||||
let expected = 0x1234;
|
||||
let target = Target::DirectDReg(1);
|
||||
|
||||
cpu.state.d_reg[1] = expected;
|
||||
let result = cpu.get_target_value(&system, target, size).unwrap();
|
||||
let result = cpu.get_target_value(target, size).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_value_direct_a() {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010);
|
||||
let (mut cpu, _) = init_execute_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Word;
|
||||
let expected = 0x1234;
|
||||
let target = Target::DirectAReg(2);
|
||||
|
||||
cpu.state.a_reg[2] = expected;
|
||||
let result = cpu.get_target_value(&system, target, size).unwrap();
|
||||
let result = cpu.get_target_value(target, size).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_value_indirect_a() {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010);
|
||||
let (mut cpu, _) = init_execute_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Long;
|
||||
let expected_addr = INIT_ADDR;
|
||||
let expected = 0x12345678;
|
||||
let target = Target::IndirectAReg(2);
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
cpu.port.write_beu32(INIT_ADDR, expected).unwrap();
|
||||
|
||||
cpu.state.a_reg[2] = INIT_ADDR as u32;
|
||||
let result = cpu.get_target_value(&system, target, size).unwrap();
|
||||
let result = cpu.get_target_value(target, size).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_value_indirect_a_inc() {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010);
|
||||
let (mut cpu, _) = init_execute_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Long;
|
||||
let expected_addr = INIT_ADDR;
|
||||
let expected = 0x12345678;
|
||||
let target = Target::IndirectARegInc(2);
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
cpu.port.write_beu32(INIT_ADDR, expected).unwrap();
|
||||
|
||||
cpu.state.a_reg[2] = INIT_ADDR as u32;
|
||||
let result = cpu.get_target_value(&system, target, size).unwrap();
|
||||
let result = cpu.get_target_value(target, size).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
assert_eq!(cpu.state.a_reg[2], (INIT_ADDR as u32) + 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_value_indirect_a_dec() {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010);
|
||||
let (mut cpu, _) = init_execute_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Long;
|
||||
let expected_addr = INIT_ADDR + 4;
|
||||
let expected = 0x12345678;
|
||||
let target = Target::IndirectARegDec(2);
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
cpu.port.write_beu32(INIT_ADDR, expected).unwrap();
|
||||
|
||||
cpu.state.a_reg[2] = (INIT_ADDR as u32) + 4;
|
||||
let result = cpu.get_target_value(&system, target, size).unwrap();
|
||||
let result = cpu.get_target_value(target, size).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
assert_eq!(cpu.state.a_reg[2], INIT_ADDR as u32);
|
||||
}
|
||||
|
@ -783,14 +775,14 @@ mod execute_tests {
|
|||
|
||||
#[test]
|
||||
fn target_value_immediate() {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010);
|
||||
let (mut cpu, _) = init_execute_test(M68kType::MC68010);
|
||||
|
||||
let size = Size::Word;
|
||||
let expected = 0x1234;
|
||||
|
||||
let target = Target::Immediate(expected);
|
||||
|
||||
let result = cpu.get_target_value(&system, target, size).unwrap();
|
||||
let result = cpu.get_target_value(target, size).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ impl Debuggable for Z80 {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_current_step(&mut self, system: &System) -> Result<(), Error> {
|
||||
fn print_current_step(&mut self, _system: &System) -> Result<(), Error> {
|
||||
self.decoder.decode_at(&mut self.port, self.state.pc)?;
|
||||
self.decoder.dump_decoded(&mut self.port);
|
||||
self.dump_state(system);
|
||||
self.dump_state();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ impl Debuggable for Z80 {
|
|||
decoder.dump_disassembly(&mut self.port, addr as u16, count as u16);
|
||||
}
|
||||
|
||||
fn execute_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {
|
||||
fn execute_command(&mut self, _system: &System, args: &[&str]) -> Result<bool, Error> {
|
||||
match args[0] {
|
||||
"l" => {
|
||||
use super::state::Register;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use crate::error::Error;
|
||||
use crate::devices::{Address, Addressable};
|
||||
|
||||
use super::state::{Z80, Z80Type, Register};
|
||||
use super::state::Register;
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
|
|
@ -3,14 +3,12 @@ use crate::system::System;
|
|||
use crate::error::{ErrorType, Error};
|
||||
use crate::devices::{ClockElapsed, Address, Steppable, Addressable, Interruptable, Debuggable, Transmutable, read_beu16, write_beu16};
|
||||
|
||||
use super::decode::{Condition, Instruction, LoadTarget, Target, RegisterPair, IndexRegister, IndexRegisterHalf, Size, Direction, UndocumentedCopy};
|
||||
use super::decode::{Condition, Instruction, LoadTarget, Target, RegisterPair, IndexRegister, IndexRegisterHalf, Size};
|
||||
use super::state::{Z80, Status, Flags, Register};
|
||||
|
||||
|
||||
const DEV_NAME: &'static str = "z80-cpu";
|
||||
|
||||
const FLAGS_ALL: u8 = 0xFF;
|
||||
const FLAGS_ALL_BUT_CARRY: u8 = 0xFE;
|
||||
const FLAGS_NUMERIC: u8 = 0xC0;
|
||||
const FLAGS_ARITHMETIC: u8 = 0x17;
|
||||
const FLAGS_CARRY_HALF_CARRY: u8 = 0x11;
|
||||
|
@ -28,8 +26,8 @@ impl Steppable for Z80 {
|
|||
Ok((1_000_000_000 / self.frequency as u64) * 4)
|
||||
}
|
||||
|
||||
fn on_error(&mut self, system: &System) {
|
||||
self.dump_state(system);
|
||||
fn on_error(&mut self, _system: &System) {
|
||||
self.dump_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,13 +53,13 @@ impl Transmutable for Z80 {
|
|||
impl Z80 {
|
||||
pub fn step_internal(&mut self, system: &System) -> Result<(), Error> {
|
||||
match self.state.status {
|
||||
Status::Init => self.init(system),
|
||||
Status::Init => self.init(),
|
||||
Status::Halted => Err(Error::new("CPU stopped")),
|
||||
Status::Running => {
|
||||
match self.cycle_one(system) {
|
||||
Ok(()) => Ok(()),
|
||||
//Err(Error { err: ErrorType::Processor, native, .. }) => {
|
||||
Err(Error { err: ErrorType::Processor, native, .. }) => {
|
||||
Err(Error { err: ErrorType::Processor, .. }) => {
|
||||
//self.exception(system, native as u8, false)?;
|
||||
Ok(())
|
||||
},
|
||||
|
@ -71,17 +69,16 @@ impl Z80 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self, system: &System) -> Result<(), Error> {
|
||||
//self.state.msp = self.port.read_beu32(0)?;
|
||||
//self.state.pc = self.port.read_beu32(4)?;
|
||||
pub fn init(&mut self) -> Result<(), Error> {
|
||||
self.state.pc = 0;
|
||||
self.state.status = Status::Running;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn cycle_one(&mut self, system: &System) -> Result<(), Error> {
|
||||
//self.timer.cycle.start();
|
||||
self.decode_next(system)?;
|
||||
self.execute_current(system)?;
|
||||
self.decode_next()?;
|
||||
self.execute_current()?;
|
||||
//self.timer.cycle.end();
|
||||
|
||||
//if (self.timer.cycle.events % 500) == 0 {
|
||||
|
@ -93,21 +90,21 @@ impl Z80 {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_next(&mut self, system: &System) -> Result<(), Error> {
|
||||
pub fn decode_next(&mut self) -> Result<(), Error> {
|
||||
//self.timer.decode.start();
|
||||
self.decoder.decode_at(&mut self.port, self.state.pc)?;
|
||||
//self.timer.decode.end();
|
||||
|
||||
//if self.debugger.use_tracing {
|
||||
//self.decoder.dump_decoded(&mut self.port);
|
||||
//self.dump_state(system);
|
||||
//self.dump_state();
|
||||
//}
|
||||
|
||||
self.state.pc = self.decoder.end;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute_current(&mut self, system: &System) -> Result<(), Error> {
|
||||
pub fn execute_current(&mut self) -> Result<(), Error> {
|
||||
match self.decoder.instruction {
|
||||
Instruction::ADCa(target) => {
|
||||
let src = self.get_target_value(target)?;
|
||||
|
@ -204,14 +201,14 @@ impl Z80 {
|
|||
Instruction::DEC16(regpair) => {
|
||||
let value = self.get_register_pair_value(regpair);
|
||||
|
||||
let (result, carry, overflow) = sub_words(value, 1);
|
||||
let (result, _, _) = sub_words(value, 1);
|
||||
|
||||
self.set_register_pair_value(regpair, result);
|
||||
},
|
||||
Instruction::DEC8(target) => {
|
||||
let value = self.get_target_value(target)?;
|
||||
|
||||
let (result, carry, overflow) = sub_bytes(value, 1);
|
||||
let (result, _, overflow) = sub_bytes(value, 1);
|
||||
let carry = self.get_flag(Flags::Carry); // Preserve the carry bit, according to Z80 reference
|
||||
self.set_arithmetic_op_flags(result as u16, Size::Byte, true, carry, overflow, (result & 0x10) != 0);
|
||||
|
||||
|
@ -620,7 +617,7 @@ impl Z80 {
|
|||
}
|
||||
|
||||
fn pop_word(&mut self) -> Result<u16, Error> {
|
||||
let mut value = 0;
|
||||
let mut value;
|
||||
value = self.port.read_u8(self.state.sp as Address)? as u16;
|
||||
self.state.sp = self.state.sp.wrapping_add(1);
|
||||
value |= (self.port.read_u8(self.state.sp as Address)? as u16) << 8;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
use crate::system::System;
|
||||
use crate::devices::Address;
|
||||
use crate::memory::BusPort;
|
||||
|
||||
|
@ -122,7 +121,7 @@ impl Z80 {
|
|||
self.debugger = Z80Debugger::new();
|
||||
}
|
||||
|
||||
pub fn dump_state(&mut self, system: &System) {
|
||||
pub fn dump_state(&mut self) {
|
||||
println!("Status: {:?}", self.state.status);
|
||||
println!("PC: {:#06x}", self.state.pc);
|
||||
println!("SP: {:#06x}", self.state.sp);
|
||||
|
|
|
@ -19,7 +19,7 @@ mod decode_tests {
|
|||
|
||||
// Initialize the CPU and make sure it's in the expected state
|
||||
let mut cpu = Z80::new(Z80Type::Z80, 4_000_000, BusPort::new(0, 16, 8, system.bus.clone()));
|
||||
cpu.init(&system).unwrap();
|
||||
cpu.init().unwrap();
|
||||
|
||||
(cpu, system)
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ mod decode_tests {
|
|||
fn run_decode_test(data: &[u8]) -> Instruction {
|
||||
let (mut cpu, system) = init_decode_test();
|
||||
load_memory(&system, data);
|
||||
cpu.decode_next(&system).unwrap();
|
||||
cpu.decode_next().unwrap();
|
||||
cpu.decoder.instruction
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ mod execute_tests {
|
|||
|
||||
use super::super::{Z80, Z80Type};
|
||||
use super::super::state::{Z80State, Register};
|
||||
use super::super::decode::{Instruction, LoadTarget, Target, RegisterPair, IndexRegister, IndexRegisterHalf, Condition};
|
||||
use super::super::decode::{Instruction, LoadTarget, Target, RegisterPair, Condition};
|
||||
|
||||
struct TestState {
|
||||
pc: u16,
|
||||
|
@ -571,7 +571,7 @@ mod execute_tests {
|
|||
|
||||
// Initialize the CPU and make sure it's in the expected state
|
||||
let mut cpu = Z80::new(Z80Type::Z80, 4_000_000, BusPort::new(0, 16, 8, system.bus.clone()));
|
||||
cpu.init(&system).unwrap();
|
||||
cpu.init().unwrap();
|
||||
|
||||
(cpu, system)
|
||||
}
|
||||
|
@ -608,10 +608,10 @@ mod execute_tests {
|
|||
load_memory(&system, case.data);
|
||||
cpu.state = init_state;
|
||||
|
||||
cpu.decode_next(&system).unwrap();
|
||||
cpu.decode_next().unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, case.ins);
|
||||
|
||||
cpu.execute_current(&system).unwrap();
|
||||
cpu.execute_current().unwrap();
|
||||
|
||||
// TODO this is a hack to ignore the functioning of the F5, F3 flags for now
|
||||
cpu.state.reg[Register::F as usize] &= 0xD7;
|
||||
|
|
|
@ -67,7 +67,7 @@ impl Debugger {
|
|||
|
||||
loop {
|
||||
let mut buffer = String::new();
|
||||
std::io::stdout().write_all(b"> ");
|
||||
std::io::stdout().write_all(b"> ").unwrap();
|
||||
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) {
|
||||
|
|
|
@ -6,8 +6,6 @@ use crate::error::Error;
|
|||
use crate::system::System;
|
||||
|
||||
|
||||
pub const MAX_READ: usize = 4;
|
||||
|
||||
/// The time in nanoseconds that have elapsed since the start of the simulation
|
||||
pub type Clock = u64;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ impl WindowUpdater for FrameSwapper {
|
|||
(self.current.width, self.current.height)
|
||||
}
|
||||
|
||||
fn update_frame(&mut self, width: u32, height: u32, bitmap: &mut [u32]) {
|
||||
fn update_frame(&mut self, width: u32, _height: u32, bitmap: &mut [u32]) {
|
||||
std::mem::swap(&mut self.current, &mut self.previous);
|
||||
|
||||
for y in 0..self.current.height {
|
||||
|
@ -84,7 +84,9 @@ impl WindowUpdater for FrameSwapperWrapper {
|
|||
}
|
||||
|
||||
fn update_frame(&mut self, width: u32, height: u32, bitmap: &mut [u32]) {
|
||||
self.0.lock().map(|mut swapper| swapper.update_frame(width, height, bitmap));
|
||||
if let Ok(mut swapper) = self.0.lock() {
|
||||
swapper.update_frame(width, height, bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::host::keys::Key;
|
||||
|
||||
|
@ -15,8 +13,8 @@ pub enum JoystickDevice {
|
|||
pub trait Host {
|
||||
//fn create_pty(&self) -> Result<Box<dyn Tty>, Error>;
|
||||
fn add_window(&mut self, updater: Box<dyn WindowUpdater>) -> Result<(), Error>;
|
||||
fn register_joystick(&mut self, device: JoystickDevice, input: Box<dyn JoystickUpdater>) -> Result<(), Error> { Err(Error::new("Not supported")) }
|
||||
fn register_keyboard(&mut self, input: Box<dyn KeyboardUpdater>) -> Result<(), Error> { Err(Error::new("Not supported")) }
|
||||
fn register_joystick(&mut self, _device: JoystickDevice, _input: Box<dyn JoystickUpdater>) -> Result<(), Error> { Err(Error::new("Not supported")) }
|
||||
fn register_keyboard(&mut self, _input: Box<dyn KeyboardUpdater>) -> Result<(), Error> { Err(Error::new("Not supported")) }
|
||||
}
|
||||
|
||||
pub trait Tty {
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::thread;
|
|||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
use std::io::{Read, Write};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use nix::fcntl::OFlag;
|
||||
|
@ -55,7 +54,7 @@ impl SimplePty {
|
|||
loop {
|
||||
match pty.read(&mut buf) {
|
||||
Ok(_) => {
|
||||
input_tx.send(buf[0]);
|
||||
input_tx.send(buf[0]).unwrap();
|
||||
},
|
||||
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { },
|
||||
Err(err) => { println!("ERROR: {:?}", err); }
|
||||
|
@ -84,7 +83,7 @@ impl Tty for SimplePty {
|
|||
}
|
||||
|
||||
fn write(&mut self, output: u8) -> bool {
|
||||
self.output.send(output);
|
||||
self.output.send(output).unwrap();
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
use std::iter;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::devices::TransmutableBox;
|
||||
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::system::System;
|
||||
use crate::memory::{MemoryBlock, BusPort};
|
||||
use crate::memory::{MemoryBlock, Bus, BusPort};
|
||||
use crate::devices::{wrap_transmutable, Debuggable};
|
||||
|
||||
use crate::cpus::m68k::{M68k, M68kType};
|
||||
use crate::cpus::z80::{Z80, Z80Type};
|
||||
use crate::peripherals::genesis;
|
||||
|
||||
use crate::host::traits::{Host, WindowUpdater};
|
||||
use crate::host::traits::{Host};
|
||||
|
||||
|
||||
pub fn build_genesis<H: Host>(host: &mut H) -> Result<System, Error> {
|
||||
|
@ -28,12 +32,17 @@ pub fn build_genesis<H: Host>(host: &mut H) -> Result<System, Error> {
|
|||
system.add_addressable_device(0x00000000, wrap_transmutable(rom)).unwrap();
|
||||
|
||||
let ram = MemoryBlock::new(vec![0; 0x00010000]);
|
||||
system.add_addressable_device(0x00FF0000, wrap_transmutable(ram)).unwrap();
|
||||
system.add_addressable_device(0x00ff0000, wrap_transmutable(ram)).unwrap();
|
||||
|
||||
|
||||
let coproc_bus = Rc::new(RefCell::new(Bus::new()));
|
||||
let coproc_shared_mem = wrap_transmutable(MemoryBlock::new(vec![0; 0x00010000]));
|
||||
coproc_bus.borrow_mut().insert(0x0000, coproc_shared_mem.borrow_mut().as_addressable().unwrap().len(), coproc_shared_mem.clone());
|
||||
let mut coproc = Z80::new(Z80Type::Z80, 3_579_545, BusPort::new(0, 16, 8, coproc_bus.clone()));
|
||||
|
||||
system.add_addressable_device(0x00a00000, coproc_shared_mem)?;
|
||||
//system.add_device("coproc", wrap_transmutable(coproc))?;
|
||||
|
||||
let coproc_shared_mem = MemoryBlock::new(vec![0; 0x00010000]);
|
||||
system.add_addressable_device(0x00A00000, wrap_transmutable(coproc_shared_mem)).unwrap();
|
||||
|
||||
|
||||
let controllers = genesis::controllers::GenesisController::create(host)?;
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::rc::Rc;
|
|||
use std::cell::RefCell;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::devices::{Address, Addressable, Transmutable, TransmutableBox, MAX_READ};
|
||||
use crate::devices::{Address, Addressable, Transmutable, TransmutableBox};
|
||||
|
||||
|
||||
pub struct MemoryBlock {
|
||||
|
@ -75,6 +75,41 @@ impl Transmutable for MemoryBlock {
|
|||
}
|
||||
|
||||
|
||||
pub struct MemoryAdapter {
|
||||
pub subdevice: TransmutableBox,
|
||||
pub shift: u8,
|
||||
}
|
||||
|
||||
impl MemoryAdapter {
|
||||
pub fn new(subdevice: TransmutableBox, shift: u8) -> Self {
|
||||
Self {
|
||||
subdevice,
|
||||
shift,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Addressable for MemoryAdapter {
|
||||
fn len(&self) -> usize {
|
||||
let len = self.subdevice.borrow_mut().as_addressable().unwrap().len();
|
||||
len << self.shift
|
||||
}
|
||||
|
||||
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
||||
self.subdevice.borrow_mut().as_addressable().unwrap().read(addr >> self.shift, data)
|
||||
}
|
||||
|
||||
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
||||
self.subdevice.borrow_mut().as_addressable().unwrap().write(addr >> self.shift, data)
|
||||
}
|
||||
}
|
||||
|
||||
impl Transmutable for MemoryAdapter {
|
||||
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct Block {
|
||||
pub base: Address,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use std::fs;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::devices::{Address, Addressable, Transmutable, MAX_READ};
|
||||
use crate::devices::{Address, Addressable, Transmutable};
|
||||
|
||||
|
||||
const ATA_REG_DATA_WORD: Address = 0x20;
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::signals::{Signal, SyncSignal};
|
||||
use crate::devices::{Address, Addressable, Transmutable, MAX_READ};
|
||||
use crate::signals::SyncSignal;
|
||||
use crate::devices::{Address, Addressable, Transmutable};
|
||||
use crate::host::traits::{Host, JoystickDevice, JoystickUpdater};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
use crate::error::Error;
|
||||
use crate::devices::{Address, Addressable, Transmutable, MAX_READ};
|
||||
use crate::devices::{Address, Addressable, Transmutable};
|
||||
|
||||
|
||||
const DEV_NAME: &'static str = "coprocessor";
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::sync::{Arc, Mutex};
|
|||
use crate::error::Error;
|
||||
use crate::system::System;
|
||||
use crate::signals::SyncSignal;
|
||||
use crate::devices::{Clock, ClockElapsed, Address, Addressable, Steppable, Transmutable, MAX_READ, read_beu16, read_beu32, write_beu16};
|
||||
use crate::devices::{Clock, ClockElapsed, Address, Addressable, Steppable, Transmutable, read_beu16, read_beu32, write_beu16};
|
||||
use crate::host::traits::{Host, BlitableSurface};
|
||||
use crate::host::gfx::{Frame, FrameSwapper};
|
||||
|
||||
|
@ -251,17 +251,20 @@ impl Ym7101State {
|
|||
}
|
||||
|
||||
pub fn draw_frame(&mut self, frame: &mut Frame) {
|
||||
let bg_colour = self.get_palette_colour((self.regs[REG_BACKGROUND] & 0x30) >> 4, self.regs[REG_BACKGROUND] & 0x0f);
|
||||
for i in 0..(frame.width as usize * frame.height as usize) {
|
||||
frame.bitmap[i] = bg_colour;
|
||||
}
|
||||
|
||||
self.draw_background(frame);
|
||||
self.draw_cell_table(frame, self.get_vram_scroll_b_addr());
|
||||
self.draw_cell_table(frame, self.get_vram_scroll_a_addr());
|
||||
//self.draw_window(frame);
|
||||
self.draw_sprites(frame);
|
||||
}
|
||||
|
||||
pub fn draw_background(&mut self, frame: &mut Frame) {
|
||||
let bg_colour = self.get_palette_colour((self.regs[REG_BACKGROUND] & 0x30) >> 4, self.regs[REG_BACKGROUND] & 0x0f);
|
||||
for i in 0..(frame.width as usize * frame.height as usize) {
|
||||
frame.bitmap[i] = bg_colour;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_cell_table(&mut self, frame: &mut Frame, cell_table: u32) {
|
||||
let (scroll_h, scroll_v) = self.get_scroll_size();
|
||||
let (cells_h, cells_v) = self.get_screen_size();
|
||||
|
@ -411,14 +414,10 @@ pub struct Ym7101 {
|
|||
}
|
||||
|
||||
impl Ym7101 {
|
||||
pub fn new<H: Host>(host: &H, external_interrupt: SyncSignal<bool>) -> Ym7101 {
|
||||
let swapper = FrameSwapper::new_shared();
|
||||
swapper.lock().map(|mut swapper| {
|
||||
swapper.current.set_size(320, 224);
|
||||
swapper.previous.set_size(320, 224);
|
||||
});
|
||||
pub fn new<H: Host>(host: &mut H, external_interrupt: SyncSignal<bool>) -> Ym7101 {
|
||||
let swapper = FrameSwapper::new_shared(320, 224);
|
||||
|
||||
host.add_window(FrameSwapper::to_boxed(swapper.clone()));
|
||||
host.add_window(FrameSwapper::to_boxed(swapper.clone())).unwrap();
|
||||
|
||||
Ym7101 {
|
||||
swapper,
|
||||
|
@ -490,16 +489,48 @@ impl Steppable for Ym7101 {
|
|||
/*
|
||||
// Print Pattern Table
|
||||
let mut swapper = self.swapper.lock().unwrap();
|
||||
let coords = self.state.get_window_coords();
|
||||
for cell_y in coords.0.1..coords.1.1 {
|
||||
for cell_x in coords.0.0..coords.1.0 {
|
||||
let pattern_addr = (cell_x + (cell_y * 40)) * 32;
|
||||
let iter = PatternIterator::new(&self.state, pattern_addr as u32, 0);
|
||||
let (cells_h, cells_v) = self.state.get_screen_size();
|
||||
for cell_y in 0..cells_v {
|
||||
for cell_x in 0..cells_h {
|
||||
let pattern_addr = (cell_x + (cell_y * cells_h)) * 32;
|
||||
let iter = PatternIterator::new(&self.state, pattern_addr as u32, 0, false, false);
|
||||
swapper.current.blit((cell_x << 3) as u32, (cell_y << 3) as u32, iter, 8, 8);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
// Print Sprite
|
||||
let mut swapper = self.swapper.lock().unwrap();
|
||||
self.state.draw_background(&mut swapper.current);
|
||||
let sprite_table = (self.state.regs[REG_SPRITES_ADDR] as usize) << 9;
|
||||
let (cells_h, cells_v) = self.state.get_screen_size();
|
||||
let sprite = 0;
|
||||
println!("{:?}", &self.state.vram[(sprite_table + (sprite * 8))..(sprite_table + (sprite * 8) + 8)].iter().map(|byte| format!("{:02x}", byte)).collect::<Vec<String>>());
|
||||
let size = self.state.vram[sprite_table + (sprite * 8) + 2];
|
||||
let (size_h, size_v) = (((size >> 2) & 0x03) as u16 + 1, (size & 0x03) as u16 + 1);
|
||||
let pattern_name = ((self.state.vram[sprite_table + (sprite * 8) + 4] as u16) << 8) | (self.state.vram[sprite_table + (sprite * 8) + 5] as u16);
|
||||
let pattern_gen = pattern_name & 0x7FF;
|
||||
println!("{:x}", pattern_name);
|
||||
|
||||
for cell_y in 0..size_v {
|
||||
for cell_x in 0..size_h {
|
||||
let pattern_addr = (pattern_gen + (cell_y * size_h) + cell_x) as u32;
|
||||
println!("pattern: ({}, {}) {:x}", cell_x, cell_y, pattern_addr);
|
||||
let iter = PatternIterator::new(&self.state, pattern_addr * 32, 3, true, true);
|
||||
swapper.current.blit((cell_x << 3) as u32, (cell_y << 3) as u32, iter, 8, 8);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//let mut swapper = self.swapper.lock().unwrap();
|
||||
//swapper.current.blit(0, 0, PatternIterator::new(&self.state, 0x408 * 32, 3, false, false), 8, 8);
|
||||
//swapper.current.blit(0, 8, PatternIterator::new(&self.state, 0x409 * 32, 3, false, false), 8, 8);
|
||||
//swapper.current.blit(8, 0, PatternIterator::new(&self.state, 0x402 * 32, 3, false, false), 8, 8);
|
||||
//swapper.current.blit(8, 8, PatternIterator::new(&self.state, 0x403 * 32, 3, false, false), 8, 8);
|
||||
//swapper.current.blit(16, 0, PatternIterator::new(&self.state, 0x404 * 32, 3, false, false), 8, 8);
|
||||
//swapper.current.blit(16, 8, PatternIterator::new(&self.state, 0x405 * 32, 3, false, false), 8, 8);
|
||||
}
|
||||
|
||||
if self.state.transfer_run != DmaType::None {
|
||||
|
@ -525,7 +556,7 @@ impl Steppable for Ym7101 {
|
|||
|
||||
{
|
||||
let addr = self.state.transfer_addr;
|
||||
let mut target = self.state.get_transfer_target_mut();
|
||||
let target = self.state.get_transfer_target_mut();
|
||||
target[addr as usize] = data[0];
|
||||
target[addr as usize + 1] = data[1];
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
use crate::error::Error;
|
||||
use crate::system::System;
|
||||
use crate::devices::{ClockElapsed, Address, Steppable, Addressable, Transmutable, MAX_READ};
|
||||
use crate::devices::{ClockElapsed, Address, Steppable, Addressable, Transmutable};
|
||||
|
||||
use crate::host::traits::Tty;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
use std::slice::Iter;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::error::Error;
|
||||
|
@ -7,7 +6,7 @@ use crate::system::System;
|
|||
use crate::devices::{ClockElapsed, Address, Addressable, Steppable, Transmutable};
|
||||
|
||||
use crate::host::keys::Key;
|
||||
use crate::host::gfx::{Frame, FrameSwapper};
|
||||
use crate::host::gfx::{FrameSwapper};
|
||||
use crate::host::traits::{Host, BlitableSurface, KeyboardUpdater};
|
||||
|
||||
use super::keymap;
|
||||
|
@ -48,7 +47,7 @@ impl KeyboardUpdater for Model1KeyboardUpdater {
|
|||
}
|
||||
|
||||
impl Steppable for Model1Peripherals {
|
||||
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
|
||||
fn step(&mut self, _system: &System) -> Result<ClockElapsed, Error> {
|
||||
let mut swapper = self.swapper.lock().unwrap();
|
||||
swapper.current.clear(0);
|
||||
for y in 0..16 {
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::memory::Bus;
|
|||
use crate::debugger::Debugger;
|
||||
use crate::error::{Error, ErrorType};
|
||||
use crate::interrupts::InterruptController;
|
||||
use crate::devices::{Clock, ClockElapsed, Address, TransmutableBox};
|
||||
use crate::devices::{Clock, Address, TransmutableBox};
|
||||
|
||||
|
||||
pub struct System {
|
||||
|
@ -45,11 +45,17 @@ impl System {
|
|||
self.interrupt_controller.borrow_mut()
|
||||
}
|
||||
|
||||
pub fn add_device(&mut self, name: &str, device: TransmutableBox) -> Result<(), Error> {
|
||||
self.try_queue_device(device.clone());
|
||||
self.devices.insert(name.to_string(), device);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_addressable_device(&mut self, addr: Address, device: TransmutableBox) -> Result<(), Error> {
|
||||
let length = device.borrow_mut().as_addressable().unwrap().len();
|
||||
self.bus.borrow_mut().insert(addr, length, device.clone());
|
||||
self.try_queue_device(device.clone());
|
||||
self.devices.insert(format!("ram{:x}", addr), device);
|
||||
self.devices.insert(format!("mem{:x}", addr), device);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -108,7 +114,7 @@ impl System {
|
|||
}
|
||||
|
||||
pub fn run_loop(&mut self) {
|
||||
self.run_for(u64::MAX);
|
||||
self.run_for(u64::MAX).unwrap();
|
||||
}
|
||||
|
||||
pub fn exit_error(&mut self) {
|
||||
|
|
25
todo.txt
25
todo.txt
|
@ -1,25 +1,19 @@
|
|||
|
||||
* the overflow bit is only correct for addition but not subtraction... in subtraction, two positives can result in a negative and vice versa
|
||||
* we need better m68k tests. Can we do what we did for Z80, with maybe a reduced test state and/or different states for different types of tests
|
||||
* maybe see about a Mac 128k or something
|
||||
|
||||
|
||||
|
||||
* could have a remapper device, which takes a big swath of addresses in and maps them to another set of addresses (for Mac VIA generic to bus-hookup-in-mac adapter)
|
||||
* how can you do devices that change their address map during operation, like mac which puts rom at 0 and ram at 600000 temporarily
|
||||
* i need a better way of handling disperate reads/writes to I/O spaces, rather than having multiple devices or having a massive chunk of address space allocated, continuously
|
||||
* should you modify Addressable to also take the absolute address as input? I'm thinking of how the same device could be mapped to multiple addresses in memory instead
|
||||
of taking up a whole range of addresses
|
||||
* could you use a generic sharable signal thing for sharing data, such as the VIA in mac128 where a single output bit determines the video mode (which would be a separate device)
|
||||
So both could share the same Signal, one setting it and the other reading it, but how would you actually configure/build that?
|
||||
|
||||
|
||||
* make it possible to specify the rom on the command line. Would this be machine specific?
|
||||
* make the frontend resize its window based on the frame swapper
|
||||
* make it possible to set the frame sizes when creating the frame swapper
|
||||
* should you rename devices.rs traits.rs?
|
||||
|
||||
|
||||
|
||||
* maybe see about a Mac 128k or something
|
||||
* how can you do devices that change their address map during operation, like mac which puts rom at 0 and ram at 600000 temporarily
|
||||
* i need a better way of handling disperate reads/writes to I/O spaces, rather than having multiple devices or having a massive chunk of address space allocated, continuously
|
||||
* should you modify Addressable to also take the absolute address as input? I'm thinking of how the same device could be mapped to multiple addresses in memory instead
|
||||
of taking up a whole range of addresses
|
||||
* could have a remapper device, which takes a big swath of addresses in and maps them to another set of addresses (for Mac VIA generic to bus-hookup-in-mac adapter)
|
||||
* could you use a generic sharable signal thing for sharing data, such as the VIA in mac128 where a single output bit determines the video mode (which would be a separate device)
|
||||
So both could share the same Signal, one setting it and the other reading it, but how would you actually configure/build that?
|
||||
|
||||
|
||||
* you could modify read()/write() in Addressable to return the number of bytes read or written for dynamic bus sizing used by the MC68020+
|
||||
|
@ -50,6 +44,5 @@ Z80:
|
|||
|
||||
|
||||
* how can you have multiple CPUs
|
||||
* each device that can make a bus request should have a BusPort which is used to access the bus
|
||||
* can you eventually make the system connections all configurable via a config file?
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user