Introduce janky trace log debugging

New functions trace_on and trace_off
This commit is contained in:
Seth Morabito 2021-04-23 05:50:15 -07:00
parent c9161324b5
commit e8f8584e64
10 changed files with 8792 additions and 6432 deletions

View File

@ -1,2 +1,2 @@
max_width = 132
max_width = 100
use_small_heuristics = "Off"

View File

@ -4,8 +4,9 @@ use crate::duart::Duart;
use crate::err::BusError;
use crate::mem::Mem;
use crate::mouse::Mouse;
use std::fmt::Debug;
use std::ops::Range;
use std::io::Write;
use std::{fmt, fs::File, ops::Range};
use std::{fmt::Debug, fs::OpenOptions};
const NVRAM_SIZE: usize = 8192;
@ -62,6 +63,7 @@ pub struct Bus {
vid: Mem, // TODO: Figure out what device this really is
bbram: Mem, // TODO: change to BBRAM when implemented
ram: Mem,
trace_log: Option<File>,
}
impl Bus {
@ -73,6 +75,7 @@ impl Bus {
vid: Mem::new(0x500000, 0x2, false),
bbram: Mem::new(0x600000, 0x2000, false),
ram: Mem::new(0x700000, mem_size, false),
trace_log: None,
}
}
@ -104,6 +107,30 @@ impl Bus {
Err(BusError::NoDevice(address as u32))
}
pub fn trace_on(&mut self, name: &str) -> std::io::Result<()> {
let mut out = OpenOptions::new().write(true).open(name)?;
write!(out, "TRACE START")?;
self.trace_log = Some(out);
Ok(())
}
pub fn trace_enabled(&self) -> bool {
self.trace_log.is_some()
}
pub fn trace_off(&mut self) {
self.trace_log = None;
}
pub fn trace<T>(&mut self, step: u64, object: &T)
where
T: fmt::Display,
{
if let Some(trace_log) = &mut self.trace_log {
let _ = writeln!(trace_log, "{:08}: {}", step, object);
}
}
pub fn read_byte(&mut self, address: usize, access: AccessCode) -> Result<u8, BusError> {
self.get_device(address)?.read_byte(address, access)
}

View File

