Fixed: Cleanups suggested by Clippy
This commit is contained in:
parent
bc7d1cf529
commit
2da0a49574
28
src/bus.rs
28
src/bus.rs
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
use crate::err::BusError;
|
||||
use crate::mem::Mem;
|
||||
use crate::duart::Duart;
|
||||
|
@ -124,17 +126,17 @@ impl Bus {
|
|||
pub fn read_op_half(&mut self, address: usize) -> Result<u16, BusError> {
|
||||
let m = self.get_device(address)?;
|
||||
|
||||
Ok((m.read_byte(address, AccessCode::OperandFetch)? as u16)
|
||||
| (m.read_byte(address + 1, AccessCode::OperandFetch)? as u16).wrapping_shl(8))
|
||||
Ok(u16::from(m.read_byte(address, AccessCode::OperandFetch)?)
|
||||
| u16::from(m.read_byte(address + 1, AccessCode::OperandFetch)?).wrapping_shl(8))
|
||||
}
|
||||
|
||||
pub fn read_op_word(&mut self, address: usize) -> Result<u32, BusError> {
|
||||
let m = self.get_device(address)?;
|
||||
|
||||
Ok((m.read_byte(address, AccessCode::OperandFetch)? as u32)
|
||||
| (m.read_byte(address + 1, AccessCode::OperandFetch)? as u32).wrapping_shl(8)
|
||||
| (m.read_byte(address + 2, AccessCode::OperandFetch)? as u32).wrapping_shl(16)
|
||||
| (m.read_byte(address + 3, AccessCode::OperandFetch)? as u32).wrapping_shl(24))
|
||||
Ok(u32::from(m.read_byte(address, AccessCode::OperandFetch)?)
|
||||
| u32::from(m.read_byte(address + 1, AccessCode::OperandFetch)?).wrapping_shl(8)
|
||||
| u32::from(m.read_byte(address + 2, AccessCode::OperandFetch)?).wrapping_shl(16)
|
||||
| u32::from(m.read_byte(address + 3, AccessCode::OperandFetch)?).wrapping_shl(24))
|
||||
}
|
||||
|
||||
pub fn write_byte(&mut self, address: usize, val: u8) -> Result<(), BusError> {
|
||||
|
@ -159,7 +161,7 @@ impl Bus {
|
|||
self.get_device(address)?.load(address, data)
|
||||
}
|
||||
|
||||
pub fn video_ram(&self) -> Result<&[u8], BusError> {
|
||||
pub fn video_ram(&self) -> &[u8] {
|
||||
self.ram.as_slice(0x0..0x19000)
|
||||
}
|
||||
|
||||
|
@ -204,17 +206,11 @@ impl Bus {
|
|||
self.duart.output_port()
|
||||
}
|
||||
|
||||
pub fn get_nvram(&self) -> [u8; NVRAM_SIZE] {
|
||||
let mut contents: [u8; NVRAM_SIZE] = [0u8; NVRAM_SIZE];
|
||||
|
||||
for i in 0..NVRAM_SIZE {
|
||||
contents[i] = self.bbram[i];
|
||||
}
|
||||
|
||||
contents
|
||||
pub fn get_nvram(&self) -> &[u8] {
|
||||
self.bbram.as_slice(0..NVRAM_SIZE)
|
||||
}
|
||||
|
||||
pub fn set_nvram(&mut self, nvram: &[u8; NVRAM_SIZE]) {
|
||||
pub fn set_nvram(&mut self, nvram: &[u8]) {
|
||||
for (i, b) in nvram.into_iter().enumerate() {
|
||||
self.bbram[i] = *b;
|
||||
}
|
||||
|
|
113
src/cpu.rs
113
src/cpu.rs
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
use crate::bus::{AccessCode, Bus};
|
||||
use crate::err::*;
|
||||
use crate::instr::*;
|
||||
|
@ -191,11 +193,11 @@ macro_rules! mn {
|
|||
}
|
||||
|
||||
fn sign_extend_halfword(data: u16) -> u32 {
|
||||
((data as i16) as i32) as u32
|
||||
i32::from(data as i16) as u32
|
||||
}
|
||||
|
||||
fn sign_extend_byte(data: u8) -> u32 {
|
||||
((data as i8) as i32) as u32
|
||||
i32::from(data as i8) as u32
|
||||
}
|
||||
|
||||
fn add_offset(val: u32, offset: u32) -> u32 {
|
||||
|
@ -403,6 +405,12 @@ pub struct Cpu {
|
|||
ir: Instruction,
|
||||
}
|
||||
|
||||
impl Default for Cpu {
|
||||
fn default() -> Self {
|
||||
Cpu::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Cpu {
|
||||
pub fn new() -> Cpu {
|
||||
Cpu {
|
||||
|
@ -542,8 +550,8 @@ impl Cpu {
|
|||
match op.data_type() {
|
||||
Data::Word | Data::UWord => self.r[r],
|
||||
Data::Half => sign_extend_halfword(self.r[r] as u16),
|
||||
Data::UHalf => (self.r[r] as u16) as u32,
|
||||
Data::Byte => (self.r[r] as u8) as u32,
|
||||
Data::UHalf => u32::from(self.r[r] as u16),
|
||||
Data::Byte => u32::from(self.r[r] as u8),
|
||||
Data::SByte => sign_extend_byte(self.r[r] as u8),
|
||||
_ => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
|
||||
}
|
||||
|
@ -557,8 +565,8 @@ impl Cpu {
|
|||
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::UHalf => bus.read_half(eff as usize, AccessCode::InstrFetch)? as u32,
|
||||
Data::Byte => bus.read_byte(eff as usize, AccessCode::InstrFetch)? as u32,
|
||||
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)?),
|
||||
_ => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
|
||||
}
|
||||
|
@ -684,7 +692,7 @@ impl Cpu {
|
|||
}
|
||||
|
||||
fn add(&mut self, bus: &mut Bus, a: u32, b: u32, dst: usize) -> Result<(), CpuError> {
|
||||
let result: u64 = (a as u64).wrapping_add(b as u64);
|
||||
let result: u64 = u64::from(a).wrapping_add(u64::from(b));
|
||||
|
||||
self.write_op(bus, dst, result as u32)?;
|
||||
|
||||
|
@ -714,7 +722,7 @@ impl Cpu {
|
|||
}
|
||||
|
||||
fn sub(&mut self, bus: &mut Bus, a: u32, b: u32, dst: usize) -> Result<(), CpuError> {
|
||||
let result: u64 = (a as u64).wrapping_sub(b as u64);
|
||||
let result: u64 = u64::from(a).wrapping_sub(u64::from(b));
|
||||
|
||||
self.write_op(bus, dst, result as u32)?;
|
||||
|
||||
|
@ -731,8 +739,8 @@ impl Cpu {
|
|||
Data::Half => (b as i16 / a as i16) as u32,
|
||||
Data::SByte => (b as i8 / a as i8) as u32,
|
||||
Data::UWord => b / a,
|
||||
Data::UHalf => (b as u16 / a as u16) as u32,
|
||||
Data::Byte => (b as u8 / a as u8) as u32,
|
||||
Data::UHalf => u32::from(b as u16 / a as u16),
|
||||
Data::Byte => u32::from(b as u8 / a as u8),
|
||||
_ => b / a,
|
||||
}
|
||||
}
|
||||
|
@ -743,15 +751,15 @@ impl Cpu {
|
|||
Data::Half => (b as i16 % a as i16) as u32,
|
||||
Data::SByte => (b as i8 % a as i8) as u32,
|
||||
Data::UWord => b % a,
|
||||
Data::UHalf => (b as u16 % a as u16) as u32,
|
||||
Data::Byte => (b as u8 % a as u8) as u32,
|
||||
Data::UHalf => u32::from(b as u16 % a as u16),
|
||||
Data::Byte => u32::from(b as u8 % a as u8),
|
||||
_ => b % a,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove unwraps
|
||||
fn on_interrupt(&mut self, bus: &mut Bus, vector: u8) {
|
||||
let new_pcbp = bus.read_word((0x8c + (4 * (vector as u32))) 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);
|
||||
|
@ -767,26 +775,22 @@ impl Cpu {
|
|||
self.context_switch_3(bus).unwrap();
|
||||
}
|
||||
|
||||
#[allow(clippy::cyclomatic_complexity)]
|
||||
fn dispatch(&mut self, bus: &mut Bus) -> Result<i32, CpuError> {
|
||||
self.steps += 1;
|
||||
|
||||
// Update anything that needs updating.
|
||||
bus.service();
|
||||
|
||||
let interrupt: Option<u8> = bus.get_interrupts();
|
||||
|
||||
match interrupt {
|
||||
Some(val) => {
|
||||
let cpu_ipl = (self.r[R_PSW]) >> 13 & 0xf;
|
||||
if cpu_ipl < IPL_TABLE[(val & 0x3f) as usize] {
|
||||
self.on_interrupt(bus, (!val) & 0x3f);
|
||||
}
|
||||
if let Some(val) = bus.get_interrupts() {
|
||||
let cpu_ipl = (self.r[R_PSW]) >> 13 & 0xf;
|
||||
if cpu_ipl < IPL_TABLE[(val & 0x3f) as usize] {
|
||||
self.on_interrupt(bus, (!val) & 0x3f);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
self.decode_instruction(bus)?;
|
||||
let mut pc_increment: i32 = self.ir.bytes as i32;
|
||||
let mut pc_increment: i32 = i32::from(self.ir.bytes);
|
||||
|
||||
match self.ir.opcode {
|
||||
NOP => {
|
||||
|
@ -811,7 +815,7 @@ impl Cpu {
|
|||
ALSW3 => {
|
||||
let a = self.read_op(bus, 0)?;
|
||||
let b = self.read_op(bus, 1)?;
|
||||
let result = (b as u64) << (a & 0x1f);
|
||||
let result = u64::from(b) << (a & 0x1f);
|
||||
self.write_op(bus, 2, result as u32)?;
|
||||
|
||||
self.set_nz_flags(result as u32, 2);
|
||||
|
@ -1218,15 +1222,15 @@ impl Cpu {
|
|||
(1 << width) - 1
|
||||
};
|
||||
|
||||
mask = mask << offset;
|
||||
mask <<= offset;
|
||||
|
||||
if width + offset > 32 {
|
||||
mask |= 1 << ((width + offset) - 32) - 1;
|
||||
mask |= (1 << ((width + offset) - 32)) - 1;
|
||||
}
|
||||
|
||||
let mut a = self.read_op(bus, 2)?;
|
||||
a &= mask;
|
||||
a = a >> offset;
|
||||
a >>= offset;
|
||||
|
||||
self.write_op(bus, 3, a)?;
|
||||
self.set_nz_flags(a, 3);
|
||||
|
@ -1269,7 +1273,7 @@ impl Cpu {
|
|||
pc_increment = 0;
|
||||
}
|
||||
LLSW3 | LLSH3 | LLSB3 => {
|
||||
let a: u64 = self.read_op(bus, 1)? as u64;
|
||||
let a: u64 = u64::from(self.read_op(bus, 1)?);
|
||||
let b = self.read_op(bus, 0)? & 0x1f;
|
||||
|
||||
let result = (a << b) as u32;
|
||||
|
@ -1286,8 +1290,8 @@ impl Cpu {
|
|||
Data::Word => (a as i32 >> b as i32) as u32,
|
||||
Data::UWord => a >> b,
|
||||
Data::Half => (a as i16 >> b as i16) as u32,
|
||||
Data::UHalf => (a as u16 >> b as u16) as u32,
|
||||
Data::Byte => (a as u8 >> b as u8) as u32,
|
||||
Data::UHalf => u32::from(a as u16 >> b as u16),
|
||||
Data::Byte => u32::from(a as u8 >> b as u8),
|
||||
Data::SByte => (a as i8 >> b as i8) as u32,
|
||||
_ => 0,
|
||||
};
|
||||
|
@ -1598,7 +1602,7 @@ impl Cpu {
|
|||
stack_offset += 4;
|
||||
}
|
||||
|
||||
self.r[R_SP] = self.r[R_SP] + 28;
|
||||
self.r[R_SP] += 28;
|
||||
self.r[R_FP] = self.r[R_SP];
|
||||
}
|
||||
SUBW2 | SUBH2 | SUBB2 => {
|
||||
|
@ -1687,7 +1691,7 @@ impl Cpu {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn on_exception(&mut self, bus: &mut Bus, exc: ExceptionType) -> Result<(), CpuError> {
|
||||
fn on_exception(&mut self, bus: &mut Bus, exc: &ExceptionType) -> Result<(), CpuError> {
|
||||
let (et, isc) = match exc {
|
||||
ExceptionType::ExternalMemory => (3, 5)
|
||||
};
|
||||
|
@ -1733,7 +1737,7 @@ impl Cpu {
|
|||
Err(CpuError::Bus(BusError::NoDevice(_)))
|
||||
| Err(CpuError::Bus(BusError::Read(_)))
|
||||
| Err(CpuError::Bus(BusError::Write(_))) => {
|
||||
self.on_exception(bus, ExceptionType::ExternalMemory).unwrap();
|
||||
self.on_exception(bus, &ExceptionType::ExternalMemory).unwrap();
|
||||
}
|
||||
Err(CpuError::Exception(CpuException::IllegalOpcode)) => {}
|
||||
Err(CpuError::Exception(CpuException::InvalidDescriptor)) => {}
|
||||
|
@ -1756,6 +1760,7 @@ impl Cpu {
|
|||
self.r[R_PC] = val;
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn set_operand(
|
||||
&mut self,
|
||||
index: usize,
|
||||
|
@ -1782,11 +1787,11 @@ impl Cpu {
|
|||
match mn.dtype {
|
||||
Data::Byte => {
|
||||
let b: u8 = bus.read_byte(addr, AccessCode::OperandFetch)?;
|
||||
self.set_operand(index, 1, AddrMode::None, Data::Byte, None, None, b as u32);
|
||||
self.set_operand(index, 1, AddrMode::None, Data::Byte, None, None, u32::from(b));
|
||||
}
|
||||
Data::Half => {
|
||||
let h: u16 = bus.read_op_half(addr)?;
|
||||
self.set_operand(index, 2, AddrMode::None, Data::Half, None, None, h as u32);
|
||||
self.set_operand(index, 2, AddrMode::None, Data::Half, None, None, u32::from(h));
|
||||
}
|
||||
Data::Word => {
|
||||
let w: u32 = bus.read_op_word(addr)?;
|
||||
|
@ -1824,7 +1829,7 @@ impl Cpu {
|
|||
match m {
|
||||
0 | 1 | 2 | 3 => {
|
||||
// Positive Literal
|
||||
self.set_operand(index, dsize, AddrMode::PositiveLiteral, dtype, etype, None, descriptor_byte as u32);
|
||||
self.set_operand(index, dsize, AddrMode::PositiveLiteral, dtype, etype, None, u32::from(descriptor_byte));
|
||||
}
|
||||
4 => {
|
||||
match r {
|
||||
|
@ -1844,7 +1849,7 @@ impl Cpu {
|
|||
15 => {
|
||||
// Halfword Immediate
|
||||
let h = bus.read_op_half(addr + 1)?;
|
||||
self.set_operand(index, dsize + 2, AddrMode::HalfwordImmediate, dtype, etype, None, h as u32);
|
||||
self.set_operand(index, dsize + 2, AddrMode::HalfwordImmediate, dtype, etype, None, u32::from(h));
|
||||
}
|
||||
11 => {
|
||||
// Illegal
|
||||
|
@ -1861,11 +1866,11 @@ 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, b as u32);
|
||||
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), r as u32);
|
||||
self.set_operand(index, dsize, AddrMode::FPShortOffset, dtype, etype, Some(R_FP), u32::from(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1878,7 +1883,7 @@ impl Cpu {
|
|||
}
|
||||
_ => {
|
||||
// AP Short Offset
|
||||
self.set_operand(index, dsize, AddrMode::APShortOffset, dtype, etype, Some(R_AP), r as u32);
|
||||
self.set_operand(index, dsize, AddrMode::APShortOffset, dtype, etype, Some(R_AP), u32::from(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1908,7 +1913,7 @@ impl Cpu {
|
|||
_ => {
|
||||
// Halfword Displacement
|
||||
let disp = bus.read_op_half(addr + 1)?;
|
||||
self.set_operand(index, dsize + 2, AddrMode::HalfwordDisplacement, dtype, etype, Some(r as usize), disp as u32);
|
||||
self.set_operand(index, dsize + 2, AddrMode::HalfwordDisplacement, dtype, etype, Some(r as usize), u32::from(disp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1925,7 +1930,7 @@ impl Cpu {
|
|||
dtype,
|
||||
etype,
|
||||
Some(r as usize),
|
||||
disp as u32,
|
||||
u32::from(disp),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1936,7 +1941,7 @@ impl Cpu {
|
|||
_ => {
|
||||
// Byte Displacement
|
||||
let disp = bus.read_byte(addr + 1, AccessCode::OperandFetch)?;
|
||||
self.set_operand(index, dsize + 1, AddrMode::ByteDisplacement, dtype, etype, Some(r as usize), disp as u32);
|
||||
self.set_operand(index, dsize + 1, AddrMode::ByteDisplacement, dtype, etype, Some(r as usize), u32::from(disp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1946,7 +1951,7 @@ impl Cpu {
|
|||
_ => {
|
||||
// Byte Displacement Deferred
|
||||
let disp = bus.read_byte(addr + 1, AccessCode::OperandFetch)?;
|
||||
self.set_operand(index, dsize + 1, AddrMode::ByteDisplacementDeferred, dtype, etype, Some(r as usize), disp as u32);
|
||||
self.set_operand(index, dsize + 1, AddrMode::ByteDisplacementDeferred, dtype, etype, Some(r as usize), u32::from(disp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1965,7 +1970,7 @@ impl Cpu {
|
|||
},
|
||||
15 => {
|
||||
// Negative Literal
|
||||
self.set_operand(index, 1, AddrMode::NegativeLiteral, dtype, etype, None, descriptor_byte as u32);
|
||||
self.set_operand(index, 1, AddrMode::NegativeLiteral, dtype, etype, None, u32::from(descriptor_byte));
|
||||
},
|
||||
_ => { return Err(CpuError::Exception(CpuException::IllegalOpcode)); }
|
||||
};
|
||||
|
@ -1979,11 +1984,11 @@ impl Cpu {
|
|||
bus: &mut Bus,
|
||||
index: usize,
|
||||
mn: &Mnemonic,
|
||||
ot: &OpType,
|
||||
ot: OpType,
|
||||
etype: Option<Data>,
|
||||
addr: usize,
|
||||
) -> Result<(), CpuError> {
|
||||
match *ot {
|
||||
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),
|
||||
}
|
||||
|
@ -2008,9 +2013,9 @@ impl Cpu {
|
|||
// Special case for half-word opcodes
|
||||
let b2 = bus.read_byte(addr, AccessCode::InstrFetch)?;
|
||||
addr += 1;
|
||||
((b1 as u16) << 8) | b2 as u16
|
||||
(u16::from(b1) << 8) | u16::from(b2)
|
||||
} else {
|
||||
b1 as u16
|
||||
u16::from(b1)
|
||||
};
|
||||
|
||||
let mn = MNEMONICS.get(&index);
|
||||
|
@ -2023,7 +2028,7 @@ impl Cpu {
|
|||
|
||||
for (index, ot) in mn.ops.iter().enumerate() {
|
||||
// Push a decoded operand
|
||||
self.decode_operand(bus, index, mn, ot, etype, addr)?;
|
||||
self.decode_operand(bus, index, mn, *ot, etype, addr)?;
|
||||
etype = self.ir.operands[index].expanded_type;
|
||||
addr += self.ir.operands[index].size as usize;
|
||||
}
|
||||
|
@ -2039,7 +2044,7 @@ impl Cpu {
|
|||
None => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
|
||||
}
|
||||
|
||||
return Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convenience operations on flags.
|
||||
|
@ -2062,11 +2067,11 @@ impl Cpu {
|
|||
}
|
||||
Data::Half | Data::UHalf => {
|
||||
self.set_n_flag((val & 0x8000) != 0);
|
||||
self.set_z_flag((val & 0xffff) == 0);
|
||||
self.set_z_flag(val.trailing_zeros() >= 16);
|
||||
}
|
||||
Data::Byte | Data::SByte => {
|
||||
self.set_n_flag((val & 0x80) != 0);
|
||||
self.set_z_flag((val & 0xff) == 0);
|
||||
self.set_z_flag(val.trailing_zeros() >= 8);
|
||||
}
|
||||
Data::None => {
|
||||
// Intentionally ignored
|
||||
|
@ -2724,7 +2729,7 @@ mod tests {
|
|||
let program = [0x40];
|
||||
do_with_program(&program, |cpu, mut bus| {
|
||||
cpu.r[0] = 0;
|
||||
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 0, false).unwrap();
|
||||
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE, false).unwrap();
|
||||
cpu.write_op(bus, 0, 0x5a).unwrap();
|
||||
assert_eq!(0x5a, cpu.r[0]);
|
||||
});
|
||||
|
|
26
src/dmd.rs
26
src/dmd.rs
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
use crate::bus::{Bus, AccessCode};
|
||||
use crate::cpu::Cpu;
|
||||
use crate::err::BusError;
|
||||
|
@ -22,6 +24,12 @@ pub struct Dmd {
|
|||
bus: Bus,
|
||||
}
|
||||
|
||||
impl Default for Dmd {
|
||||
fn default() -> Self {
|
||||
Dmd::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Dmd {
|
||||
pub fn new() -> Dmd {
|
||||
let cpu = Cpu::new();
|
||||
|
@ -40,7 +48,7 @@ impl Dmd {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn video_ram(&self) -> Result<&[u8], BusError> {
|
||||
pub fn video_ram(&self) -> &[u8] {
|
||||
self.bus.video_ram()
|
||||
}
|
||||
|
||||
|
@ -109,11 +117,11 @@ impl Dmd {
|
|||
self.bus.duart_output()
|
||||
}
|
||||
|
||||
pub fn set_nvram(&mut self, nvram: &[u8; 8192]) {
|
||||
pub fn set_nvram(&mut self, nvram: &[u8]) {
|
||||
self.bus.set_nvram(nvram);
|
||||
}
|
||||
|
||||
pub fn get_nvram(&self) -> [u8; 8192] {
|
||||
pub fn get_nvram(&self) -> &[u8] {
|
||||
self.bus.get_nvram()
|
||||
}
|
||||
}
|
||||
|
@ -139,10 +147,7 @@ fn dmd_reset() -> c_int {
|
|||
fn dmd_video_ram() -> *const u8 {
|
||||
match DMD.lock() {
|
||||
Ok(dmd) => {
|
||||
match dmd.video_ram() {
|
||||
Ok(video_ram) => video_ram.as_ptr(),
|
||||
Err(_) => ptr::null()
|
||||
}
|
||||
dmd.video_ram().as_ptr()
|
||||
}
|
||||
Err(_) => ptr::null()
|
||||
}
|
||||
|
@ -302,13 +307,10 @@ fn dmd_set_nvram(nvram: &[u8; 8192]) -> c_int {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
fn dmd_get_nvram(nvram: &mut [u8; 8192]) -> c_int {
|
||||
fn dmd_get_nvram(nvram: &mut [u8]) -> c_int {
|
||||
match DMD.lock() {
|
||||
Ok(dmd) => {
|
||||
let buf = dmd.get_nvram();
|
||||
for i in 0..8192 {
|
||||
nvram[i] = buf[i];
|
||||
}
|
||||
nvram.clone_from_slice(&dmd.get_nvram());
|
||||
SUCCESS
|
||||
}
|
||||
Err(_) => ERROR
|
||||
|
|
99
src/duart.rs
99
src/duart.rs
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
use crate::bus::AccessCode;
|
||||
use crate::bus::Device;
|
||||
use crate::err::BusError;
|
||||
|
@ -17,18 +19,18 @@ 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
|
||||
|
||||
// Delay rates selected when ACR[7] = 0
|
||||
// Delay rates, in nanoseconds, selected when ACR[7] = 0
|
||||
const DELAY_RATES_A: [u32;13] = [
|
||||
200000000, 90909096, 74074072, 50000000,
|
||||
33333336, 16666668, 8333334, 9523810,
|
||||
4166667, 2083333, 1388888, 1041666, 260416,
|
||||
200_000_000, 90_909_096, 74_074_072, 50_000_000,
|
||||
33_333_336, 16_666_668, 8_333_334, 9_523_810,
|
||||
4_166_667, 2_083_333, 1_388_888, 1_041_666, 260_416,
|
||||
];
|
||||
|
||||
// Delay rates selected when ACR[7] = 1
|
||||
// Delay rates, in nanoseconds, selected when ACR[7] = 1
|
||||
const DELAY_RATES_B: [u32;13] = [
|
||||
133333344, 90909096, 74074072, 66666672,
|
||||
33333336, 16666668, 8333334, 5000000,
|
||||
4166667, 205338, 5555555, 1041666, 520833,
|
||||
133_333_344, 90_909_096, 74_074_072, 66_666_672,
|
||||
33_333_336, 16_666_668, 8_333_334, 5_000_000,
|
||||
4_166_667, 205_338, 5_555_555, 1_041_666, 520_833,
|
||||
];
|
||||
|
||||
const PORT_0: usize = 0;
|
||||
|
@ -107,6 +109,30 @@ struct Port {
|
|||
next_tx: Instant,
|
||||
}
|
||||
|
||||
impl Port {
|
||||
fn new() -> Port {
|
||||
Port {
|
||||
mode: [0; 2],
|
||||
stat: 0,
|
||||
conf: 0,
|
||||
rx_data: 0,
|
||||
tx_data: 0,
|
||||
mode_ptr: 0,
|
||||
rx_queue: VecDeque::new(),
|
||||
tx_queue: VecDeque::new(),
|
||||
char_delay: Duration::new(0, 1_000_000),
|
||||
next_rx: Instant::now(),
|
||||
next_tx: Instant::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Port {
|
||||
fn default() -> Self {
|
||||
Port::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Duart {
|
||||
ports: [Port; 2],
|
||||
acr: u8,
|
||||
|
@ -119,36 +145,18 @@ pub struct Duart {
|
|||
last_vblank: Instant,
|
||||
}
|
||||
|
||||
impl Default for Duart {
|
||||
fn default() -> Self {
|
||||
Duart::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Duart {
|
||||
pub fn new() -> Duart {
|
||||
Duart {
|
||||
ports: [
|
||||
Port {
|
||||
mode: [0; 2],
|
||||
stat: 0,
|
||||
conf: 0,
|
||||
rx_data: 0,
|
||||
tx_data: 0,
|
||||
mode_ptr: 0,
|
||||
rx_queue: VecDeque::new(),
|
||||
tx_queue: VecDeque::new(),
|
||||
char_delay: Duration::new(0, 1_000_000),
|
||||
next_rx: Instant::now(),
|
||||
next_tx: Instant::now(),
|
||||
},
|
||||
Port {
|
||||
mode: [0; 2],
|
||||
stat: 0,
|
||||
conf: 0,
|
||||
rx_data: 0,
|
||||
tx_data: 0,
|
||||
mode_ptr: 0,
|
||||
rx_queue: VecDeque::new(),
|
||||
tx_queue: VecDeque::new(),
|
||||
char_delay: Duration::new(0, 1_000_000),
|
||||
next_rx: Instant::now(),
|
||||
next_tx: Instant::now(),
|
||||
},
|
||||
Port::new(),
|
||||
Port::new(),
|
||||
],
|
||||
acr: 0,
|
||||
ipcr: 0x40,
|
||||
|
@ -187,21 +195,14 @@ impl Duart {
|
|||
};
|
||||
|
||||
if !ctx.rx_queue.is_empty() && Instant::now() >= ctx.next_rx {
|
||||
match ctx.rx_queue.pop_back() {
|
||||
Some(c) => {
|
||||
if ctx.conf & CNF_ERX != 0 {
|
||||
ctx.rx_data = c;
|
||||
ctx.stat |= STS_RXR;
|
||||
self.istat |= istat;
|
||||
self.ivec |= ivec;
|
||||
} else {
|
||||
ctx.stat |= STS_OER;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
// This is really unexpected! We just asserted
|
||||
// that the queue was not empty, so this should
|
||||
// really never happen.
|
||||
if let Some(c) = ctx.rx_queue.pop_back() {
|
||||
if ctx.conf & CNF_ERX != 0 {
|
||||
ctx.rx_data = c;
|
||||
ctx.stat |= STS_RXR;
|
||||
self.istat |= istat;
|
||||
self.ivec |= ivec;
|
||||
} else {
|
||||
ctx.stat |= STS_OER;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
use crate::bus::*;
|
||||
use crate::err::BusError;
|
||||
|
||||
|
@ -26,8 +28,8 @@ impl Mem {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_slice(&self, range: Range<usize>) -> Result<&[u8], BusError> {
|
||||
Ok(&self.ram[range])
|
||||
pub fn as_slice(&self, range: Range<usize>) -> &[u8] {
|
||||
&self.ram[range]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +171,7 @@ impl Index<usize> for Mem {
|
|||
}
|
||||
|
||||
impl IndexMut<usize> for Mem {
|
||||
fn index_mut<'a>(&'a mut self, idx: usize) -> &'a mut u8 {
|
||||
fn index_mut(&'_ mut self, idx: usize) -> &'_ mut u8 {
|
||||
&mut self.ram[idx]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
use crate::bus::Device;
|
||||
use crate::bus::AccessCode;
|
||||
use crate::err::BusError;
|
||||
|
@ -13,6 +15,12 @@ pub struct Mouse {
|
|||
pub y: u16,
|
||||
}
|
||||
|
||||
impl Default for Mouse {
|
||||
fn default() -> Self {
|
||||
Mouse::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Mouse {
|
||||
pub fn new() -> Mouse {
|
||||
Mouse {
|
||||
|
|
Loading…
Reference in New Issue