Compare commits

...

4 Commits

Author SHA1 Message Date
dc7d3d6268 Format + some clipy 2022-11-28 19:52:23 +01:00
8a45d13e8c Cleanup 2022-03-15 21:36:48 +01:00
4e4b92abf2 cargo clippy --fix 2022-03-15 21:26:09 +01:00
f1a5d13830 Fix some clippy warnings 2022-03-15 21:24:54 +01:00
10 changed files with 192 additions and 173 deletions

View File

@ -1,47 +1,34 @@
use cpu::CPU; use cpu::CPU;
use devices; use devices::{oscillator::Oscillator, ram::Ram, usart::Usart, Device, DeviceTree};
use slog; use slog;
pub struct Chip { pub struct Chip {
log: slog::Logger, log: slog::Logger,
pub cpu: CPU, pub cpu: CPU,
pub rom: Box<[u8]>, pub rom: Box<[u8]>,
pub device_tree: devices::DeviceTree, pub device_tree: DeviceTree,
// TODO: List of devices // TODO: List of devices
} }
impl Chip { impl Chip {
pub fn new(log: slog::Logger, rom: Box<[u8]>) -> Chip { pub fn new(log: slog::Logger, rom: Box<[u8]>) -> Chip {
// Internal registers // Internal registers
let internal_regs = devices::ram::RAM::new(log.clone()); let internal_regs = Ram::new(log.clone());
let ram_device = devices::ram::RAM::new(log.clone()); let ram_device = Ram::new(log.clone());
let usart_device = devices::usart::USART::new(log.clone()); let usart_device = Usart::new(log.clone());
let mut dev_tree = devices::DeviceTree::new(log.clone()); let mut dev_tree = DeviceTree::new(log.clone());
// Add RAM and USART // Add RAM and USART
dev_tree.add_device( dev_tree.add_device(Device::new(ram_device, 0x2000, 0x2000));
devices::Device::new(Box::new(ram_device), 0x2000, 0x2000) dev_tree.add_device(Device::new(internal_regs, 0, 0x40));
); dev_tree.add_device(Device::new(usart_device, 0x8A0, 0x8A7 - 0x8A0 + 1));
dev_tree.add_device( dev_tree.add_device(Device::new(Oscillator::new(log.clone()), 0x50, 0x07));
devices::Device::new(Box::new(internal_regs), 0, 0x40)
);
dev_tree.add_device(
devices::Device::new(Box::new(usart_device), 0x8A0, 0x8A7 - 0x8A0 + 1)
);
dev_tree.add_device(
devices::Device::new(
Box::new(devices::oscillator::Oscillator::new(log.clone())),
0x50, 0x07
)
);
Self { Self {
log: log.clone(), log: log.clone(),
cpu: CPU::new(log), cpu: CPU::new(log),
rom: rom, rom,
device_tree: dev_tree, device_tree: dev_tree,
} }
} }

View File

@ -1,12 +1,10 @@
#![allow(dead_code)] #![allow(dead_code)]
#![allow(unused_variables)] #![allow(unused_variables)]
use decoder; use chip_definitions::IOAdress;
use decoder::{IncrementMode, Instruction}; use decoder::{self, IncrementMode, Instruction};
use regs::{GeneralPurposeRegister, GeneralPurposeRegisterPair, StatusFlag};
use chip_definitions;
use devices::DeviceTree; use devices::DeviceTree;
use regs::{GeneralPurposeRegister, GeneralPurposeRegisterPair, StatusFlag};
use std::fmt; use std::fmt;
@ -54,14 +52,14 @@ impl fmt::Display for CPU {
write!(f, "-")?; write!(f, "-")?;
} }
} }
write!(f, "\n")?; writeln!(f)?;
for i in 0..32 { for i in 0..32 {
write!(f, " R{:-2}={:02X} ", i, self.registers[i])?; write!(f, " R{:-2}={:02X} ", i, self.registers[i])?;
if (i + 1) % 10 == 0 { if (i + 1) % 10 == 0 {
write!(f, "\n")?; writeln!(f)?;
} }
} }
write!(f, "\n") writeln!(f)
} }
} }
@ -71,19 +69,19 @@ impl CPU {
registers: [0u8; 32], registers: [0u8; 32],
pc: 0, // Reset vector pc: 0, // Reset vector
sreg: 0, // Uninitialized as well sreg: 0, // Uninitialized as well
logger: logger, logger,
} }
} }
pub fn get_sp(&self, mem: &mut DeviceTree) -> u16 { pub fn get_sp(&self, mem: &mut DeviceTree) -> u16 {
let spl: u16 = mem.read(chip_definitions::IOAdress::SPL as u32) as u16; let spl: u16 = mem.read(IOAdress::SPL as u32) as u16;
let sph: u16 = mem.read(chip_definitions::IOAdress::SPH as u32) as u16; let sph: u16 = mem.read(IOAdress::SPH as u32) as u16;
sph << 8 | spl sph << 8 | spl
} }
fn set_sp(&self, mem: &mut DeviceTree, val: u16) { fn set_sp(&self, mem: &mut DeviceTree, val: u16) {
mem.write(chip_definitions::IOAdress::SPL as u32, val as u8); mem.write(IOAdress::SPL as u32, val as u8);
mem.write(chip_definitions::IOAdress::SPH as u32, (val >> 8) as u8); mem.write(IOAdress::SPH as u32, (val >> 8) as u8);
} }
fn test_flag(&self, flag: StatusFlag) -> bool { fn test_flag(&self, flag: StatusFlag) -> bool {
@ -232,7 +230,11 @@ impl CPU {
} }
// Returns # of ticks the executed instruction took // Returns # of ticks the executed instruction took
pub fn step(&mut self, rom: &mut [u8], device_tree: &mut DeviceTree) -> Result<usize, CPUError> { pub fn step(
&mut self,
rom: &mut [u8],
device_tree: &mut DeviceTree,
) -> Result<usize, CPUError> {
// Instruction fetch // Instruction fetch
if (self.pc as usize) * 2 >= rom.len() { if (self.pc as usize) * 2 >= rom.len() {
return Err(CPUError::OutOfBoundsException); return Err(CPUError::OutOfBoundsException);
@ -316,16 +318,16 @@ impl CPU {
IncrementMode::ConstantOffset(o) => base.wrapping_add(u16::from(o)), IncrementMode::ConstantOffset(o) => base.wrapping_add(u16::from(o)),
}; };
self.ram_write(device_tree, addr, self.get_register(src_reg))?; self.ram_write(device_tree, addr, self.get_register(src_reg))?;
}, }
Instruction::LD(ref dst_reg, ref ptr, ref inc_mode) => { Instruction::LD(ref dst_reg, ref ptr, ref inc_mode) => {
let base = self.get_register_pair(ptr); let base = self.get_register_pair(ptr);
/* /*
// TODO: RAMPX/Y/Z // TODO: RAMPX/Y/Z
if ptr.low() == 26 && ram[chip_definitions::IOAdress::RAMPX as usize] > 0 { if ptr.low() == 26 && ram[IOAdress::RAMPX as usize] > 0 {
panic!("Unexpected"); panic!("Unexpected");
} else if ptr.low() == 28 && ram[chip_definitions::IOAdress::RAMPY as usize] > 0 { } else if ptr.low() == 28 && ram[IOAdress::RAMPY as usize] > 0 {
panic!("Unexpected"); panic!("Unexpected");
} else if ptr.low() == 30 && ram[chip_definitions::IOAdress::RAMPZ as usize] > 0 { } else if ptr.low() == 30 && ram[IOAdress::RAMPZ as usize] > 0 {
panic!("Unexpected"); panic!("Unexpected");
} }
*/ */
@ -347,17 +349,16 @@ impl CPU {
Instruction::ELPM(ref dst_reg, ref inc_mode) => { Instruction::ELPM(ref dst_reg, ref inc_mode) => {
let Zb = self.get_register_pair(&30u8.into()); let Zb = self.get_register_pair(&30u8.into());
// TODO: Only use required bits, other read as zero (according to datasheet) // TODO: Only use required bits, other read as zero (according to datasheet)
let Z = let Z = Zb as usize | (device_tree.read(IOAdress::RAMPZ as u32) as usize) << 16;
Zb as usize |
(device_tree.read(chip_definitions::IOAdress::RAMPZ as u32) as usize) << 16;
match *inc_mode { match *inc_mode {
IncrementMode::PostIncrement => { IncrementMode::PostIncrement => {
self.set_register_pair(&30u8.into(), Zb.wrapping_add(1)); self.set_register_pair(&30u8.into(), Zb.wrapping_add(1));
device_tree.write(chip_definitions::IOAdress::RAMPZ as u32, (Z.wrapping_add(1) >> 16) as u8); device_tree.write(IOAdress::RAMPZ as u32, (Z.wrapping_add(1) >> 16) as u8);
}, }
_ => { _ => {
// This instruction does only support None + PostIncrement // This instruction does only support None + PostIncrement
panic!("Invalid increment mode for ELPM: {:?}", inc_mode);
} }
} }
if Z >= rom.len() { if Z >= rom.len() {
@ -384,13 +385,14 @@ impl CPU {
} }
_ => { _ => {
// This instruction does only support None + PostIncrement // This instruction does only support None + PostIncrement
panic!("Invalid increment mode for LPM: {:?}", inc_mode);
} }
} }
} }
Instruction::OUT(ref addr, ref val) => { Instruction::OUT(ref addr, ref val) => {
let val = self.get_register(val); let val = self.get_register(val);
self.ram_write(device_tree, *addr, val)?; self.ram_write(device_tree, *addr, val)?;
}, }
Instruction::IN(ref reg, ref addr) => { Instruction::IN(ref reg, ref addr) => {
let v = self.ram_read(device_tree, *addr)?; let v = self.ram_read(device_tree, *addr)?;
self.set_register(reg, v); self.set_register(reg, v);
@ -408,7 +410,7 @@ impl CPU {
self.push(device_tree, ((ret_to >> 8) & 0xFF) as u8)?; self.push(device_tree, ((ret_to >> 8) & 0xFF) as u8)?;
self.push(device_tree, (ret_to & 0xFF) as u8)?; self.push(device_tree, (ret_to & 0xFF) as u8)?;
self.pc = (self.pc as i32 + *addr as i32) as u32; self.pc = (self.pc as i32 + *addr as i32) as u32;
}, }
Instruction::RET => { Instruction::RET => {
let mut ret_to = self.pop(device_tree)? as u32; let mut ret_to = self.pop(device_tree)? as u32;
ret_to += (self.pop(device_tree)? as u32) << 8; ret_to += (self.pop(device_tree)? as u32) << 8;
@ -422,7 +424,7 @@ impl CPU {
Instruction::PUSH(ref reg) => { Instruction::PUSH(ref reg) => {
let v = self.registers[reg.as_usize()]; let v = self.registers[reg.as_usize()];
self.push(device_tree, v)?; self.push(device_tree, v)?;
}, }
Instruction::SUBI(ref d, ref v) => { Instruction::SUBI(ref d, ref v) => {
let dv = self.get_register(d); let dv = self.get_register(d);
let vres = dv.wrapping_sub(*v); let vres = dv.wrapping_sub(*v);
@ -545,16 +547,20 @@ impl CPU {
self.update_flags_zns_8(res); self.update_flags_zns_8(res);
} }
Instruction::STS16(ref addr, ref r) => { Instruction::STS16(ref addr, ref r) => {
let rampd = device_tree.read(chip_definitions::IOAdress::RAMPD as u32); let rampd = device_tree.read(IOAdress::RAMPD as u32);
if rampd != 0 { panic!("This is unexpected (for now)"); } if rampd != 0 {
panic!("This is unexpected (for now)");
}
self.ram_write(device_tree, *addr, self.get_register(r))?; self.ram_write(device_tree, *addr, self.get_register(r))?;
}, }
Instruction::STS8(ref addr, ref r) => { Instruction::STS8(ref addr, ref r) => {
self.ram_write(device_tree, *addr as u16, self.get_register(r))?; self.ram_write(device_tree, *addr as u16, self.get_register(r))?;
}, }
Instruction::LDS16(ref r, ref addr) => { Instruction::LDS16(ref r, ref addr) => {
let rampd = device_tree.read(chip_definitions::IOAdress::RAMPD as u32); let rampd = device_tree.read(IOAdress::RAMPD as u32);
if rampd != 0 { panic!("This is unexpected (for now)"); } if rampd != 0 {
panic!("This is unexpected (for now)");
}
let v = self.ram_read(device_tree, *addr)?; let v = self.ram_read(device_tree, *addr)?;
self.set_register(r, v); self.set_register(r, v);
} }
@ -655,7 +661,7 @@ impl CPU {
if self.test_flag(StatusFlag::BitCopyStorage) { if self.test_flag(StatusFlag::BitCopyStorage) {
rv |= 1 << *v; rv |= 1 << *v;
} }
let r = self.set_register(r, rv); self.set_register(r, rv);
} }
Instruction::SWAP(ref r) => { Instruction::SWAP(ref r) => {
let rv = self.get_register(r); let rv = self.get_register(r);

View File

@ -282,7 +282,7 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
if v & 0b1111_1111_0000_0000 == 0b0000_0011_0000_0000 { if v & 0b1111_1111_0000_0000 == 0b0000_0011_0000_0000 {
// FMUL/FMULS/FMULSU/MULSU // FMUL/FMULS/FMULSU/MULSU
let d = ((v & 0b0111_0000) >> 4) as u8; let d = ((v & 0b0111_0000) >> 4) as u8;
let r = ((v & 0b0111)) as u8; let r = (v & 0b0111) as u8;
let mode = v & 0b1000_1000; let mode = v & 0b1000_1000;
match mode { match mode {
0b0000_0000 => return Ok(Instruction::MULSU((d + 16).into(), (r + 16).into())), 0b0000_0000 => return Ok(Instruction::MULSU((d + 16).into(), (r + 16).into())),
@ -308,7 +308,7 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
let K = (((v & 0b1100_0000) >> 2) | (v & 0b1111)) as u8; let K = (((v & 0b1100_0000) >> 2) | (v & 0b1111)) as u8;
let d = ((v & 0b1111_0000) >> 4) as u8; let d = ((v & 0b1111_0000) >> 4) as u8;
let r = (v & 0b1111) as u8; let r = (v & 0b1111) as u8;
let A = u16::from((v & 0b1111_1000) >> 3); let A = (v & 0b1111_1000) >> 3;
let b = (v & 0b0111) as u8; let b = (v & 0b0111) as u8;
match v & 0b1111_1111_0000_0000 { match v & 0b1111_1111_0000_0000 {
0b1001_0110_0000_0000 => { 0b1001_0110_0000_0000 => {
@ -318,16 +318,20 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
)) ))
} }
0b0000_0001_0000_0000 => return Ok(Instruction::MOVW((d * 2).into(), (r * 2).into())), 0b0000_0001_0000_0000 => return Ok(Instruction::MOVW((d * 2).into(), (r * 2).into())),
0b0000_0010_0000_0000 => return Ok(Instruction::MULS((d + 16).into(), (r + 16).into())), 0b0000_0010_0000_0000 => {
return Ok(Instruction::MULS((d + 16).into(), (r + 16).into()))
}
0b1001_0111_0000_0000 => { 0b1001_0111_0000_0000 => {
return Ok(Instruction::SBIW( return Ok(Instruction::SBIW(
((d & 0b11) * 2 + 24).into(), ((d & 0b11) * 2 + 24).into(),
u16::from(K), u16::from(K),
)) ))
} }
0b1110_1111_0000_0000 => if r == 0b1111 { 0b1110_1111_0000_0000 => {
return Ok(Instruction::SER((d + 16).into())); if r == 0b1111 {
}, return Ok(Instruction::SER((d + 16).into()));
}
}
0b1001_1010_0000_0000 => return Ok(Instruction::SBI(A, b)), 0b1001_1010_0000_0000 => return Ok(Instruction::SBI(A, b)),
0b1001_1011_0000_0000 => return Ok(Instruction::SBIS(A, b)), 0b1001_1011_0000_0000 => return Ok(Instruction::SBIS(A, b)),
0b1001_1001_0000_0000 => return Ok(Instruction::SBIC(A, b)), 0b1001_1001_0000_0000 => return Ok(Instruction::SBIC(A, b)),

View File

@ -2,9 +2,9 @@
use slog::Logger; use slog::Logger;
pub mod oscillator;
pub mod ram; pub mod ram;
pub mod usart; pub mod usart;
pub mod oscillator;
pub trait DeviceImpl { pub trait DeviceImpl {
/// addr relative to the start of the device memory map. /// addr relative to the start of the device memory map.
@ -16,15 +16,15 @@ pub trait DeviceImpl {
pub struct Device { pub struct Device {
start_addr: u32, start_addr: u32,
addr_len: u32, addr_len: u32,
device: Box<DeviceImpl>, device: Box<dyn DeviceImpl>,
} }
impl Device { impl Device {
pub fn new(device: Box<DeviceImpl>, start_addr: u32, addr_len: u32) -> Self { pub fn new<T: DeviceImpl + 'static>(device: T, start_addr: u32, addr_len: u32) -> Self {
Self { Self {
start_addr: start_addr, start_addr,
addr_len: addr_len, addr_len,
device: device, device: Box::new(device),
} }
} }
@ -49,7 +49,7 @@ pub struct DeviceTree {
impl DeviceTree { impl DeviceTree {
pub fn new(log: Logger) -> Self { pub fn new(log: Logger) -> Self {
Self { Self {
log: log, log,
devices: Vec::new(), devices: Vec::new(),
} }
} }
@ -59,7 +59,7 @@ impl DeviceTree {
} }
fn get_device_for_addr(&mut self, addr: u32) -> Option<&mut Device> { fn get_device_for_addr(&mut self, addr: u32) -> Option<&mut Device> {
self.devices.iter_mut().filter(|d| d.handles_addr(addr)).nth(0) self.devices.iter_mut().find(|d| d.handles_addr(addr))
} }
pub fn read(&mut self, addr: u32) -> u8 { pub fn read(&mut self, addr: u32) -> u8 {
@ -74,6 +74,9 @@ impl DeviceTree {
if let Some(ref mut d) = self.get_device_for_addr(addr) { if let Some(ref mut d) = self.get_device_for_addr(addr) {
return d.write(addr, val); return d.write(addr, val);
} }
warn!(self.log, "Trying to write unmapped I/O: {:08X} <- {:02X}", addr, val); warn!(
self.log,
"Trying to write unmapped I/O: {:08X} <- {:02X}", addr, val
);
} }
} }

View File

@ -6,15 +6,19 @@ const OSC_CTRL: u32 = 0;
const OSC_STATUS: u32 = 1; const OSC_STATUS: u32 = 1;
const OSC_XOSCCTRL: u32 = 2; const OSC_XOSCCTRL: u32 = 2;
const OSC_XOSCFAIL: u32 = 3; const OSC_XOSCFAIL: u32 = 3;
/*
const OSC_RC32KCAL: u32 = 4; const OSC_RC32KCAL: u32 = 4;
const OSC_PLLCTRL: u32 = 5; const OSC_PLLCTRL: u32 = 5;
const OSC_DFLLCTRL: u32 = 6; const OSC_DFLLCTRL: u32 = 6;
*/
/*
enum PllSrc { enum PllSrc {
RC2M, RC2M,
RC32M, RC32M,
XOSC, XOSC,
} }
*/
pub struct Oscillator { pub struct Oscillator {
log: Logger, log: Logger,
@ -24,27 +28,31 @@ pub struct Oscillator {
ctrl: u8, ctrl: u8,
status: u8, status: u8,
xoscctrl: u8, xoscctrl: u8,
/*
xoscfail: u8, xoscfail: u8,
rs32kcal: u8, rs32kcal: u8,
pllsrc: PllSrc, pllsrc: PllSrc,
pllfac: u8, pllfac: u8,
dfllctrl: u8, dfllctrl: u8,
*/
} }
impl Oscillator { impl Oscillator {
pub fn new(log: Logger) -> Self { pub fn new(log: Logger) -> Self {
Self { Self {
log: log, log,
reg_values: [0u8; 7], reg_values: [0u8; 7],
ctrl: 0, ctrl: 0,
status: 0, status: 0,
xoscctrl: 0, xoscctrl: 0,
/*
xoscfail: 0, xoscfail: 0,
rs32kcal: 0, rs32kcal: 0,
pllsrc: PllSrc::RC2M, pllsrc: PllSrc::RC2M,
pllfac: 0, pllfac: 0,
dfllctrl: 0, dfllctrl: 0,
*/
} }
} }
} }
@ -74,47 +82,45 @@ impl DeviceImpl for Oscillator {
OSC_XOSCCTRL => { OSC_XOSCCTRL => {
self.xoscctrl = value & 0xEF; self.xoscctrl = value & 0xEF;
} }
OSC_XOSCFAIL => { OSC_XOSCFAIL => {}
},
_ => {} _ => {}
} }
self.reg_values[addr as usize] = value; self.reg_values[addr as usize] = value;
} }
/* /*
} else if(addr == 0x03) { // XOSCFAIL } else if(addr == 0x03) { // XOSCFAIL
XOSCFAIL vreg; XOSCFAIL vreg;
vreg.data = v & 0x03; vreg.data = v & 0x03;
// XOSCFDEN // XOSCFDEN
if(!xoscfail_.xoscfden && vreg.xoscfden) { if(!xoscfail_.xoscfden && vreg.xoscfden) {
if(device_->ccpState() & Device::CCP_IOREG) { if(device_->ccpState() & Device::CCP_IOREG) {
xoscfail_.xoscfden = 1; xoscfail_.xoscfden = 1;
} else {
LOGF(ERROR, "cannot set XOSCFAIL.XOSCFDEN: protected by CCP");
}
} else if(xoscfail_.xoscfden && !vreg.xoscfden) {
LOGF(ERROR, "XOSCFAIL.XOSCFDEN cannot be cleared");
}
// XOSCFDIF
if(vreg.xoscfdif) {
xoscfail_.xoscfdif = 0;
}
} else if(addr == 0x04) { // RC32KCAL
rc32kcal_ = v;
} else if(addr == 0x05) { // PLLCTRL
if((v >> 6) == 1) {
LOGF(ERROR, "invalid PLLSRC value");
} else {
pllsrc_ = static_cast<PLLSRC>(v >> 6);
}
pllfac_ = v & 0x1F;
} else if(addr == 0x06) { // DFLLCTRL
//TODO no check nor handling is made here
dfllctrl_.data = v & 0x03;
} else { } else {
LOGF(ERROR, "cannot set XOSCFAIL.XOSCFDEN: protected by CCP"); LOGF(ERROR, "I/O write %s + 0x%02X: not writable") % name() % addr;
}
} else if(xoscfail_.xoscfden && !vreg.xoscfden) {
LOGF(ERROR, "XOSCFAIL.XOSCFDEN cannot be cleared");
} }
// XOSCFDIF */
if(vreg.xoscfdif) {
xoscfail_.xoscfdif = 0;
}
} else if(addr == 0x04) { // RC32KCAL
rc32kcal_ = v;
} else if(addr == 0x05) { // PLLCTRL
if((v >> 6) == 1) {
LOGF(ERROR, "invalid PLLSRC value");
} else {
pllsrc_ = static_cast<PLLSRC>(v >> 6);
}
pllfac_ = v & 0x1F;
} else if(addr == 0x06) { // DFLLCTRL
//TODO no check nor handling is made here
dfllctrl_.data = v & 0x03;
} else {
LOGF(ERROR, "I/O write %s + 0x%02X: not writable") % name() % addr;
}
*/
} }

View File

@ -2,21 +2,21 @@
use devices::DeviceImpl; use devices::DeviceImpl;
use slog::Logger; use slog::Logger;
pub struct RAM { pub struct Ram {
log: Logger, log: Logger,
data: Box<[u8]>, data: Box<[u8]>,
} }
impl RAM { impl Ram {
pub fn new(log: Logger) -> Self { pub fn new(log: Logger) -> Self {
Self { Self {
log: log, log,
data: Box::new([0u8; 0x4000]), data: Box::new([0u8; 0x4000]),
} }
} }
} }
impl DeviceImpl for RAM { impl DeviceImpl for Ram {
fn read(&mut self, addr: u32) -> u8 { fn read(&mut self, addr: u32) -> u8 {
self.data[addr as usize] self.data[addr as usize]
} }

View File

@ -1,7 +1,7 @@
use devices::DeviceImpl; use devices::DeviceImpl;
use std;
use slog::Logger; use slog::Logger;
use std;
const USART_DATA: u32 = 0; const USART_DATA: u32 = 0;
const USART_STATUS: u32 = 1; const USART_STATUS: u32 = 1;
@ -11,7 +11,7 @@ const USART_CTRLC: u32 = 5;
const USART_BAUDCTRLA: u32 = 6; const USART_BAUDCTRLA: u32 = 6;
const USART_BAUDCTRLB: u32 = 7; const USART_BAUDCTRLB: u32 = 7;
pub struct USART { pub struct Usart {
/* /*
0x8A0: 'USARTC0_DATA', 0x8A0: 'USARTC0_DATA',
0x8A1: 'USARTC0_STATUS', 0x8A1: 'USARTC0_STATUS',
@ -31,10 +31,10 @@ pub struct USART {
baudctrlb: u8, baudctrlb: u8,
} }
impl USART { impl Usart {
pub fn new(log: Logger) -> Self { pub fn new(log: Logger) -> Self {
Self { Self {
log: log, log,
status: 0, status: 0,
ctrla: 0, ctrla: 0,
ctrlb: 0, ctrlb: 0,
@ -45,13 +45,13 @@ impl USART {
} }
} }
impl DeviceImpl for USART { impl DeviceImpl for Usart {
fn read(&mut self, addr: u32) -> u8 { fn read(&mut self, addr: u32) -> u8 {
match addr { match addr {
USART_DATA => { USART_DATA => {
info!(self.log, "USART::Read(), not implemented"); info!(self.log, "USART::Read(), not implemented");
0 0
}, }
USART_STATUS => { USART_STATUS => {
// USART_DREIF_bm 0x20 // USART_DREIF_bm 0x20
/* /*
@ -78,23 +78,28 @@ impl DeviceImpl for USART {
6547 #define USART_RXB8_bp 0 // Receive Bit 8 bit position. 6547 #define USART_RXB8_bp 0 // Receive Bit 8 bit position.
6548 6548
*/ */
info!(self.log, "Checking USART status"); info!(self.log, "Checking Usart status");
self.status | 0x20u8 // Data register empty flag. self.status | 0x20u8 // Data register empty flag.
} }
USART_CTRLA => self.ctrla, USART_CTRLA => self.ctrla,
USART_CTRLB => self.ctrlb, USART_CTRLB => self.ctrlb,
USART_CTRLC => self.ctrlc, USART_CTRLC => self.ctrlc,
USART_BAUDCTRLA => self.baudctrla, USART_BAUDCTRLA => self.baudctrla,
USART_BAUDCTRLB => self.baudctrlb, USART_BAUDCTRLB => self.baudctrlb,
_ => unreachable!() _ => unreachable!(),
} }
} }
fn write(&mut self, addr: u32, value: u8) { fn write(&mut self, addr: u32, value: u8) {
match addr { match addr {
USART_DATA => { USART_DATA => {
info!(self.log, "USART::Write({} / {:?})", value, std::char::from_u32(u32::from(value))); info!(
}, self.log,
"USART::Write({} / {:?})",
value,
std::char::from_u32(u32::from(value))
);
}
USART_STATUS => self.status = value, USART_STATUS => self.status = value,
USART_CTRLA => self.ctrla = value, USART_CTRLA => self.ctrla = value,
USART_CTRLB => self.ctrlb = value, USART_CTRLB => self.ctrlb = value,

View File

@ -1,8 +1,8 @@
use std;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashSet; use std::collections::HashSet;
use std;
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use slog; use slog;
@ -59,7 +59,8 @@ impl GDBPacket {
let checksum = u8::from_str_radix( let checksum = u8::from_str_radix(
std::str::from_utf8(&checksum).map_err(|_| (GDBPacketError::InvalidFormat))?, std::str::from_utf8(&checksum).map_err(|_| (GDBPacketError::InvalidFormat))?,
16, 16,
).map_err(|_| (GDBPacketError::InvalidFormat))?; )
.map_err(|_| (GDBPacketError::InvalidFormat))?;
let p = GDBPacket { let p = GDBPacket {
raw_data: decoded_data.clone(), raw_data: decoded_data.clone(),
}; };
@ -90,8 +91,7 @@ impl GDBPacket {
} }
pub fn to_packet_format(&self) -> Vec<u8> { pub fn to_packet_format(&self) -> Vec<u8> {
let mut r = Vec::new(); let mut r = vec![b'$'];
r.push(b'$');
r.extend(self.escaped_data()); r.extend(self.escaped_data());
r.push(b'#'); r.push(b'#');
r.extend(format!("{:02X}", self.gen_checksum()).as_bytes()); r.extend(format!("{:02X}", self.gen_checksum()).as_bytes());
@ -103,7 +103,7 @@ fn split_definitions(pkg: &str) -> Vec<(String, String)> {
let mut res = Vec::new(); let mut res = Vec::new();
for definition in pkg.split(';') { for definition in pkg.split(';') {
let mut v = definition.split(':'); let mut v = definition.split(':');
let first = v.nth(0).unwrap().to_string(); let first = v.next().unwrap().to_string();
res.push((first, v.collect::<String>())); res.push((first, v.collect::<String>()));
} }
res res
@ -123,9 +123,12 @@ impl<'a> GDBStub<'a> {
format!( format!(
"T0520:{:02X};21:{:04X};22:{:08X};", "T0520:{:02X};21:{:04X};22:{:08X};",
self.chip.cpu.sreg, self.chip.cpu.sreg,
self.chip.cpu.get_sp(&mut self.chip.device_tree).swap_bytes(), self.chip
.cpu
.get_sp(&mut self.chip.device_tree)
.swap_bytes(),
(2 * self.chip.cpu.pc).swap_bytes() (2 * self.chip.cpu.pc).swap_bytes()
).to_string() )
} }
fn receive_pkg(&self, stream: &mut TcpStream) -> Result<(String, String), ()> { fn receive_pkg(&self, stream: &mut TcpStream) -> Result<(String, String), ()> {
@ -167,16 +170,13 @@ impl<'a> GDBStub<'a> {
.to_string(); .to_string();
// Split it into command and values. // Split it into command and values.
if response.chars().nth(0).ok_or(())? == 'v' { if response.chars().next().ok_or(())? == 'v' {
// Multibyte word, up to the first ; (or others?). // Multibyte word, up to the first ; (or others?).
let word_payload = response.split(';').collect::<Vec<_>>(); let word_payload = response.split(';').collect::<Vec<_>>();
Ok(( Ok((word_payload[0].to_string(), word_payload[1..].join(";")))
word_payload[0].to_string(),
word_payload[1..].join(";").to_string(),
))
} else { } else {
Ok(( Ok((
response.chars().nth(0).ok_or(())?.to_string(), response.chars().next().ok_or(())?.to_string(),
response.chars().skip(1).collect::<String>(), response.chars().skip(1).collect::<String>(),
)) ))
} }
@ -184,8 +184,8 @@ impl<'a> GDBStub<'a> {
pub fn new(log: slog::Logger, chip: &'a mut chip::Chip) -> Self { pub fn new(log: slog::Logger, chip: &'a mut chip::Chip) -> Self {
Self { Self {
log: log, log,
chip: chip, chip,
breakpoints: HashSet::new(), breakpoints: HashSet::new(),
watchpoints_read: HashSet::new(), watchpoints_read: HashSet::new(),
watchpoints_write: HashSet::new(), watchpoints_write: HashSet::new(),
@ -194,7 +194,7 @@ impl<'a> GDBStub<'a> {
pub fn run(&mut self, port: u16) { pub fn run(&mut self, port: u16) {
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).unwrap(); let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).unwrap();
let mut conn = listener.incoming().nth(0).unwrap().unwrap(); let mut conn = listener.incoming().next().unwrap().unwrap();
info!(self.log, "Debugger attached."); info!(self.log, "Debugger attached.");
// Main debugging loop. // Main debugging loop.
loop { loop {
@ -223,8 +223,10 @@ impl<'a> GDBStub<'a> {
</memory></memory-map>", </memory></memory-map>",
/*self.chip.ram.len()*/ 0x4000, /*self.chip.ram.len()*/ 0x4000,
self.chip.rom.len() self.chip.rom.len()
).to_string().into(); )
}, .to_string()
.into();
}
"C" => response = "01".into(), "C" => response = "01".into(),
query => { query => {
warn!(self.log, "Unknown query: '{}'", query); warn!(self.log, "Unknown query: '{}'", query);
@ -246,7 +248,10 @@ impl<'a> GDBStub<'a> {
// SP // SP
reg_vals.push(format!( reg_vals.push(format!(
"{:04X}", "{:04X}",
self.chip.cpu.get_sp(&mut self.chip.device_tree).swap_bytes() self.chip
.cpu
.get_sp(&mut self.chip.device_tree)
.swap_bytes()
)); ));
// PC // PC
reg_vals.push(format!("{:08X}", (2 * self.chip.cpu.pc).swap_bytes())); reg_vals.push(format!("{:08X}", (2 * self.chip.cpu.pc).swap_bytes()));
@ -257,7 +262,7 @@ impl<'a> GDBStub<'a> {
"s" | "c" => { "s" | "c" => {
// Step / Continue // Step / Continue
// Parse resume from. // Parse resume from.
let resume_from = u32::from_str_radix(&*payload, 16); let resume_from = u32::from_str_radix(&payload, 16);
if let Ok(pc) = resume_from { if let Ok(pc) = resume_from {
self.chip.cpu.pc = pc; self.chip.cpu.pc = pc;
} }
@ -334,7 +339,10 @@ impl<'a> GDBStub<'a> {
err = true; err = true;
break; break;
} }
self.chip.device_tree.write(addr_i as u32, u8::from_str_radix(&value[2 * i..2 * (i + 1)], 16).unwrap_or(0)); self.chip.device_tree.write(
addr_i as u32,
u8::from_str_radix(&value[2 * i..2 * (i + 1)], 16).unwrap_or(0),
);
} else { } else {
// ROM // ROM
if addr >= self.chip.rom.len() { if addr >= self.chip.rom.len() {

View File

@ -1,8 +1,8 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use std::path::Path; use std::fs;
use std::io; use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::fs; use std::path::Path;
#[macro_use] #[macro_use]
extern crate slog; extern crate slog;
@ -11,13 +11,13 @@ extern crate slog_term;
use slog::Drain; use slog::Drain;
mod cpu;
mod regs;
mod decoder;
mod devices;
mod chip; mod chip;
mod chip_definitions; mod chip_definitions;
mod cpu;
mod decoder;
mod devices;
mod gdbstub; mod gdbstub;
mod regs;
fn main() { fn main() {
let decorator = slog_term::PlainDecorator::new(std::io::stdout()); let decorator = slog_term::PlainDecorator::new(std::io::stdout());
@ -34,11 +34,12 @@ fn main() {
std::env::args() std::env::args()
.nth(1) .nth(1)
.unwrap_or_else(|| "rom.bin".to_string()), .unwrap_or_else(|| "rom.bin".to_string()),
).unwrap(); )
.unwrap();
let mut chip = chip::Chip::new(log.clone(), rom); let mut chip = chip::Chip::new(log.clone(), rom);
if std::env::args().nth(2).unwrap_or("0".to_string()) == "gdb" { if std::env::args().nth(2).unwrap_or_else(|| "0".to_string()) == "gdb" {
// Use GDBStub // Use GDBStub
info!(log, "Enabling GDB backend"); info!(log, "Enabling GDB backend");
gdbstub::run(log.clone(), &mut chip); gdbstub::run(log.clone(), &mut chip);
@ -52,14 +53,14 @@ fn main() {
} }
pub fn read_file<P: AsRef<Path>>(rom_path: P) -> Result<Box<[u8]>, io::Error> { pub fn read_file<P: AsRef<Path>>(rom_path: P) -> Result<Box<[u8]>, io::Error> {
let mut file = try!(fs::File::open(rom_path)); let mut file = fs::File::open(rom_path)?;
let mut buf = Vec::new(); let mut buf = Vec::new();
try!(file.read_to_end(&mut buf)); file.read_to_end(&mut buf)?;
Ok(buf.into_boxed_slice()) Ok(buf.into_boxed_slice())
} }
pub fn write_file<P: AsRef<Path>>(path: P, data: &[u8]) -> Result<(), io::Error> { pub fn write_file<P: AsRef<Path>>(path: P, data: &[u8]) -> Result<(), io::Error> {
let mut file = try!(fs::File::create(path)); let mut file = fs::File::create(path)?;
try!(file.write_all(data)); file.write_all(data)?;
Ok(()) Ok(())
} }

View File

@ -41,9 +41,9 @@ impl fmt::Display for StatusFlag {
} }
} }
impl Into<u8> for StatusFlag { impl From<StatusFlag> for u8 {
fn into(self) -> u8 { fn from(sf: StatusFlag) -> u8 {
1 << match self { 1 << match sf {
StatusFlag::GlobalInterruptEnable => 7, StatusFlag::GlobalInterruptEnable => 7,
StatusFlag::BitCopyStorage => 6, StatusFlag::BitCopyStorage => 6,
StatusFlag::HalfCarry => 5, StatusFlag::HalfCarry => 5,
@ -98,19 +98,18 @@ impl From<u8> for GeneralPurposeRegister {
if v > 31 { if v > 31 {
unreachable!(); unreachable!();
} }
Self { 0: v } Self(v)
} }
} }
impl Into<u8> for GeneralPurposeRegister { impl From<GeneralPurposeRegister> for u8 {
fn into(self) -> u8 { fn from(r: GeneralPurposeRegister) -> u8 {
self.0 r.0
} }
} }
impl From<GeneralPurposeRegister> for usize {
impl Into<usize> for GeneralPurposeRegister { fn from(r: GeneralPurposeRegister) -> usize {
fn into(self) -> usize { r.0.into()
self.0 as usize
} }
} }
@ -142,13 +141,13 @@ impl From<u8> for GeneralPurposeRegisterPair {
println!("v={}", v); println!("v={}", v);
unreachable!(); unreachable!();
} }
Self { 0: v } Self(v)
} }
} }
impl Into<u8> for GeneralPurposeRegisterPair { impl From<GeneralPurposeRegisterPair> for u8 {
fn into(self) -> u8 { fn from(v: GeneralPurposeRegisterPair) -> u8 {
self.0 v.0
} }
} }