@ -3,6 +3,7 @@
use crate::bus::{AccessCode, Bus};
use crate::err::*;
use crate::instr::*;
use std::fmt;
///
/// PSW Flags and Offsets
@ -39,8 +40,9 @@ const R_ISP: usize = 14;
const R_PC: usize = 15;
const IPL_TABLE: [u32; 64] = [
0, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
0, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
];
const WE32100_VERSION: u32 = 0x1a;
@ -169,9 +171,30 @@ pub struct Instruction {
pub operands: [Operand; 4],
}
impl Instruction {
pub fn decode(&self) -> String {
format!("{}\t0x{:x}", self.name, 1000)
impl fmt::Display for Operand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.data_type {
Data::None => Ok(()),
Data::Byte | Data::SByte => {
write!(f, "0x{:02x}", self.data as u8)
}
Data::Half | Data::UHalf => {
write!(f, "0x{:04x}", self.data as u16)
}
Data::Word | Data::UWord => {
write!(f, "0x{:08x}", self.data)
}
}
}
}
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:5} {}{}{}{}",
self.name, self.operands[0], self.operands[1], self.operands[2], self.operands[3]
)
}
}
@ -458,17 +481,62 @@ static BYTE_MNEMONICS: [Option<Mnemonic>; 256] = [
];
static HALFWORD_MNEMONICS: [Option<Mnemonic>; HALFWORD_MNEMONIC_COUNT] = [
Some(mn!(0x3009, Data::None, "MVERNO", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x300d, Data::None, "ENBVJMP", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x3013, Data::None, "DISVJMP", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x3019, Data::None, "MOVBLW", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x301f, Data::None, "STREND", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x302f, Data::None, "INTACK", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x303f, Data::None, "STRCPY", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(
0x3009,
Data::None,
"MVERNO",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(
0x300d,
Data::None,
"ENBVJMP",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(
0x3013,
Data::None,
"DISVJMP",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(
0x3019,
Data::None,
"MOVBLW",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(
0x301f,
Data::None,
"STREND",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(
0x302f,
Data::None,
"INTACK",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(
0x303f,
Data::None,
"STRCPY",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(0x3045, Data::None, "RETG", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x3061, Data::None, "GATE", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x30ac, Data::None, "CALLPS", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x30c8, Data::None, "RETPS", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(
0x30ac,
Data::None,
"CALLPS",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
Some(mn!(
0x30c8,
Data::None,
"RETPS",
[OpType::None, OpType::None, OpType::None, OpType::None]
)),
];
static NULL_MNEMONIC: Option<Mnemonic> = None;
@ -560,7 +628,9 @@ impl Cpu {
self.r[r]
}
AddrMode::Absolute => embedded,
AddrMode::AbsoluteDeferred => bus.read_word(embedded as usize, AccessCode::AddressFetch)?,
AddrMode::AbsoluteDeferred => {
bus.read_word(embedded as usize, AccessCode::AddressFetch)?
}
AddrMode::FpShortOffset => add_offset(self.r[R_FP], sign_extend_byte(embedded as u8)),
AddrMode::ApShortOffset => add_offset(self.r[R_AP], sign_extend_byte(embedded as u8)),
AddrMode::WordDisplacement => {
@ -589,7 +659,10 @@ impl Cpu {
Some(v) => v,
None => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
};
bus.read_word((add_offset(self.r[r], sign_extend_halfword(embedded as u16))) as usize, AccessCode::AddressFetch)?
bus.read_word(
(add_offset(self.r[r], sign_extend_halfword(embedded as u16))) as usize,
AccessCode::AddressFetch,
)?
}
AddrMode::ByteDisplacement => {
let r = match register {
@ -603,7 +676,10 @@ impl Cpu {
Some(v) => v,
None => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
};
bus.read_word(add_offset(self.r[r], sign_extend_byte(embedded as u8)) as usize, AccessCode::AddressFetch)?
bus.read_word(
add_offset(self.r[r], sign_extend_byte(embedded as u8)) as usize,
AccessCode::AddressFetch,
)?
}
_ => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
};
@ -633,18 +709,26 @@ impl Cpu {
_ => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
}
}
AddrMode::PositiveLiteral | AddrMode::NegativeLiteral => sign_extend_byte(op.embedded as u8),
AddrMode::PositiveLiteral | AddrMode::NegativeLiteral => {
sign_extend_byte(op.embedded as u8)
}
AddrMode::WordImmediate => op.embedded,
AddrMode::HalfwordImmediate => sign_extend_halfword(op.embedded as u16),
AddrMode::ByteImmediate => sign_extend_byte(op.embedded as u8),
_ => {
let eff = self.effective_address(bus, index)?;
match op.data_type() {
Data::UWord | Data::Word => bus.read_word(eff as usize, AccessCode::InstrFetch)?,
Data::Half => sign_extend_halfword(bus.read_half(eff as usize, AccessCode::InstrFetch)?),
Data::UWord | Data::Word => {
bus.read_word(eff as usize, AccessCode::InstrFetch)?
}
Data::Half => {
sign_extend_halfword(bus.read_half(eff as usize, AccessCode::InstrFetch)?)
}
Data::UHalf => u32::from(bus.read_half(eff as usize, AccessCode::InstrFetch)?),
Data::Byte => u32::from(bus.read_byte(eff as usize, AccessCode::InstrFetch)?),
Data::SByte => sign_extend_byte(bus.read_byte(eff as usize, AccessCode::InstrFetch)?),
Data::SByte => {
sign_extend_byte(bus.read_byte(eff as usize, AccessCode::InstrFetch)?)
}
_ => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
}
}
@ -836,7 +920,9 @@ impl Cpu {
// TODO: Remove unwraps
fn on_interrupt(&mut self, bus: &mut Bus, vector: u8) {
let new_pcbp = bus.read_word((0x8c + (4 * u32::from(vector))) as usize, AccessCode::AddressFetch).unwrap();
let new_pcbp = bus
.read_word((0x8c + (4 * u32::from(vector))) as usize, AccessCode::AddressFetch)
.unwrap();
self.irq_push(bus, self.r[R_PCBP]).unwrap();
self.r[R_PSW] &= !(F_ISC | F_TM | F_ET);
@ -869,6 +955,8 @@ impl Cpu {
self.decode_instruction(bus)?;
let mut pc_increment: i32 = i32::from(self.ir.bytes);
bus.trace(self.steps, &self.ir);
match self.ir.opcode {
NOP => {
pc_increment = 1;
@ -1547,7 +1635,8 @@ impl Cpu {
self.r[R_SP] = a;
}
RETG => {
let mut new_psw = bus.read_word(self.r[R_SP] as usize - 4, AccessCode::AddressFetch)?;
let mut new_psw =
bus.read_word(self.r[R_SP] as usize - 4, AccessCode::AddressFetch)?;
let new_pc = bus.read_word(self.r[R_SP] as usize - 8, AccessCode::AddressFetch)?;
// TODO: Check for illegal level change
@ -1643,17 +1732,28 @@ impl Cpu {
self.context_switch_3(bus)?;
if self.r[R_PSW] & F_R != 0 {
self.r[R_FP] = bus.read_word((new_pcbp + 24) as usize, AccessCode::AddressFetch)?;
self.r[0] = bus.read_word((new_pcbp + 28) as usize, AccessCode::AddressFetch)?;
self.r[1] = bus.read_word((new_pcbp + 32) as usize, AccessCode::AddressFetch)?;
self.r[2] = bus.read_word((new_pcbp + 36) as usize, AccessCode::AddressFetch)?;
self.r[3] = bus.read_word((new_pcbp + 40) as usize, AccessCode::AddressFetch)?;
self.r[4] = bus.read_word((new_pcbp + 44) as usize, AccessCode::AddressFetch)?;
self.r[5] = bus.read_word((new_pcbp + 48) as usize, AccessCode::AddressFetch)?;
self.r[6] = bus.read_word((new_pcbp + 52) as usize, AccessCode::AddressFetch)?;
self.r[7] = bus.read_word((new_pcbp + 56) as usize, AccessCode::AddressFetch)?;
self.r[8] = bus.read_word((new_pcbp + 60) as usize, AccessCode::AddressFetch)?;
self.r[R_AP] = bus.read_word((new_pcbp + 20) as usize, AccessCode::AddressFetch)?;
self.r[R_FP] =
bus.read_word((new_pcbp + 24) as usize, AccessCode::AddressFetch)?;
self.r[0] =
bus.read_word((new_pcbp + 28) as usize, AccessCode::AddressFetch)?;
self.r[1] =
bus.read_word((new_pcbp + 32) as usize, AccessCode::AddressFetch)?;
self.r[2] =
bus.read_word((new_pcbp + 36) as usize, AccessCode::AddressFetch)?;
self.r[3] =
bus.read_word((new_pcbp + 40) as usize, AccessCode::AddressFetch)?;
self.r[4] =
bus.read_word((new_pcbp + 44) as usize, AccessCode::AddressFetch)?;
self.r[5] =
bus.read_word((new_pcbp + 48) as usize, AccessCode::AddressFetch)?;
self.r[6] =
bus.read_word((new_pcbp + 52) as usize, AccessCode::AddressFetch)?;
self.r[7] =
bus.read_word((new_pcbp + 56) as usize, AccessCode::AddressFetch)?;
self.r[8] =
bus.read_word((new_pcbp + 60) as usize, AccessCode::AddressFetch)?;
self.r[R_AP] =
bus.read_word((new_pcbp + 20) as usize, AccessCode::AddressFetch)?;
}
pc_increment = 0;
@ -1857,7 +1957,13 @@ impl Cpu {
///
/// These operands belong to only certain instructions, where a word without
/// a descriptor byte immediately follows the opcode.
fn decode_literal_operand(&mut self, bus: &mut Bus, index: usize, mn: &Mnemonic, addr: usize) -> Result<(), CpuError> {
fn decode_literal_operand(
&mut self,
bus: &mut Bus,
index: usize,
mn: &Mnemonic,
addr: usize,
) -> Result<(), CpuError> {
match mn.dtype {
Data::Byte => {
let b: u8 = bus.read_byte(addr, AccessCode::OperandFetch)?;
@ -1903,18 +2009,42 @@ impl Cpu {
match m {
0 | 1 | 2 | 3 => {
// Positive Literal
self.set_operand(index, dsize, AddrMode::PositiveLiteral, dtype, etype, None, u32::from(descriptor_byte));
self.set_operand(
index,
dsize,
AddrMode::PositiveLiteral,
dtype,
etype,
None,
u32::from(descriptor_byte),
);
}
4 => {
match r {
15 => {
// Word Immediate
let w = bus.read_op_word(addr + 1)?;
self.set_operand(index, dsize + 4, AddrMode::WordImmediate, dtype, etype, None, w);
self.set_operand(
index,
dsize + 4,
AddrMode::WordImmediate,
dtype,
etype,
None,
w,
);
}
_ => {
// Register
self.set_operand(index, dsize, AddrMode::Register, dtype, etype, Some(r as usize), 0);
self.set_operand(
index,
dsize,
AddrMode::Register,
dtype,
etype,
Some(r as usize),
0,
);
}
}
}
@ -1923,7 +2053,15 @@ impl Cpu {
15 => {
// Halfword Immediate
let h = bus.read_op_half(addr + 1)?;
self.set_operand(index, dsize + 2, AddrMode::HalfwordImmediate, dtype, etype, None, u32::from(h));
self.set_operand(
index,
dsize + 2,
AddrMode::HalfwordImmediate,
dtype,
etype,
None,
u32::from(h),
);
}
11 => {
// Illegal
@ -1931,7 +2069,15 @@ impl Cpu {
}
_ => {
// Register Deferred Mode
self.set_operand(index, dsize, AddrMode::RegisterDeferred, dtype, etype, Some(r as usize), 0);
self.set_operand(
index,
dsize,
AddrMode::RegisterDeferred,
dtype,
etype,
Some(r as usize),
0,
);
}
}
}
@ -1940,11 +2086,27 @@ impl Cpu {
15 => {
// Byte Immediate
let b = bus.read_byte(addr + 1, AccessCode::OperandFetch)?;
self.set_operand(index, dsize + 1, AddrMode::ByteImmediate, dtype, etype, None, u32::from(b));
self.set_operand(
index,
dsize + 1,
AddrMode::ByteImmediate,
dtype,
etype,
None,
u32::from(b),
);
}
_ => {
// FP Short Offset
self.set_operand(index, dsize, AddrMode::FpShortOffset, dtype, etype, Some(R_FP), u32::from(r));
self.set_operand(
index,
dsize,
AddrMode::FpShortOffset,
dtype,
etype,
Some(R_FP),
u32::from(r),
);
}
}
}
@ -1953,11 +2115,27 @@ impl Cpu {
15 => {
// Absolute
let w = bus.read_op_word(addr + 1)?;
self.set_operand(index, dsize + 4, AddrMode::Absolute, dtype, etype, None, w);
self.set_operand(
index,
dsize + 4,
AddrMode::Absolute,
dtype,
etype,
None,
w,
);
}
_ => {
// AP Short Offset
self.set_operand(index, dsize, AddrMode::ApShortOffset, dtype, etype, Some(R_AP), u32::from(r));
self.set_operand(
index,
dsize,
AddrMode::ApShortOffset,
dtype,
etype,
Some(R_AP),
u32::from(r),
);
}
}
}
@ -1967,7 +2145,15 @@ impl Cpu {
_ => {
// Word Displacement
let disp = bus.read_op_word(addr + 1)?;
self.set_operand(index, dsize + 4, AddrMode::WordDisplacement, dtype, etype, Some(r as usize), disp);
self.set_operand(
index,
dsize + 4,
AddrMode::WordDisplacement,
dtype,
etype,
Some(r as usize),
disp,
);
}
}
}
@ -2062,15 +2248,65 @@ impl Cpu {
}
}
14 => match r {
0 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::UWord), addr + 1, true)?,
2 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::UHalf), addr + 1, true)?,
3 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::Byte), addr + 1, true)?,
4 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::Word), addr + 1, true)?,
6 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::Half), addr + 1, true)?,
7 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::SByte), addr + 1, true)?,
0 => self.decode_descriptor_operand(
bus,
index,
dtype,
Some(Data::UWord),
addr + 1,
true,
)?,
2 => self.decode_descriptor_operand(
bus,
index,
dtype,
Some(Data::UHalf),
addr + 1,
true,
)?,
3 => self.decode_descriptor_operand(
bus,
index,
dtype,
Some(Data::Byte),
addr + 1,
true,
)?,
4 => self.decode_descriptor_operand(
bus,
index,
dtype,
Some(Data::Word),
addr + 1,
true,
)?,
6 => self.decode_descriptor_operand(
bus,
index,
dtype,
Some(Data::Half),
addr + 1,
true,
)?,
7 => self.decode_descriptor_operand(
bus,
index,
dtype,
Some(Data::SByte),
addr + 1,
true,
)?,
15 => {
let w = bus.read_op_word(addr + 1)?;
self.set_operand(index, dsize + 4, AddrMode::AbsoluteDeferred, dtype, etype, None, w);
self.set_operand(
index,
dsize + 4,
AddrMode::AbsoluteDeferred,
dtype,
etype,
None,
w,
);
}
_ => {
return Err(CpuError::Exception(CpuException::IllegalOpcode));
@ -2078,7 +2314,15 @@ impl Cpu {
},
15 => {
// Negative Literal
self.set_operand(index, 1, AddrMode::NegativeLiteral, dtype, etype, None, u32::from(descriptor_byte));
self.set_operand(
index,
1,
AddrMode::NegativeLiteral,
dtype,
etype,
None,
u32::from(descriptor_byte),
);
}
_ => {
return Err(CpuError::Exception(CpuException::IllegalOpcode));
@ -2100,7 +2344,9 @@ impl Cpu {
) -> Result<(), CpuError> {
match ot {
OpType::Lit => self.decode_literal_operand(bus, index, mn, addr),
OpType::Src | OpType::Dest => self.decode_descriptor_operand(bus, index, mn.dtype, etype, addr, false),
OpType::Src | OpType::Dest => {
self.decode_descriptor_operand(bus, index, mn.dtype, etype, addr, false)
}
OpType::None => Ok(()),
}
}
@ -2385,8 +2631,17 @@ mod tests {
let program: [u8; 2] = [0x4f, 0x06]; // BLEB 0x6
do_with_program(&program, |cpu, mut bus| {
cpu.decode_literal_operand(&mut bus, 0, BYTE_MNEMONICS[0x4F as usize].as_ref().unwrap(), BASE + 1).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::None, Data::Byte, None, None, 6));
cpu.decode_literal_operand(
&mut bus,
0,
BYTE_MNEMONICS[0x4F as usize].as_ref().unwrap(),
BASE + 1,
)
.unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::None, Data::Byte, None, None, 6)
);
})
}
@ -2395,8 +2650,17 @@ mod tests {
let program: [u8; 3] = [0x4e, 0xff, 0x0f]; // BLEH 0xfff
do_with_program(&program, |cpu, mut bus| {
cpu.decode_literal_operand(&mut bus, 0, BYTE_MNEMONICS[0x4e as usize].as_ref().unwrap(), BASE + 1).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(2, AddrMode::None, Data::Half, None, None, 0xfff));
cpu.decode_literal_operand(
&mut bus,
0,
BYTE_MNEMONICS[0x4e as usize].as_ref().unwrap(),
BASE + 1,
)
.unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(2, AddrMode::None, Data::Half, None, None, 0xfff)
);
})
}
@ -2405,8 +2669,17 @@ mod tests {
let program: [u8; 5] = [0x32, 0xff, 0x4f, 0x00, 0x00]; // SPOP 0x4fff
do_with_program(&program, |cpu, mut bus| {
cpu.decode_literal_operand(&mut bus, 0, BYTE_MNEMONICS[0x32 as usize].as_ref().unwrap(), BASE + 1).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(4, AddrMode::None, Data::Word, None, None, 0x4fff));
cpu.decode_literal_operand(
&mut bus,
0,
BYTE_MNEMONICS[0x32 as usize].as_ref().unwrap(),
BASE + 1,
)
.unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(4, AddrMode::None, Data::Word, None, None, 0x4fff)
);
});
}
@ -2416,7 +2689,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::PositiveLiteral, Data::Byte, None, None, 0x04));
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::PositiveLiteral, Data::Byte, None, None, 0x04)
);
});
}
@ -2426,7 +2702,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(5, AddrMode::WordImmediate, Data::Word, None, None, 0x12345678));
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::WordImmediate, Data::Word, None, None, 0x12345678)
);
});
}
@ -2436,7 +2715,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 2, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::Register, Data::Byte, None, Some(4), 0));
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::Register, Data::Byte, None, Some(4), 0)
);
});
}
@ -2446,7 +2728,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(3, AddrMode::HalfwordImmediate, Data::Word, None, None, 0x1234,));
assert_eq!(
cpu.ir.operands[0],
Operand::new(3, AddrMode::HalfwordImmediate, Data::Word, None, None, 0x1234,)
);
});
}
@ -2456,7 +2741,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Half, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::RegisterDeferred, Data::Half, None, Some(2), 0));
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::RegisterDeferred, Data::Half, None, Some(2), 0)
);
});
}
@ -2466,7 +2754,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(2, AddrMode::ByteImmediate, Data::Word, None, None, 40));
assert_eq!(
cpu.ir.operands[0],
Operand::new(2, AddrMode::ByteImmediate, Data::Word, None, None, 40)
);
});
}
@ -2476,7 +2767,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::FpShortOffset, Data::Word, None, Some(R_FP), 12));
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::FpShortOffset, Data::Word, None, Some(R_FP), 12)
);
});
}
@ -2486,7 +2780,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(5, AddrMode::Absolute, Data::Byte, None, None, 0x00000100));
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::Absolute, Data::Byte, None, None, 0x00000100)
);
});
}
@ -2496,7 +2793,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(5, AddrMode::AbsoluteDeferred, Data::Byte, None, None, 0x00000100));
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::AbsoluteDeferred, Data::Byte, None, None, 0x00000100)
);
});
}
@ -2506,7 +2806,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::ApShortOffset, Data::Word, None, Some(R_AP), 4));
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::ApShortOffset, Data::Word, None, Some(R_AP), 4)
);
});
}
@ -2516,7 +2819,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(5, AddrMode::WordDisplacement, Data::Byte, None, Some(2), 0x1234,));
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::WordDisplacement, Data::Byte, None, Some(2), 0x1234,)
);
});
}
@ -2526,7 +2832,17 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(5, AddrMode::WordDisplacementDeferred, Data::Byte, None, Some(2), 0x4050,));
assert_eq!(
cpu.ir.operands[0],
Operand::new(
5,
AddrMode::WordDisplacementDeferred,
Data::Byte,
None,
Some(2),
0x4050,
)
);
});
}
@ -2536,7 +2852,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(3, AddrMode::HalfwordDisplacement, Data::Byte, None, Some(2), 0x1234,));
assert_eq!(
cpu.ir.operands[0],
Operand::new(3, AddrMode::HalfwordDisplacement, Data::Byte, None, Some(2), 0x1234,)
);
});
}
@ -2548,7 +2867,14 @@ mod tests {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(3, AddrMode::HalfwordDisplacementDeferred, Data::Byte, None, Some(2), 0x4050,)
Operand::new(
3,
AddrMode::HalfwordDisplacementDeferred,
Data::Byte,
None,
Some(2),
0x4050,
)
);
});
}
@ -2559,7 +2885,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(2, AddrMode::ByteDisplacement, Data::Byte, None, Some(1), 6));
assert_eq!(
cpu.ir.operands[0],
Operand::new(2, AddrMode::ByteDisplacement, Data::Byte, None, Some(1), 6)
);
});
}
@ -2569,7 +2898,17 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(2, AddrMode::ByteDisplacementDeferred, Data::Byte, None, Some(2), 0x30));
assert_eq!(
cpu.ir.operands[0],
Operand::new(
2,
AddrMode::ByteDisplacementDeferred,
Data::Byte,
None,
Some(2),
0x30
)
);
});
}
@ -2581,8 +2920,21 @@ mod tests {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_descriptor_operand(&mut bus, 1, Data::Byte, None, BASE + 3, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(2, AddrMode::Register, Data::Byte, Some(Data::SByte), Some(0), 0,));
assert_eq!(cpu.ir.operands[1], Operand::new(3, AddrMode::ByteDisplacement, Data::Byte, Some(Data::UHalf), Some(1), 4,));
assert_eq!(
cpu.ir.operands[0],
Operand::new(2, AddrMode::Register, Data::Byte, Some(Data::SByte), Some(0), 0,)
);
assert_eq!(
cpu.ir.operands[1],
Operand::new(
3,
AddrMode::ByteDisplacement,
Data::Byte,
Some(Data::UHalf),
Some(1),
4,
)
);
});
}
@ -2592,7 +2944,10 @@ mod tests {
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::NegativeLiteral, Data::Byte, None, None, 0xff));
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::NegativeLiteral, Data::Byte, None, None, 0xff)
);
});
}
@ -2625,7 +2980,14 @@ mod tests {
cpu.decode_instruction(bus).unwrap();
let expected_operands = vec![
Operand::new(2, AddrMode::Register, Data::Byte, Some(Data::SByte), Some(0), 0),
Operand::new(3, AddrMode::ByteDisplacement, Data::Byte, Some(Data::UHalf), Some(1), 4),
Operand::new(
3,
AddrMode::ByteDisplacement,
Data::Byte,
Some(Data::UHalf),
Some(1),
4,
),
];
assert_instruction(cpu, 0x87, 6, "MOVB", Data::Byte);
assert_eq!(cpu.ir.operands[0], expected_operands[0]);
@ -2635,7 +2997,14 @@ mod tests {
cpu.set_pc((BASE + 6) as u32);
cpu.decode_instruction(bus).unwrap();
let expected_operands = vec![
Operand::new(2, AddrMode::ByteDisplacementDeferred, Data::Byte, None, Some(2), 0x30),
Operand::new(
2,
AddrMode::ByteDisplacementDeferred,
Data::Byte,
None,
Some(2),
0x30,
),
Operand::new(1, AddrMode::Register, Data::Byte, None, Some(3), 0),
];
assert_instruction(cpu, 0x87, 4, "MOVB", Data::Byte);
@ -2651,7 +3020,8 @@ mod tests {
let program = [0x87, 0xe7, 0x40, 0xe2, 0x41]; // MOVB {sbyte}%r0,{uhalf}%r1
do_with_program(&program, |cpu, mut bus| {
cpu.r[0] = 0xff;
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false)
.unwrap();
assert_eq!(0xffffffff, cpu.read_op(bus, 0).unwrap());
});
}
@ -2660,7 +3030,8 @@ mod tests {
let program = [0x87, 0x40, 0x41]; // MOVB %r0,%r1
do_with_program(&program, |cpu, mut bus| {
cpu.r[0] = 0xff;
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false)
.unwrap();
assert_eq!(0xff, cpu.read_op(bus, 0).unwrap());
});
}

