Merge branch 'dev.branch'

This commit is contained in:
Seth Morabito 2022-09-03 16:45:04 -07:00
commit 0a8fc818f1
7 changed files with 264 additions and 261 deletions

View File

@ -104,7 +104,7 @@ impl Bus {
return Ok(&mut self.ram);
}
Err(BusError::NoDevice(address as u32))
Err(BusError::NoDevice(address))
}
pub fn trace_on(&mut self, name: &str) -> std::io::Result<()> {
@ -134,14 +134,14 @@ impl Bus {
pub fn read_half(&mut self, address: usize, access: AccessCode) -> Result<u16, BusError> {
if address & 1 != 0 {
return Err(BusError::Alignment);
return Err(BusError::Alignment(address));
}
self.get_device(address)?.read_half(address, access)
}
pub fn read_word(&mut self, address: usize, access: AccessCode) -> Result<u32, BusError> {
if address & 3 != 0 {
return Err(BusError::Alignment);
return Err(BusError::Alignment(address));
}
self.get_device(address)?.read_word(address, access)
}
@ -168,14 +168,14 @@ impl Bus {
pub fn write_half(&mut self, address: usize, val: u16) -> Result<(), BusError> {
if address & 1 != 0 {
return Err(BusError::Alignment);
return Err(BusError::Alignment(address));
}
self.get_device(address)?.write_half(address, val, AccessCode::Write)
}
pub fn write_word(&mut self, address: usize, val: u32) -> Result<(), BusError> {
if address & 3 != 0 {
return Err(BusError::Alignment);
return Err(BusError::Alignment(address));
}
self.get_device(address)?.write_word(address, val, AccessCode::Write)
}

View File

@ -132,6 +132,7 @@ pub struct Operand {
pub register: Option<usize>,
pub embedded: u32,
pub data: u32, // Data moved to / from operand
pub eff: u32, // Effective address (if any)
}
impl Operand {
@ -151,6 +152,7 @@ impl Operand {
register,
embedded,
data: 0,
eff: 0,
}
}
@ -184,7 +186,9 @@ pub struct Instruction {
pub opcode: u16,
pub name: &'static str,
pub data_type: Data,
pub bytes: u8,
pub len: u8,
/// The raw data decoded from the byte stream
pub data: [u8; 32],
pub operands: [Operand; 4],
}
@ -193,47 +197,47 @@ impl fmt::Display for Operand {
match self.mode {
AddrMode::None => Ok(()),
AddrMode::Absolute => {
write!(f, "0x{}", self.data)
write!(f, "0x{:x}", self.embedded)
}
AddrMode::AbsoluteDeferred => write!(f, "*$0x{:x}", self.data),
AddrMode::AbsoluteDeferred => write!(f, "*$0x{:x}", self.embedded),
AddrMode::ByteDisplacement => {
write!(f, "{}(%r{})", self.data as i8, self.register.unwrap())
write!(f, "{}(%r{})", self.embedded as i8, self.register.unwrap())
}
AddrMode::ByteDisplacementDeferred => {
write!(f, "*{}(%r{})", self.data as i8, self.register.unwrap())
write!(f, "*{}(%r{})", self.embedded as i8, self.register.unwrap())
}
AddrMode::HalfwordDisplacement => {
write!(f, "0x{:x}(%r{})", self.data as i16, self.register.unwrap())
write!(f, "0x{:x}(%r{})", self.embedded as i16, self.register.unwrap())
}
AddrMode::HalfwordDisplacementDeferred => {
write!(f, "*0x{:x}(%r{})", self.data as i16, self.register.unwrap())
write!(f, "*0x{:x}(%r{})", self.embedded as i16, self.register.unwrap())
}
AddrMode::WordDisplacement => {
write!(f, "0x{:x}(%r{})", self.data, self.register.unwrap())
write!(f, "0x{:x}(%r{})", self.embedded, self.register.unwrap())
}
AddrMode::WordDisplacementDeferred => {
write!(f, "*0x{:x}(%r{})", self.data, self.register.unwrap())
write!(f, "*0x{:x}(%r{})", self.embedded, self.register.unwrap())
}
AddrMode::ApShortOffset => {
write!(f, "{}(%ap)", self.data as i8)
write!(f, "{}(%ap)", self.embedded as i8)
}
AddrMode::FpShortOffset => {
write!(f, "{}(%fp)", self.data as i8)
write!(f, "{}(%fp)", self.embedded as i8)
}
AddrMode::ByteImmediate => {
write!(f, "&{}", self.data as u8)
write!(f, "&{}", self.embedded as u8)
}
AddrMode::HalfwordImmediate => {
write!(f, "&0x{:x}", self.data as u16)
write!(f, "&0x{:x}", self.embedded as u16)
}
AddrMode::WordImmediate => {
write!(f, "&0x{:x}", self.data)
write!(f, "&0x{:x}", self.embedded)
}
AddrMode::PositiveLiteral => {
write!(f, "$0x{:x}", self.data)
write!(f, "$0x{:x}", self.embedded)
}
AddrMode::NegativeLiteral => {
write!(f, "-$0x{:x}", self.data)
write!(f, "-$0x{:x}", self.embedded)
}
AddrMode::Register => {
write!(f, "%r{}", self.register.unwrap())
@ -250,7 +254,22 @@ impl fmt::Display for Operand {
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let _ = write!(f, "{:8} ", self.name);
let mut i = 0;
loop {
if i < self.len {
write!(f, "{:02x} ", self.data[i as usize])?;
} else {
write!(f, " ")?;
}
i += 1;
if i > 16 {
break;
}
}
write!(f, "{:8} ", self.name)?;
for index in 0..=3 {
let op = &self.operands[index];
@ -260,9 +279,9 @@ impl fmt::Display for Instruction {
}
if index == 0 {
let _ = write!(f, "{}", op);
write!(f, "{}", op)?;
} else {
let _ = write!(f, ",{}", op);
write!(f, ",{}", op)?;
}
}
@ -641,7 +660,8 @@ impl Cpu {
opcode: 0,
name: "???",
data_type: Data::None,
bytes: 0,
len: 0,
data: [0; 32],
operands: [
Operand::new(0, AddrMode::None, Data::None, None, None, 0),
Operand::new(0, AddrMode::None, Data::None, None, None, 0),
@ -789,6 +809,7 @@ impl Cpu {
AddrMode::ByteImmediate => sign_extend_byte(op.embedded as u8),
_ => {
let eff = self.effective_address(bus, index)?;
op.eff = eff;
match op.data_type() {
Data::UWord | Data::Word => {
bus.read_word(eff as usize, AccessCode::InstrFetch)?
@ -817,6 +838,8 @@ impl Cpu {
let register = self.ir.operands[index].register;
let data_type = self.ir.operands[index].data_type();
self.ir.operands[index].data = val;
match mode {
AddrMode::Register => match register {
Some(r) => self.r[r] = val,
@ -831,6 +854,7 @@ impl Cpu {
}
_ => {
let eff = self.effective_address(bus, index)?;
self.ir.operands[index].eff = eff;
match data_type {
Data::UWord | Data::Word => bus.write_word(eff as usize, val)?,
Data::Half | Data::UHalf => bus.write_half(eff as usize, val as u16)?,
@ -840,8 +864,6 @@ impl Cpu {
}
};
self.ir.operands[index].data = val;
Ok(())
}
@ -1012,7 +1034,7 @@ impl Cpu {
#[allow(clippy::cognitive_complexity)]
fn dispatch(&mut self, bus: &mut Bus) -> Result<i32, CpuError> {
self.steps += 1;
self.steps = self.steps.wrapping_add(1);
// Update anything that needs updating.
bus.service();
@ -1030,7 +1052,7 @@ impl Cpu {
}
self.decode_instruction(bus)?;
let mut pc_increment: i32 = i32::from(self.ir.bytes);
let mut pc_increment: i32 = i32::from(self.ir.len);
match self.ir.opcode {
NOP => {
@ -1608,6 +1630,13 @@ impl Cpu {
self.set_c_flag(false);
self.set_v_flag_op(val, 1);
}
MOVTRW => {
let val = self.effective_address(bus, 0)?;
self.write_op(bus, 1, val)?;
self.set_nz_flags(val, 1);
self.set_c_flag(false);
self.set_v_flag_op(val, 1);
}
MODW2 | MODH2 | MODB2 => {
// TODO: Modulo needs to be revisited.
let a = self.read_op(bus, 0)?;
@ -1982,7 +2011,11 @@ impl Cpu {
match self.dispatch(bus) {
Ok(i) => {
// We should have the necessary information to trace after dispatch.
trace!(bus, self.steps, &format!("[{:08x}] {}", &self.r[R_PC], &self.ir));
trace!(
bus,
self.steps,
&format!("[PC={:08x} PSW={:08x}] {}", &self.r[R_PC], &self.r[R_PSW], &self.ir)
);
self.r[R_PC] = (self.r[R_PC] as i32 + i) as u32
}
Err(CpuError::Bus(BusError::NoDevice(_)))
@ -1996,7 +2029,10 @@ impl Cpu {
// Err(CpuError::Exception(CpuException::InvalidDescriptor)) => {}
// Err(CpuError::Exception(CpuException::PrivilegedOpcode)) => {}
Err(e) => {
panic!("Unexpected CPU Error: {}", e)
panic!(
"Unexpected CPU Error '{}'. PC={:08x} R0={:08x} R1={:08x} R2={:08x} OP={:?}",
e, &self.r[R_PC], &self.r[0], &self.r[1], &self.r[2], &self.ir
)
}
}
}
@ -2034,6 +2070,34 @@ impl Cpu {
self.ir.operands[index].embedded = embedded;
}
fn accumulate_instruction_byte(&mut self, bus: &mut Bus) -> Result<u8, CpuError> {
let addr: usize = self.r[R_PC] as usize + self.ir.len as usize;
let datum: u8 = bus.read_byte(addr, AccessCode::InstrFetch)?;
self.ir.data[self.ir.len as usize] = datum;
self.ir.len += 1;
Ok(datum)
}
fn accumulate_instruction_half(&mut self, bus: &mut Bus) -> Result<u16, CpuError> {
let addr: usize = self.r[R_PC] as usize + self.ir.len as usize;
let datum: u16 = bus.read_op_half(addr)?;
self.ir.data[self.ir.len as usize] = (datum & 0xff) as u8;
self.ir.data[(self.ir.len + 1) as usize] = ((datum >> 8) & 0xff) as u8;
self.ir.len += 2;
Ok(datum)
}
fn accumulate_instruction_word(&mut self, bus: &mut Bus) -> Result<u32, CpuError> {
let addr: usize = self.r[R_PC] as usize + self.ir.len as usize;
let datum: u32 = bus.read_op_word(addr)?;
self.ir.data[self.ir.len as usize] = (datum & 0xff) as u8;
self.ir.data[(self.ir.len + 1) as usize] = ((datum >> 8) & 0xff) as u8;
self.ir.data[(self.ir.len + 2) as usize] = ((datum >> 16) & 0xff) as u8;
self.ir.data[(self.ir.len + 3) as usize] = ((datum >> 24) & 0xff) as u8;
self.ir.len += 4;
Ok(datum)
}
/// Decode a literal Operand type.
///
/// These operands belong to only certain instructions, where a word without
@ -2043,19 +2107,18 @@ impl Cpu {
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)?;
let b: u8 = self.accumulate_instruction_byte(bus)?;
self.set_operand(index, 1, AddrMode::None, Data::Byte, None, None, u32::from(b));
}
Data::Half => {
let h: u16 = bus.read_op_half(addr)?;
let h: u16 = self.accumulate_instruction_half(bus)?;
self.set_operand(index, 2, AddrMode::None, Data::Half, None, None, u32::from(h));
}
Data::Word => {
let w: u32 = bus.read_op_word(addr)?;
let w: u32 = self.accumulate_instruction_word(bus)?;
self.set_operand(index, 4, AddrMode::None, Data::Word, None, None, w);
}
_ => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
@ -2071,10 +2134,9 @@ impl Cpu {
index: usize,
dtype: Data,
etype: Option<Data>,
addr: usize,
recur: bool,
) -> Result<(), CpuError> {
let descriptor_byte: u8 = bus.read_byte(addr, AccessCode::OperandFetch)?;
let descriptor_byte: u8 = self.accumulate_instruction_byte(bus)?;
let m = (descriptor_byte & 0xf0) >> 4;
let r = descriptor_byte & 0xf;
@ -2104,7 +2166,7 @@ impl Cpu {
match r {
15 => {
// Word Immediate
let w = bus.read_op_word(addr + 1)?;
let w = self.accumulate_instruction_word(bus)?;
self.set_operand(
index,
dsize + 4,
@ -2133,7 +2195,7 @@ impl Cpu {
match r {
15 => {
// Halfword Immediate
let h = bus.read_op_half(addr + 1)?;
let h = self.accumulate_instruction_half(bus)?;
self.set_operand(
index,
dsize + 2,
@ -2166,7 +2228,7 @@ impl Cpu {
match r {
15 => {
// Byte Immediate
let b = bus.read_byte(addr + 1, AccessCode::OperandFetch)?;
let b = self.accumulate_instruction_byte(bus)?;
self.set_operand(
index,
dsize + 1,
@ -2195,7 +2257,7 @@ impl Cpu {
match r {
15 => {
// Absolute
let w = bus.read_op_word(addr + 1)?;
let w = self.accumulate_instruction_word(bus)?;
self.set_operand(
index,
dsize + 4,
@ -2225,7 +2287,7 @@ impl Cpu {
11 => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
_ => {
// Word Displacement
let disp = bus.read_op_word(addr + 1)?;
let disp = self.accumulate_instruction_word(bus)?;
self.set_operand(
index,
dsize + 4,
@ -2243,7 +2305,7 @@ impl Cpu {
11 => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
_ => {
// Word Displacement Deferred
let disp = bus.read_op_word(addr + 1)?;
let disp = self.accumulate_instruction_word(bus)?;
self.set_operand(
index,
dsize + 4,
@ -2261,7 +2323,7 @@ impl Cpu {
11 => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
_ => {
// Halfword Displacement
let disp = bus.read_op_half(addr + 1)?;
let disp = self.accumulate_instruction_half(bus)?;
self.set_operand(
index,
dsize + 2,
@ -2279,7 +2341,7 @@ impl Cpu {
11 => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
_ => {
// Halfword Displacement Deferred
let disp = bus.read_op_half(addr + 1)?;
let disp = self.accumulate_instruction_half(bus)?;
self.set_operand(
index,
dsize + 2,
@ -2297,7 +2359,7 @@ impl Cpu {
11 => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
_ => {
// Byte Displacement
let disp = bus.read_byte(addr + 1, AccessCode::OperandFetch)?;
let disp = self.accumulate_instruction_byte(bus)?;
self.set_operand(
index,
dsize + 1,
@ -2315,7 +2377,7 @@ impl Cpu {
11 => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
_ => {
// Byte Displacement Deferred
let disp = bus.read_byte(addr + 1, AccessCode::OperandFetch)?;
let disp = self.accumulate_instruction_byte(bus)?;
self.set_operand(
index,
dsize + 1,
@ -2329,56 +2391,14 @@ 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), true)?,
2 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::UHalf), true)?,
3 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::Byte), true)?,
4 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::Word), true)?,
6 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::Half), true)?,
7 => self.decode_descriptor_operand(bus, index, dtype, Some(Data::SByte), true)?,
15 => {
let w = bus.read_op_word(addr + 1)?;
let w = self.accumulate_instruction_word(bus)?;
self.set_operand(
index,
dsize + 4,
@ -2421,28 +2441,23 @@ impl Cpu {
mn: &Mnemonic,
ot: OpType,
etype: Option<Data>,
addr: usize,
) -> Result<(), CpuError> {
match ot {
OpType::Lit => self.decode_literal_operand(bus, index, mn, addr),
OpType::Lit => self.decode_literal_operand(bus, index, mn),
OpType::Src | OpType::Dest => {
self.decode_descriptor_operand(bus, index, mn.dtype, etype, addr, false)
self.decode_descriptor_operand(bus, index, mn.dtype, etype, false)
}
OpType::None => Ok(()),
}
}
/// Decode the instruction currently pointed at by the Program Counter.
/// Returns the number of bytes consumed, or a CpuError.
fn decode_instruction(&mut self, bus: &mut Bus) -> Result<(), CpuError> {
// The next address to read from is pointed to by the PC
let mut addr = self.r[R_PC] as usize;
let initial_addr = addr;
self.ir.len = 0;
// Read the first byte of the instruction. Most instructions are only
// one byte, so this is usually enough.
let b1 = bus.read_byte(addr, AccessCode::InstrFetch)?;
addr += 1;
let b1 = self.accumulate_instruction_byte(bus)?;
// Map the Mnemonic to the opcode we just read. But there's a special
// case if the value we read was '0x30'. This indicates that the instruction
@ -2451,8 +2466,7 @@ impl Cpu {
let mut mn: &Option<Mnemonic> = &NULL_MNEMONIC;
if b1 == 0x30 {
let b2 = bus.read_byte(addr, AccessCode::InstrFetch)?;
addr += 1;
let b2 = self.accumulate_instruction_byte(bus)?;
let opcode = (u16::from(b1) << 8) | u16::from(b2);
@ -2477,18 +2491,14 @@ impl Cpu {
self.ir.operands[index].clear();
} else {
// Push a decoded operand
self.decode_operand(bus, index, mn, *ot, etype, addr)?;
self.decode_operand(bus, index, mn, *ot, etype)?;
etype = self.ir.operands[index].expanded_type;
addr += self.ir.operands[index].size as usize;
}
}
let total_bytes = addr - initial_addr;
self.ir.opcode = mn.opcode;
self.ir.name = mn.name;
self.ir.data_type = mn.dtype;
self.ir.bytes = total_bytes as u8;
}
None => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
}
@ -2662,7 +2672,7 @@ mod tests {
let mut cpu: Cpu = Cpu::new();
let mut bus: Bus = Bus::new(0x10000);
bus.load(BASE, &program).unwrap();
bus.load(BASE, program).unwrap();
cpu.r[R_PC] = BASE as u32;
test(&mut cpu, &mut bus);
@ -2712,14 +2722,8 @@ mod tests {
fn decodes_byte_literal_operand() {
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();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::None, Data::Byte, None, None, 6)
@ -2731,14 +2735,8 @@ mod tests {
fn decodes_halfword_literal_operand() {
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();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(2, AddrMode::None, Data::Half, None, None, 0xfff)
@ -2750,14 +2748,8 @@ mod tests {
fn decodes_word_literal_operand() {
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();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(4, AddrMode::None, Data::Word, None, None, 0x4fff)
@ -2769,8 +2761,8 @@ mod tests {
fn decodes_positive_literal_operand() {
let program: [u8; 3] = [0x87, 0x04, 0x44]; // MOVB &4,%r4
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::PositiveLiteral, Data::Byte, None, None, 0x04)
@ -2782,8 +2774,8 @@ mod tests {
fn decodes_word_immediate_operand() {
let program = [0x84, 0x4f, 0x78, 0x56, 0x34, 0x12, 0x43]; // MOVW &0x12345678,%r3
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::WordImmediate, Data::Word, None, None, 0x12345678)
@ -2795,10 +2787,10 @@ mod tests {
fn decodes_register_operand() {
let program: [u8; 3] = [0x87, 0x04, 0x44]; // MOVB &4,%r4
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 2, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
cpu.ir.operands[1],
Operand::new(1, AddrMode::Register, Data::Byte, None, Some(4), 0)
);
});
@ -2808,8 +2800,8 @@ mod tests {
fn decodes_halfword_immediate_operand() {
let program = [0x84, 0x5f, 0x34, 0x12, 0x42]; // MOVW &0x1234,%r2
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(3, AddrMode::HalfwordImmediate, Data::Word, None, None, 0x1234,)
@ -2821,8 +2813,8 @@ mod tests {
fn decodes_register_deferred_operand() {
let program: [u8; 3] = [0x86, 0x52, 0x41]; // MOVH (%r2),%r1
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Half, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::RegisterDeferred, Data::Half, None, Some(2), 0)
@ -2834,8 +2826,8 @@ mod tests {
fn decodes_byte_immediate_operand() {
let program: [u8; 4] = [0x84, 0x6f, 0x28, 0x46]; // MOVW &40,%r6
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(2, AddrMode::ByteImmediate, Data::Word, None, None, 40)
@ -2847,8 +2839,8 @@ mod tests {
fn decodes_fp_short_offset_operand() {
let program: [u8; 3] = [0x84, 0x6C, 0x40]; // MOVW 12(%fp),%r0
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::FpShortOffset, Data::Word, None, Some(R_FP), 12)
@ -2860,8 +2852,8 @@ mod tests {
fn decodes_absolute_operand() {
let program: [u8; 7] = [0x87, 0x7f, 0x00, 0x01, 0x00, 0x00, 0x40]; // MOVB $0x100, %r0
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::Absolute, Data::Byte, None, None, 0x00000100)
@ -2873,8 +2865,8 @@ mod tests {
fn decodes_absolute_deferred_operand() {
let program = [0x87, 0xef, 0x00, 0x01, 0x00, 0x00, 0x40]; // MOVB *$0x100,%r0
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::AbsoluteDeferred, Data::Byte, None, None, 0x00000100)
@ -2886,8 +2878,8 @@ mod tests {
fn decodes_ap_short_offset_operand() {
let program: [u8; 3] = [0x84, 0x74, 0x43]; // MOVW 4(%ap),%r3
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::ApShortOffset, Data::Word, None, Some(R_AP), 4)
@ -2899,8 +2891,8 @@ mod tests {
fn decodes_word_displacement_operand() {
let program: [u8; 7] = [0x87, 0x82, 0x34, 0x12, 0x00, 0x00, 0x44]; // MOVB 0x1234(%r2),%r4
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(5, AddrMode::WordDisplacement, Data::Byte, None, Some(2), 0x1234,)
@ -2912,8 +2904,8 @@ mod tests {
fn decodes_word_displacement_deferred_operand() {
let program: [u8; 7] = [0x87, 0x92, 0x50, 0x40, 0x00, 0x00, 0x40]; // MOVB *0x4050(%r2),%r0
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(
@ -2932,8 +2924,8 @@ mod tests {
fn decodes_halfword_displacement_operand() {
let program: [u8; 5] = [0x87, 0xa2, 0x34, 0x12, 0x44]; // MOVB 0x1234(%r2),%r4
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(3, AddrMode::HalfwordDisplacement, Data::Byte, None, Some(2), 0x1234,)
@ -2945,8 +2937,8 @@ mod tests {
fn decodes_halfword_displacement_deferred_operand() {
let program: [u8; 5] = [0x87, 0xb2, 0x50, 0x40, 0x40]; // MOVB *0x4050(%r2),%r0
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(
@ -2965,8 +2957,8 @@ mod tests {
fn decodes_byte_displacement_operand() {
let program: [u8; 4] = [0x87, 0xc1, 0x06, 0x40]; // MOVB 6(%r1),%r0
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(2, AddrMode::ByteDisplacement, Data::Byte, None, Some(1), 6)
@ -2978,8 +2970,8 @@ mod tests {
fn decodes_byte_displacement_deferred_operand() {
let program: [u8; 4] = [0x87, 0xd2, 0x30, 0x43]; // MOVB *0x30(%r2),%r3
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(
@ -2998,9 +2990,8 @@ mod tests {
fn decodes_expanded_type_operand() {
let program: [u8; 6] = [0x87, 0xe7, 0x40, 0xe2, 0xc1, 0x04]; // MOVB {sbyte}%r0,{uhalf}4(%r1)
do_with_program(&program, |cpu, mut bus| {
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();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
@ -3024,8 +3015,8 @@ mod tests {
fn decodes_negative_literal_operand() {
let program: [u8; 3] = [0x87, 0xff, 0x40]; // MOVB &-1,%r0
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(
cpu.ir.operands[0],
Operand::new(1, AddrMode::NegativeLiteral, Data::Byte, None, None, 0xff)
@ -3035,11 +3026,16 @@ mod tests {
fn assert_instruction(cpu: &Cpu, opcode: u16, size: u8, name: &'static str, data_type: Data) {
assert_eq!(cpu.ir.opcode, opcode);
assert_eq!(cpu.ir.bytes, size);
assert_eq!(cpu.ir.len, size);
assert_eq!(cpu.ir.name, name);
assert_eq!(cpu.ir.data_type, data_type);
}
// #[test]
// fn adds_two_numbers() {
// let program = [0xdc, 0x4f, 0x78, 0x56, 0x34, 0x12, 0x43]; // ADDW3 &16, &0x12345678,%r3
// }
#[test]
fn decodes_halfword_instructions() {
let program = [0x30, 0x0d]; // ENBVJMP
@ -3100,20 +3096,18 @@ mod tests {
fn reads_register_operand_data() {
{
let program = [0x87, 0xe7, 0x40, 0xe2, 0x41]; // MOVB {sbyte}%r0,{uhalf}%r1
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[0] = 0xff;
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false)
.unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0xffffffff, cpu.read_op(bus, 0).unwrap());
});
}
{
let program = [0x87, 0x40, 0x41]; // MOVB %r0,%r1
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[0] = 0xff;
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false)
.unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0xff, cpu.read_op(bus, 0).unwrap());
});
}
@ -3122,8 +3116,8 @@ mod tests {
#[test]
fn reads_positive_literal_operand_data() {
let program = [0x87, 0x04, 0x44];
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(4, cpu.read_op(bus, 0).unwrap() as i8);
});
}
@ -3131,8 +3125,8 @@ mod tests {
#[test]
fn reads_negative_literal_operand_data() {
let program = [0x87, 0xff, 0x44];
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(-1, cpu.read_op(bus, 0).unwrap() as i8);
});
}
@ -3140,8 +3134,8 @@ mod tests {
#[test]
fn reads_word_immediate_operand_data() {
let program = [0x84, 0x4f, 0x78, 0x56, 0x34, 0x12, 0x43]; // MOVW &0x12345678,%r3
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x12345678, cpu.read_op(bus, 0).unwrap())
});
}
@ -3149,8 +3143,8 @@ mod tests {
#[test]
fn reads_halfword_immediate_operand_data() {
let program = [0x84, 0x5f, 0x34, 0x12, 0x42]; // MOVW &0x1234,%r2
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x1234, cpu.read_op(bus, 0).unwrap())
});
}
@ -3158,8 +3152,8 @@ mod tests {
#[test]
fn reads_negative_halfword_immediate_operand_data() {
let program = [0x84, 0x5f, 0x00, 0x80, 0x42]; // MOVW &0x8000,%r2
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(0xffff8000, cpu.read_op(bus, 0).unwrap())
});
}
@ -3167,8 +3161,8 @@ mod tests {
#[test]
fn reads_byte_immediate_operand_data() {
let program = [0x84, 0x6f, 0x28, 0x42]; // MOVW &40,%r2
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(40, cpu.read_op(bus, 0).unwrap())
});
}
@ -3176,8 +3170,8 @@ mod tests {
#[test]
fn reads_negative_byte_immediate_operand_data() {
let program = [0x84, 0x6f, 0xff, 0x42]; // MOVW &-1,%r2
do_with_program(&program, |cpu, mut bus| {
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
do_with_program(&program, |cpu, bus| {
cpu.decode_instruction(bus).unwrap();
assert_eq!(-1, cpu.read_op(bus, 0).unwrap() as i32)
});
}
@ -3185,9 +3179,9 @@ mod tests {
#[test]
fn reads_absolute_operand_data() {
let program = [0x87, 0x7f, 0x00, 0x02, 0x70, 0x00, 0x04]; // MOVB $0x700200,%r0
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
bus.write_byte(0x700200, 0x5a).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x5a, cpu.read_op(bus, 0).unwrap());
});
}
@ -3195,27 +3189,36 @@ mod tests {
#[test]
fn reads_absolute_deferred_operand_data() {
let program = [0x87, 0xef, 0x00, 0x01, 0x70, 0x00, 0x41]; // MOVB *$0x700100,%r0
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
bus.write_word(0x700100, 0x700300).unwrap();
bus.write_byte(0x700300, 0x1f).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x1f, cpu.read_op(bus, 0).unwrap());
});
}
#[test]
fn reads_byte_displacement_operand_data() {
fn reads_positive_byte_displacement_operand_data() {
let program = [
0x87, 0xc1, 0x06, 0x40, // MOVB 6(%r1),%r0
0x87, 0xc1, 0xfe, 0x40, // MOVB -2(%r1),%r0
];
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[1] = 0x700200;
bus.write_byte(0x700206, 0x1f).unwrap();
bus.write_byte(0x7001fe, 0xc5).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x1f, cpu.read_op(bus, 0).unwrap());
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 5, false).unwrap();
});
}
#[test]
fn reads_negative_byte_displacement_operand_data() {
let program = [
0x87, 0xc1, 0xfe, 0x40, // MOVB -2(%r1),%r0
];
do_with_program(&program, |cpu, bus| {
cpu.r[1] = 0x700200;
bus.write_byte(0x7001fe, 0xc5).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0xc5, cpu.read_op(bus, 0).unwrap());
});
}
@ -3223,11 +3226,11 @@ mod tests {
#[test]
fn reads_byte_displacement_deferred_operand_data() {
let program = [0x87, 0xd2, 0x30, 0x43]; // MOVB *0x30(%r2),%r3
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[2] = 0x700200;
bus.write_word(0x700230, 0x700300).unwrap();
bus.write_byte(0x700300, 0x5a).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x5a, cpu.read_op(bus, 0).unwrap());
})
}
@ -3235,10 +3238,10 @@ mod tests {
#[test]
fn reads_halword_displacement_operand_data() {
let program = [0x87, 0xa2, 0x01, 0x11, 0x48]; // MOVB 0x1101(%r2),%r8
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[2] = 0x700000;
bus.write_byte(0x701101, 0x1f).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x1f, cpu.read_op(bus, 0).unwrap());
});
}
@ -3246,11 +3249,11 @@ mod tests {
#[test]
fn reads_halfword_displacement_deferred_operand_data() {
let program = [0x87, 0xb2, 0x00, 0x02, 0x46]; // MOVB *0x200(%r2),%r6
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[2] = 0x700000;
bus.write_word(0x700200, 0x700500).unwrap();
bus.write_byte(0x700500, 0x5a).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x5a, cpu.read_op(bus, 0).unwrap());
})
}
@ -3258,10 +3261,10 @@ mod tests {
#[test]
fn reads_word_displacement_operand_data() {
let program = [0x87, 0x82, 0x01, 0x11, 0x00, 0x00, 0x48]; // MOVB 0x1101(%r2),%r8
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[2] = 0x700000;
bus.write_byte(0x701101, 0x1f).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x1f, cpu.read_op(bus, 0).unwrap());
});
}
@ -3269,11 +3272,11 @@ mod tests {
#[test]
fn reads_word_displacement_deferred_operand_data() {
let program = [0x87, 0x92, 0x00, 0x02, 0x00, 0x00, 0x46]; // MOVB *0x200(%r2),%r6
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[2] = 0x700000;
bus.write_word(0x700200, 0x700500).unwrap();
bus.write_byte(0x700500, 0x5a).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Byte, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x5a, cpu.read_op(bus, 0).unwrap());
})
}
@ -3281,10 +3284,10 @@ mod tests {
#[test]
fn reads_ap_short_offset_operand_data() {
let program = [0x84, 0x74, 0x43]; // MOVW 4(%ap),%r3
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[R_AP] = 0x700500;
bus.write_word(0x700504, 0x12345678).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x12345678, cpu.read_op(bus, 0).unwrap());
});
}
@ -3292,22 +3295,11 @@ mod tests {
#[test]
fn reads_fp_short_offset_operand_data() {
let program = [0x84, 0x6c, 0x40]; // MOVW 12(%fp),%r0
do_with_program(&program, |cpu, mut bus| {
do_with_program(&program, |cpu, bus| {
cpu.r[R_FP] = 0x700200;
bus.write_word(0x70020c, 0x12345678).unwrap();
cpu.decode_descriptor_operand(&mut bus, 0, Data::Word, None, BASE + 1, false).unwrap();
cpu.decode_instruction(bus).unwrap();
assert_eq!(0x12345678, cpu.read_op(bus, 0).unwrap());
});
}
#[test]
fn writes_register_operand_data() {
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, false).unwrap();
cpu.write_op(bus, 0, 0x5a).unwrap();
assert_eq!(0x5a, cpu.r[0]);
});
}
}

View File

@ -195,6 +195,17 @@ pub unsafe fn dmd_trace_on(file_name: *const c_char) -> c_int {
}
}
#[no_mangle]
pub fn dmd_trace_off() -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
dmd.trace_off();
SUCCESS
}
Err(_) => ERROR,
}
}
#[no_mangle]
fn dmd_step_loop(steps: usize) -> c_int {
match DMD.lock() {

View File

@ -1,5 +1,3 @@
#![allow(clippy::unreadable_literal)]
use crate::bus::AccessCode;
use crate::bus::Device;
use crate::err::BusError;
@ -19,17 +17,11 @@ 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, 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 BAUD_RATES_A: [u32; 13] =
[50, 110, 135, 200, 300, 600, 1200, 1050, 2400, 4800, 7200, 9600, 38400];
// 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 BAUD_RATES_B: [u32; 13] =
[75, 110, 135, 150, 300, 600, 1200, 2000, 2400, 4800, 1800, 9600, 19200];
const PORT_0: usize = 0;
const PORT_1: usize = 1;
@ -148,6 +140,21 @@ impl Default for Duart {
}
}
/// Compute the delay rate to wait for the next transmit or receive
fn delay_rate(csr_bits: u8, acr_bits: u8) -> u32 {
const NS_PER_SEC: u32 = 1_100_000_000;
const BITS_PER_CHAR: u32 = 7;
let baud_bits: usize = ((csr_bits >> 4) & 0xf) as usize;
let baud_rate = if acr_bits & 0x80 == 0 {
BAUD_RATES_A[baud_bits]
} else {
BAUD_RATES_B[baud_bits]
};
NS_PER_SEC / (baud_rate / BITS_PER_CHAR)
}
impl Duart {
pub fn new() -> Duart {
Duart {
@ -476,15 +483,8 @@ impl Device for Duart {
ctx.mode_ptr = (ctx.mode_ptr + 1) % 2;
}
CSRA => {
// Set the baud rate.
let baud_bits: usize = ((val >> 4) & 0xf) as usize;
let delay = if self.acr & 0x80 == 0 {
DELAY_RATES_A[baud_bits]
} else {
DELAY_RATES_B[baud_bits]
};
let mut ctx = &mut self.ports[PORT_0];
ctx.char_delay = Duration::new(0, delay);
ctx.char_delay = Duration::new(0, delay_rate(val, self.acr));
}
CRA => {
self.handle_command(val, PORT_0);

View File

@ -34,12 +34,12 @@ impl Error for CpuException {
#[derive(Debug)]
pub enum BusError {
Init,
Read(u32),
Write(u32),
NoDevice(u32),
Read(usize),
Write(usize),
NoDevice(usize),
Range,
Permission,
Alignment,
Alignment(usize),
}
impl fmt::Display for BusError {
@ -51,7 +51,7 @@ impl fmt::Display for BusError {
BusError::NoDevice(addr) => write!(f, "No device at address {:x}", addr),
BusError::Range => write!(f, "Address out of range"),
BusError::Permission => write!(f, "Invalid permission"),
BusError::Alignment => write!(f, "Memory Alignment"),
BusError::Alignment(addr) => write!(f, "Memory Alignment at address {:08x}", addr),
}
}
}
@ -65,7 +65,7 @@ impl Error for BusError {
BusError::NoDevice(_) => None,
BusError::Range => None,
BusError::Permission => None,
BusError::Alignment => None,
BusError::Alignment(_) => None,
}
}
}

View File

@ -99,7 +99,7 @@ impl Device for Mem {
/// Write to memory at the specified absolute address.
fn write_byte(&mut self, address: usize, val: u8, _: AccessCode) -> Result<(), BusError> {
if self.is_read_only {
return Err(BusError::Write(address as u32));
return Err(BusError::Write(address));
}
let offset = address.wrapping_sub(self.address_range().start);
@ -114,7 +114,7 @@ impl Device for Mem {
fn write_half(&mut self, address: usize, val: u16, _: AccessCode) -> Result<(), BusError> {
if self.is_read_only {
return Err(BusError::Write(address as u32));
return Err(BusError::Write(address));
}
let offset = address.wrapping_sub(self.address_range().start);
@ -130,7 +130,7 @@ impl Device for Mem {
fn write_word(&mut self, address: usize, val: u32, _: AccessCode) -> Result<(), BusError> {
if self.is_read_only {
return Err(BusError::Write(address as u32));
return Err(BusError::Write(address));
}
let offset = address.wrapping_sub(self.address_range().start);

View File

@ -51,7 +51,7 @@ impl Device for Mouse {
match address - START_ADDRESS {
0 => Ok(self.y),
2 => Ok(self.x),
_ => Err(BusError::NoDevice(address as u32)),
_ => Err(BusError::NoDevice(address)),
}
}