View File

@ -1,14 +1,14 @@
#![allow(clippy::unreadable_literal)]
use crate::bus::{Bus, AccessCode};
use crate::bus::{AccessCode, Bus};
use crate::cpu::Cpu;
use crate::err::BusError;
use crate::rom_hi::HI_ROM;
use crate::rom_lo::LO_ROM;
use libc::*;
use std::ptr;
use std::sync::Mutex;
use std::{ffi::CStr, ptr};
lazy_static! {
static ref DMD: Mutex<Dmd> = Mutex::new(Dmd::new());
@ -40,6 +40,14 @@ impl Dmd {
}
}
pub fn trace_on(&mut self, name: &str) -> std::io::Result<()> {
self.bus.trace_on(name)
}
pub fn trace_off(&mut self) {
self.bus.trace_off()
}
pub fn reset(&mut self) -> Result<(), BusError> {
self.bus.load(0, &LO_ROM)?;
self.bus.load(0x10000, &HI_ROM)?;
@ -140,23 +148,19 @@ impl Dmd {
#[no_mangle]
fn dmd_reset() -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
match dmd.reset() {
Ok(()) => SUCCESS,
Err(_) => ERROR
}
}
Err(_) => ERROR
Ok(mut dmd) => match dmd.reset() {
Ok(()) => SUCCESS,
Err(_) => ERROR,
},
Err(_) => ERROR,
}
}
#[no_mangle]
fn dmd_video_ram() -> *const u8 {
match DMD.lock() {
Ok(dmd) => {
dmd.video_ram().as_ptr()
}
Err(_) => ptr::null()
Ok(dmd) => dmd.video_ram().as_ptr(),
Err(_) => ptr::null(),
}
}
@ -167,7 +171,21 @@ fn dmd_step() -> c_int {
dmd.step();
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
#[no_mangle]
fn dmd_trace_on(file_name: &CStr) -> c_int {
match DMD.lock() {
Ok(mut dmd) => match file_name.to_str() {
Ok(file_name) => match dmd.trace_on(file_name) {
Ok(()) => SUCCESS,
Err(_) => ERROR,
},
Err(_) => ERROR,
},
Err(_) => ERROR,
}
}
@ -177,8 +195,8 @@ fn dmd_step_loop(steps: usize) -> c_int {
Ok(mut dmd) => {
dmd.run(steps);
SUCCESS
},
Err(_) => ERROR
}
Err(_) => ERROR,
}
}
@ -188,8 +206,8 @@ fn dmd_get_pc(pc: &mut u32) -> c_int {
Ok(dmd) => {
*pc = dmd.get_pc();
SUCCESS
},
Err(_) => ERROR
}
Err(_) => ERROR,
}
}
@ -199,40 +217,36 @@ fn dmd_get_register(reg: u8, val: &mut u32) -> c_int {
Ok(dmd) => {
*val = dmd.get_register(reg);
SUCCESS
},
Err(_) => ERROR
}
Err(_) => ERROR,
}
}
#[no_mangle]
fn dmd_read_word(addr: u32, val: &mut u32) -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
match dmd.read_word(addr as usize) {
Some(word) => {
*val = word;
SUCCESS
},
None => ERROR
Ok(mut dmd) => match dmd.read_word(addr as usize) {
Some(word) => {
*val = word;
SUCCESS
}
None => ERROR,
},
Err(_) => ERROR
Err(_) => ERROR,
}
}
#[no_mangle]
fn dmd_read_byte(addr: u32, val: &mut u8) -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
match dmd.read_byte(addr as usize) {
Some(byte) => {
*val = byte;
SUCCESS
},
None => ERROR
Ok(mut dmd) => match dmd.read_byte(addr as usize) {
Some(byte) => {
*val = byte;
SUCCESS
}
None => ERROR,
},
Err(_) => ERROR
Err(_) => ERROR,
}
}
@ -243,7 +257,7 @@ fn dmd_get_duart_output_port(oport: &mut u8) -> c_int {
*oport = dmd.duart_output();
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
@ -254,7 +268,7 @@ fn dmd_rx_char(c: u8) -> c_int {
dmd.rx_char(c as u8);
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
@ -265,7 +279,7 @@ fn dmd_rx_keyboard(c: u8) -> c_int {
dmd.rx_keyboard(c);
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
@ -276,7 +290,7 @@ fn dmd_mouse_move(x: u16, y: u16) -> c_int {
dmd.mouse_move(x, y);
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
@ -287,7 +301,7 @@ fn dmd_mouse_down(button: u8) -> c_int {
dmd.mouse_down(button);
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
@ -298,39 +312,35 @@ fn dmd_mouse_up(button: u8) -> c_int {
dmd.mouse_up(button);
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
#[no_mangle]
fn dmd_rs232_tx_poll(tx_char: &mut u8) -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
match dmd.rs232_tx_poll() {
Some(c) => {
*tx_char = c;
SUCCESS
}
None => BUSY
Ok(mut dmd) => match dmd.rs232_tx_poll() {
Some(c) => {
*tx_char = c;
SUCCESS
}
}
Err(_) => ERROR
None => BUSY,
},
Err(_) => ERROR,
}
}
#[no_mangle]
fn dmd_kb_tx_poll(tx_char: &mut u8) -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
match dmd.kb_tx_poll() {
Some(c) => {
*tx_char = c;
SUCCESS
}
None => BUSY
Ok(mut dmd) => match dmd.kb_tx_poll() {
Some(c) => {
*tx_char = c;
SUCCESS
}
}
Err(_) => ERROR
None => BUSY,
},
Err(_) => ERROR,
}
}
@ -341,7 +351,7 @@ fn dmd_set_nvram(nvram: &[u8; 8192]) -> c_int {
dmd.set_nvram(nvram);
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}
@ -352,7 +362,7 @@ fn dmd_get_nvram(nvram: &mut [u8; 8192]) -> c_int {
nvram.clone_from_slice(dmd.get_nvram());
SUCCESS
}
Err(_) => ERROR
Err(_) => ERROR,
}
}

View File

@ -4,33 +4,31 @@ use crate::bus::AccessCode;
use crate::bus::Device;
use crate::err::BusError;
use std::collections::VecDeque;
use std::fmt::Debug;
use std::fmt::Error;
use std::fmt::Formatter;
use std::ops::Range;
use std::time::Duration;
use std::time::Instant;
use std::collections::VecDeque;
const START_ADDR: usize = 0x200000;
const END_ADDR: usize = 0x2000040;
const ADDRESS_RANGE: Range<usize> = START_ADDR..END_ADDR;
// Vertical blanks should occur at 60Hz. This value is in nanoseconds
const VERTICAL_BLANK_DELAY: u32 = 16_666_666; // 60 Hz
const VERTICAL_BLANK_DELAY: u32 = 16_666_666; // 60 Hz
// Delay rates, in nanoseconds, selected when ACR[7] = 0
const DELAY_RATES_A: [u32;13] = [
160000000, 72727272, 59259260, 40000000,
26666668, 13333334, 6666667, 7619047,
3333333, 1666666, 1111111, 833333, 208333
const DELAY_RATES_A: [u32; 13] = [
160000000, 72727272, 59259260, 40000000, 26666668, 13333334, 6666667, 7619047, 3333333,
1666666, 1111111, 833333, 208333,
];
// Delay rates, in nanoseconds, selected when ACR[7] = 1
const DELAY_RATES_B: [u32;13] = [
106666672, 72727272, 59259260, 53333336,
26666668, 13333334, 6666667, 4000000,
3333333, 1666666, 4444444, 833333, 416666
const DELAY_RATES_B: [u32; 13] = [
106666672, 72727272, 59259260, 53333336, 26666668, 13333334, 6666667, 4000000, 3333333,
1666666, 4444444, 833333, 416666,
];
const PORT_0: usize = 0;
@ -53,7 +51,6 @@ const IP_OPCR: u8 = 0x37;
const OPBITS_SET: u8 = 0x3b;
const OPBITS_RESET: u8 = 0x3f;
//
// Port Configuration Bits
//
@ -96,7 +93,7 @@ const TX_INT: u8 = 0x10;
const RX_INT: u8 = 0x20;
struct Port {
mode: [u8;2],
mode: [u8; 2],
stat: u8,
conf: u8,
rx_data: u8,
@ -142,7 +139,7 @@ pub struct Duart {
istat: u8,
imr: u8,
ivec: u8,
next_vblank: Instant
next_vblank: Instant,
}
impl Default for Duart {
@ -154,10 +151,7 @@ impl Default for Duart {
impl Duart {
pub fn new() -> Duart {
Duart {
ports: [
Port::new(),
Port::new(),
],
ports: [Port::new(), Port::new()],
acr: 0,
ipcr: 0x40,
inprt: 0xb,
@ -216,9 +210,10 @@ impl Duart {
_ => (ISTS_TBI, ISTS_RBI),
};
if (ctx.conf & CNF_ETX) != 0 &&
(ctx.stat & STS_TXR) == 0 &&
(ctx.stat & STS_TXE) == 0 && Instant::now() >= ctx.next_tx
if (ctx.conf & CNF_ETX) != 0
&& (ctx.stat & STS_TXR) == 0
&& (ctx.stat & STS_TXE) == 0
&& Instant::now() >= ctx.next_tx
{
let c = ctx.tx_data;
ctx.stat |= STS_TXR;
@ -395,7 +390,7 @@ impl Duart {
ctx.stat |= STS_TXE;
ctx.conf &= !CNF_ETX;
}
4 => ctx.stat &= !(STS_FER|STS_PER|STS_OER),
4 => ctx.stat &= !(STS_FER | STS_PER | STS_OER),
_ => {}
}
}
@ -428,9 +423,7 @@ impl Device for Duart {
ctx.mode_ptr = (ctx.mode_ptr + 1) % 2;
Ok(val)
}
CSRA => {
Ok(self.ports[PORT_0].stat)
}
CSRA => Ok(self.ports[PORT_0].stat),
THRA => {
let mut ctx = &mut self.ports[PORT_0];
ctx.stat &= !STS_RXR;
@ -445,18 +438,14 @@ impl Device for Duart {
self.istat &= !ISTS_IPC;
Ok(result)
}
ISR_MASK => {
Ok(self.istat)
}
ISR_MASK => Ok(self.istat),
MR12B => {
let mut ctx = &mut self.ports[PORT_1];
let val = ctx.mode[ctx.mode_ptr];
ctx.mode_ptr = (ctx.mode_ptr + 1) % 2;
Ok(val)
}
CSRB => {
Ok(self.ports[PORT_1].stat)
}
CSRB => Ok(self.ports[PORT_1].stat),
THRB => {
let mut ctx = &mut self.ports[PORT_1];
ctx.stat &= !STS_RXR;
@ -464,9 +453,7 @@ impl Device for Duart {
self.ivec &= !KEYBOARD_INT;
Ok(ctx.rx_data)
}
IP_OPCR => {
Ok(self.inprt)
}
IP_OPCR => Ok(self.inprt),
_ => Ok(0),
}
}

View File

@ -1,14 +1,14 @@
pub mod bus;
pub mod cpu;
pub mod dmd;
pub mod duart;
pub mod err;
pub mod instr;
pub mod mem;
pub mod duart;
pub mod mouse;
pub mod rom_hi;
pub mod rom_lo;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate libc;

View File

@ -6,9 +6,9 @@ use crate::err::BusError;
use std::fmt::Debug;
use std::fmt::Error;
use std::fmt::Formatter;
use std::ops::Range;
use std::ops::{Index, IndexMut};
use std::vec::Vec;
use std::ops::Range;
pub struct Mem {
address_range: Range<usize>,
@ -21,7 +21,7 @@ pub struct Mem {
impl Mem {
pub fn new(start_address: usize, len: usize, is_read_only: bool) -> Mem {
Mem {
address_range: start_address..start_address+len,
address_range: start_address..start_address + len,
len,
ram: vec![0; len],
is_read_only,
@ -91,7 +91,7 @@ impl Device for Mem {
u32::from(self.ram[offset]).wrapping_shl(24)
| u32::from(self.ram[offset + 1]).wrapping_shl(16)
| u32::from(self.ram[offset + 2]).wrapping_shl(8)
| u32::from(self.ram[offset + 3])
| u32::from(self.ram[offset + 3]),
)
}
}

View File

@ -1,7 +1,7 @@
#![allow(clippy::unreadable_literal)]
use crate::bus::Device;
use crate::bus::AccessCode;
use crate::bus::Device;
use crate::err::BusError;
use std::ops::Range;
@ -48,7 +48,7 @@ impl Device for Mouse {
}
fn read_half(&mut self, address: usize, _access: AccessCode) -> Result<u16, BusError> {
match address-START_ADDRESS {
match address - START_ADDRESS {
0 => Ok(self.y),
2 => Ok(self.x),
_ => Err(BusError::NoDevice(address as u32)),
@ -59,19 +59,34 @@ impl Device for Mouse {
unimplemented!()
}
fn write_byte(&mut self, _address: usize, _val: u8, _access: AccessCode) -> Result<(), BusError> {
fn write_byte(
&mut self,
_address: usize,
_val: u8,
_access: AccessCode,
) -> Result<(), BusError> {
unimplemented!()
}
fn write_half(&mut self, _address: usize, _val: u16, _access: AccessCode) -> Result<(), BusError> {
fn write_half(
&mut self,
_address: usize,
_val: u16,
_access: AccessCode,
) -> Result<(), BusError> {
unimplemented!()
}
fn write_word(&mut self, _address: usize, _val: u32, _access: AccessCode) -> Result<(), BusError> {
fn write_word(
&mut self,
_address: usize,
_val: u32,
_access: AccessCode,
) -> Result<(), BusError> {
unimplemented!()
}
fn load(&mut self, _address: usize, _data: &[u8]) -> Result<(), BusError> {
unimplemented!()
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff