diff --git a/src/chip.rs b/src/chip.rs index 342cd99..b77a352 100644 --- a/src/chip.rs +++ b/src/chip.rs @@ -1,27 +1,53 @@ use cpu::CPU; +use devices; use slog; + pub struct Chip { log: slog::Logger, pub cpu: CPU, pub rom: Box<[u8]>, - pub ram: Box<[u8]>, + pub device_tree: devices::DeviceTree, + // TODO: List of devices } impl Chip { pub fn new(log: slog::Logger, rom: Box<[u8]>) -> Chip { + // Internal registers + let internal_regs = devices::ram::RAM::new(log.clone()); + let ram_device = devices::ram::RAM::new(log.clone()); + let usart_device = devices::usart::USART::new(log.clone()); + let mut dev_tree = devices::DeviceTree::new(log.clone()); + + // Add RAM and USART + dev_tree.add_device( + devices::Device::new(Box::new(ram_device), 0x2000, 0x2000) + ); + dev_tree.add_device( + 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 { log: log.clone(), cpu: CPU::new(log), rom: rom, - ram: Box::new([0u8; 0x4000]), + device_tree: dev_tree, } } pub fn step(&mut self) -> bool { - match self.cpu.step(&mut self.rom, &mut self.ram) { + match self.cpu.step(&mut self.rom, &mut self.device_tree) { Ok(_) => true, Err(ref e) => { warn!(self.log, "Error occured: {:?}", e); diff --git a/src/cpu.rs b/src/cpu.rs index e8a6c1a..3aa1e51 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -6,6 +6,8 @@ use decoder::{IncrementMode, Instruction}; use regs::{GeneralPurposeRegister, GeneralPurposeRegisterPair, StatusFlag}; use chip_definitions; +use devices::DeviceTree; + use std::fmt; use slog; @@ -73,14 +75,15 @@ impl CPU { } } - pub fn get_sp(&self, mem: &[u8]) -> u16 { - u16::from(mem[chip_definitions::IOAdress::SPL as usize]) - | (u16::from(mem[chip_definitions::IOAdress::SPH as usize]) << 8) + pub fn get_sp(&self, mem: &mut DeviceTree) -> u16 { + let spl: u16 = mem.read(chip_definitions::IOAdress::SPL as u32) as u16; + let sph: u16 = mem.read(chip_definitions::IOAdress::SPH as u32) as u16; + sph << 8 | spl } - fn set_sp(&self, mem: &mut [u8], val: u16) { - mem[chip_definitions::IOAdress::SPL as usize] = val as u8; - mem[chip_definitions::IOAdress::SPH as usize] = (val >> 8) as u8; + fn set_sp(&self, mem: &mut DeviceTree, val: u16) { + mem.write(chip_definitions::IOAdress::SPL as u32, val as u8); + mem.write(chip_definitions::IOAdress::SPH as u32, (val >> 8) as u8); } fn test_flag(&self, flag: StatusFlag) -> bool { @@ -121,163 +124,26 @@ impl CPU { self.registers[r.as_usize()] = v; } - fn ram_write(&self, ram: &mut [u8], addr: u16, val: u8) -> Result<(), CPUError> { - if addr as usize >= ram.len() { - error!(self.logger, "Ram write OOB: {:04X}={:02X}] ", addr, val); - Err(CPUError::OutOfBoundsException) - } else { - if addr < 0x2000 { - if addr != chip_definitions::IOAdress::SPH as u16 - && addr != chip_definitions::IOAdress::SPL as u16 - { - // info!(self.logger, "Writing to IOR: {:04X} = {:02X}", addr, val); - } - if addr == chip_definitions::IOAdress::USARTC0_DATA as u16 { - // print!("USART_OUT:{: <3} ({}) ", val, (val as char).escape_debug()); - info!( - self.logger, - "UART output: {: <3} ({})", - val, - (val as char).escape_debug() - ); - } /* else if addr == chip_definitions::IOAdress::SPL as u16 { - - } else if addr == chip_definitions::IOAdress::SPH as u16 { - - } else if addr == chip_definitions::IOAdress::SREG as u16 { - - } else if addr == chip_definitions::IOAdress::EIND as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPX as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPY as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPZ as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPD as u16 { - - } else if addr == chip_definitions::IOAdress::OSC_CTRL as u16 { - - } else if addr == chip_definitions::IOAdress::OSC_STATUS as u16 { - - } else if addr == chip_definitions::IOAdress::CCP as u16 { - - } else if addr == chip_definitions::IOAdress::CLK_CTRL as u16 { - - } else if addr == 0x645 || addr == 0x641 || addr == 0x642 || addr == 0x646 { // PortC stuff - - } else if addr == 0x8A3 || addr == 0x8A4 || addr == 0x8A5 || addr == 0x08A6 || addr == 0x8A7 { // Usart - - } else if addr >= 0x1C0 && addr < 0x200 { // NVM - - } else if addr == 0x600 || addr == 0x680 || addr == 0x626 || addr == 0x621 { // PortA/PortE - - } else if addr == 0xA00 || addr == 0xA01 || addr == 0xA28 || addr == 0xA29 { // TCE0_CTRLA - - } else if addr == 0xA2 { // PMIC - - } else if addr == 0x43 { // CLK_RTCCTRL - - } else if addr == 0x400 || addr == 0x401 || addr == 0x402 || addr == 0x40A || addr == 0x40B { // RTC_STATUS - - } else if addr == 0x320 || addr == 0x321 || addr == 0x322 || addr == 0x328 || addr == 0x329 || addr == 0x32A || addr == 0x32B { // Dac - //} else if addr == 0x238{ - - } else { - return Err(CPUError::UnsupportedAddress); - }*/ - } - ram[addr as usize] = val; - Ok(()) - } - } - - fn ram_read(&self, ram: &[u8], addr: u16) -> Result { - // print!("[RAMR:{:04X}] ", addr); - if addr as usize >= ram.len() { - Err(CPUError::OutOfBoundsException) - } else { - // TODO: Hooks - if addr == chip_definitions::IOAdress::USARTC0_DATA as _ { - info!(self.logger, "Read from USART"); - // return Err(CPUError::Exit); - // return Ok(b'\r') - // return Ok(0); - } else if addr == chip_definitions::IOAdress::USARTC0_STATUS as _ { - // info!(self.logger, "Read from USART status"); - if self.pc == 0x5AC { - // USART data check -> Yes, there is indeed data available! - return Ok(0x80); - } else { - return Ok(0x20); // Usart is ready to send. - } - } else if addr == chip_definitions::IOAdress::OSC_STATUS as _ { - // HACK: Osci is set right.. - return Ok(0x02); - } else if addr < 0x2000 { - if addr != chip_definitions::IOAdress::SPH as u16 - && addr != chip_definitions::IOAdress::SPL as u16 - { - info!(self.logger, "Reading from IOR: {:04X}", addr); - } - /* - if addr == chip_definitions::IOAdress::SPL as u16 { - - } else if addr == chip_definitions::IOAdress::SPH as u16 { - - } else if addr == chip_definitions::IOAdress::SREG as u16 { - - } else if addr == chip_definitions::IOAdress::EIND as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPX as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPY as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPZ as u16 { - - } else if addr == chip_definitions::IOAdress::RAMPD as u16 { - - } else if addr == chip_definitions::IOAdress::OSC_CTRL as u16 { - - } else if addr == chip_definitions::IOAdress::OSC_STATUS as u16 { - - } else if addr == chip_definitions::IOAdress::CCP as u16 { - - } else if addr > 0x1C0 && addr < 0x200 { // NVM status - - } else if addr == 0x8A3 || addr == 0x8A4 { // Usart - - } else if addr == 0xA2 { // PMIC - - } else if addr == 0x402 { // RTC_INTCTRL - - } else if addr == 0x400 || addr == 0x401 || addr == 0x402 { // RTC_CTRL - - } else if addr == 0x320 || addr == 0x321 || addr == 0x322 { - // DAC? @DD2E - } else if addr == 0x230 || addr == 0x231 || addr == 0x234 || addr == 0x235 { // ADC - } else if addr >= 0x1f00 { - - } else { - return Err(CPUError::UnsupportedAddress); - } - */ - } - Ok(ram[addr as usize]) - } - } - - fn push(&mut self, ram: &mut [u8], val: u8) -> Result<(), CPUError> { - let sp = self.get_sp(ram); - self.ram_write(ram, sp, val)?; - self.set_sp(ram, sp.wrapping_sub(1)); + fn ram_write(&self, device_tree: &mut DeviceTree, addr: u16, val: u8) -> Result<(), CPUError> { + device_tree.write(addr as u32, val); Ok(()) } - fn pop(&mut self, ram: &mut [u8]) -> Result { - let sp = self.get_sp(ram); - self.set_sp(ram, sp.wrapping_add(1)); - self.ram_read(ram, sp.wrapping_add(1)) + fn ram_read(&self, device_tree: &mut DeviceTree, addr: u16) -> Result { + Ok(device_tree.read(addr as u32)) + } + + fn push(&mut self, device_tree: &mut DeviceTree, val: u8) -> Result<(), CPUError> { + let sp = self.get_sp(device_tree); + self.ram_write(device_tree, sp, val)?; + self.set_sp(device_tree, sp.wrapping_sub(1)); + Ok(()) + } + + fn pop(&mut self, device_tree: &mut DeviceTree) -> Result { + let sp = self.get_sp(device_tree); + self.set_sp(device_tree, sp.wrapping_add(1)); + self.ram_read(device_tree, sp.wrapping_add(1)) } // Flag update functions on a single value: @@ -366,7 +232,7 @@ impl CPU { } // Returns # of ticks the executed instruction took - pub fn step(&mut self, rom: &mut [u8], ram: &mut [u8]) -> Result { + pub fn step(&mut self, rom: &mut [u8], device_tree: &mut DeviceTree) -> Result { // Instruction fetch if (self.pc as usize) * 2 >= rom.len() { return Err(CPUError::OutOfBoundsException); @@ -380,7 +246,7 @@ impl CPU { self.logger, "CPU: pc={:06X} sp={:04X} Fetch: {: <40}", self.pc, - self.get_sp(ram), + self.get_sp(device_tree), format!("{}", ins) ); @@ -449,10 +315,12 @@ impl CPU { } IncrementMode::ConstantOffset(o) => base.wrapping_add(u16::from(o)), }; - self.ram_write(ram, 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) => { let base = self.get_register_pair(ptr); + /* + // TODO: RAMPX/Y/Z if ptr.low() == 26 && ram[chip_definitions::IOAdress::RAMPX as usize] > 0 { panic!("Unexpected"); } else if ptr.low() == 28 && ram[chip_definitions::IOAdress::RAMPY as usize] > 0 { @@ -460,6 +328,7 @@ impl CPU { } else if ptr.low() == 30 && ram[chip_definitions::IOAdress::RAMPZ as usize] > 0 { panic!("Unexpected"); } + */ let addr = match *inc_mode { IncrementMode::None => base, IncrementMode::PreDecrement => { @@ -472,20 +341,21 @@ impl CPU { } IncrementMode::ConstantOffset(o) => base.wrapping_add(u16::from(o)), }; - let v = self.ram_read(ram, addr)?; + let v = self.ram_read(device_tree, addr)?; self.set_register(dst_reg, v); } Instruction::ELPM(ref dst_reg, ref inc_mode) => { let Zb = self.get_register_pair(&30u8.into()); // TODO: Only use required bits, other read as zero (according to datasheet) let Z = - Zb as usize | (ram[chip_definitions::IOAdress::RAMPZ as usize] as usize) << 16; + Zb as usize | + (device_tree.read(chip_definitions::IOAdress::RAMPZ as u32) as usize) << 16; + match *inc_mode { IncrementMode::PostIncrement => { self.set_register_pair(&30u8.into(), Zb.wrapping_add(1)); - ram[chip_definitions::IOAdress::RAMPZ as usize] = - (Z.wrapping_add(1) >> 16) as u8; - } + device_tree.write(chip_definitions::IOAdress::RAMPZ as u32, (Z.wrapping_add(1) >> 16) as u8); + }, _ => { // This instruction does only support None + PostIncrement } @@ -519,40 +389,40 @@ impl CPU { } Instruction::OUT(ref addr, ref val) => { let val = self.get_register(val); - self.ram_write(ram, *addr, val)?; - } + self.ram_write(device_tree, *addr, val)?; + }, Instruction::IN(ref reg, ref addr) => { - let v = self.ram_read(ram, *addr)?; + let v = self.ram_read(device_tree, *addr)?; self.set_register(reg, v); } Instruction::CALL(ref addr) => { let ret_to = self.pc; - self.push(ram, ((ret_to >> 16) & 0xFF) as u8)?; - self.push(ram, ((ret_to >> 8) & 0xFF) as u8)?; - self.push(ram, (ret_to & 0xFF) as u8)?; + self.push(device_tree, ((ret_to >> 16) & 0xFF) as u8)?; + self.push(device_tree, ((ret_to >> 8) & 0xFF) as u8)?; + self.push(device_tree, (ret_to & 0xFF) as u8)?; self.pc = *addr; } Instruction::RCALL(ref addr) => { let ret_to = self.pc; - self.push(ram, ((ret_to >> 16) & 0xFF) as u8)?; - self.push(ram, ((ret_to >> 8) & 0xFF) as u8)?; - self.push(ram, (ret_to & 0xFF) as u8)?; - self.pc = ((self.pc as i32) + i32::from(*addr)) as u32; - } + self.push(device_tree, ((ret_to >> 16) & 0xFF) as u8)?; + self.push(device_tree, ((ret_to >> 8) & 0xFF) as u8)?; + self.push(device_tree, (ret_to & 0xFF) as u8)?; + self.pc = (self.pc as i32 + *addr as i32) as u32; + }, Instruction::RET => { - let mut ret_to = u32::from(self.pop(ram)?); - ret_to += u32::from(self.pop(ram)?) << 8; - ret_to += u32::from(self.pop(ram)?) << 16; + 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) << 16; self.pc = ret_to as _; } Instruction::POP(ref reg) => { - let v = self.pop(ram)?; + let v = self.pop(device_tree)?; self.registers[reg.as_usize()] = v; } Instruction::PUSH(ref reg) => { let v = self.registers[reg.as_usize()]; - self.push(ram, v)?; - } + self.push(device_tree, v)?; + }, Instruction::SUBI(ref d, ref v) => { let dv = self.get_register(d); let vres = dv.wrapping_sub(*v); @@ -675,25 +545,21 @@ impl CPU { self.update_flags_zns_8(res); } Instruction::STS16(ref addr, ref r) => { - let rampd = u32::from(ram[chip_definitions::IOAdress::RAMPD as usize]); - if rampd != 0 { - panic!("This is unexpected (for now)"); - } - self.ram_write(ram, *addr, self.get_register(r))?; - } + let rampd = device_tree.read(chip_definitions::IOAdress::RAMPD as u32); + if rampd != 0 { panic!("This is unexpected (for now)"); } + self.ram_write(device_tree, *addr, self.get_register(r))?; + }, Instruction::STS8(ref addr, ref r) => { - self.ram_write(ram, u16::from(*addr), self.get_register(r))?; - } + self.ram_write(device_tree, *addr as u16, self.get_register(r))?; + }, Instruction::LDS16(ref r, ref addr) => { - let rampd = u32::from(ram[chip_definitions::IOAdress::RAMPD as usize]); - if rampd != 0 { - panic!("This is unexpected (for now)"); - } - let v = self.ram_read(ram, *addr)?; + let rampd = device_tree.read(chip_definitions::IOAdress::RAMPD as u32); + if rampd != 0 { panic!("This is unexpected (for now)"); } + let v = self.ram_read(device_tree, *addr)?; self.set_register(r, v); } Instruction::LDS8(ref r, ref addr) => { - let v = self.ram_read(ram, u16::from(*addr))?; + let v = self.ram_read(device_tree, *addr as u16)?; self.set_register(r, v); } Instruction::LSL(ref r) => { diff --git a/src/devices/mod.rs b/src/devices/mod.rs new file mode 100644 index 0000000..69f7ddb --- /dev/null +++ b/src/devices/mod.rs @@ -0,0 +1,79 @@ +// All devices are implemented here. + +use slog::Logger; + +pub mod ram; +pub mod usart; +pub mod oscillator; + +pub trait DeviceImpl { + /// addr relative to the start of the device memory map. + fn read(&mut self, addr: u32) -> u8; + /// addr relative to the start of the device memory map. + fn write(&mut self, addr: u32, value: u8); +} + +pub struct Device { + start_addr: u32, + addr_len: u32, + device: Box, +} + +impl Device { + pub fn new(device: Box, start_addr: u32, addr_len: u32) -> Self { + Self { + start_addr: start_addr, + addr_len: addr_len, + device: device, + } + } + + pub fn handles_addr(&self, addr: u32) -> bool { + addr >= self.start_addr && addr - self.start_addr < self.addr_len + } + + pub fn read(&mut self, addr: u32) -> u8 { + self.device.read(addr - self.start_addr) + } + + pub fn write(&mut self, addr: u32, val: u8) { + self.device.write(addr - self.start_addr, val) + } +} + +pub struct DeviceTree { + log: Logger, + devices: Vec, +} + +impl DeviceTree { + pub fn new(log: Logger) -> Self { + Self { + log: log, + devices: Vec::new(), + } + } + + pub fn add_device(&mut self, device: Device) { + self.devices.push(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) + } + + pub fn read(&mut self, addr: u32) -> u8 { + if let Some(ref mut d) = self.get_device_for_addr(addr) { + return d.read(addr); + } + warn!(self.log, "Trying to read unmapped I/O: {:08X}", addr); + 0 + } + + pub fn write(&mut self, addr: u32, val: u8) { + if let Some(ref mut d) = self.get_device_for_addr(addr) { + return d.write(addr, val); + } + warn!(self.log, "Trying to write unmapped I/O: {:08X} <- {:02X}", addr, val); + } +} diff --git a/src/devices/oscillator.rs b/src/devices/oscillator.rs new file mode 100644 index 0000000..80ccfeb --- /dev/null +++ b/src/devices/oscillator.rs @@ -0,0 +1,120 @@ +// Oscillator +use devices::DeviceImpl; +use slog::Logger; + +const OSC_CTRL: u32 = 0; +const OSC_STATUS: u32 = 1; +const OSC_XOSCCTRL: u32 = 2; +const OSC_XOSCFAIL: u32 = 3; +const OSC_RC32KCAL: u32 = 4; +const OSC_PLLCTRL: u32 = 5; +const OSC_DFLLCTRL: u32 = 6; + +enum PllSrc { + RC2M, + RC32M, + XOSC, +} + +pub struct Oscillator { + log: Logger, + reg_values: [u8; 7], + + // Real attributes: + ctrl: u8, + status: u8, + xoscctrl: u8, + xoscfail: u8, + rs32kcal: u8, + pllsrc: PllSrc, + pllfac: u8, + dfllctrl: u8, +} + +impl Oscillator { + pub fn new(log: Logger) -> Self { + Self { + log: log, + reg_values: [0u8; 7], + + ctrl: 0, + status: 0, + xoscctrl: 0, + xoscfail: 0, + rs32kcal: 0, + pllsrc: PllSrc::RC2M, + pllfac: 0, + dfllctrl: 0, + } + } +} + +impl DeviceImpl for Oscillator { + fn read(&mut self, addr: u32) -> u8 { + match addr { + OSC_CTRL => { + // PLL and clock ready. + return self.ctrl | 0x30; + } + OSC_STATUS => { + return self.status | 0x30; + } + _ => {} + } + self.reg_values[addr as usize] + } + + fn write(&mut self, addr: u32, value: u8) { + match addr { + OSC_CTRL => { + info!(self.log, "OSC_CTRL <= {:02X}", value); + self.ctrl = value & 0x1F; + self.status = value & 0x1F; + } + OSC_XOSCCTRL => { + self.xoscctrl = value & 0xEF; + } + OSC_XOSCFAIL => { + + }, + + _ => {} + } + self.reg_values[addr as usize] = value; + } + +/* + } else if(addr == 0x03) { // XOSCFAIL + XOSCFAIL vreg; + vreg.data = v & 0x03; + // XOSCFDEN + if(!xoscfail_.xoscfden && vreg.xoscfden) { + if(device_->ccpState() & Device::CCP_IOREG) { + 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(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; +} +*/ +} diff --git a/src/devices/ram.rs b/src/devices/ram.rs new file mode 100644 index 0000000..fea1d2e --- /dev/null +++ b/src/devices/ram.rs @@ -0,0 +1,27 @@ +// RAM 'device' +use devices::DeviceImpl; +use slog::Logger; + +pub struct RAM { + log: Logger, + data: Box<[u8]>, +} + +impl RAM { + pub fn new(log: Logger) -> Self { + Self { + log: log, + data: Box::new([0u8; 0x4000]), + } + } +} + +impl DeviceImpl for RAM { + fn read(&mut self, addr: u32) -> u8 { + self.data[addr as usize] + } + + fn write(&mut self, addr: u32, value: u8) { + self.data[addr as usize] = value; + } +} diff --git a/src/devices/usart.rs b/src/devices/usart.rs new file mode 100644 index 0000000..5a13e5c --- /dev/null +++ b/src/devices/usart.rs @@ -0,0 +1,79 @@ +use devices::DeviceImpl; + +use std; +use slog::Logger; + +const USART_DATA: u32 = 0; +const USART_STATUS: u32 = 1; +const USART_CTRLA: u32 = 3; +const USART_CTRLB: u32 = 4; +const USART_CTRLC: u32 = 5; +const USART_BAUDCTRLA: u32 = 6; +const USART_BAUDCTRLB: u32 = 7; + +pub struct USART { + /* + 0x8A0: 'USARTC0_DATA', + 0x8A1: 'USARTC0_STATUS', + 0x8A3: 'USARTC0_CTRLA', + 0x8A4: 'USARTC0_CTRLB', + 0x8A5: 'USARTC0_CTRLC', + 0x8A6: 'USARTC0_BAUDCTRLA', + 0x8A7: 'USARTC0_BAUDCTRLB', + */ + log: Logger, + // Raw values: + status: u8, + ctrla: u8, + ctrlb: u8, + ctrlc: u8, + baudctrla: u8, + baudctrlb: u8, +} + +impl USART { + pub fn new(log: Logger) -> Self { + Self { + log: log, + status: 0, + ctrla: 0, + ctrlb: 0, + ctrlc: 0, + baudctrla: 0, + baudctrlb: 0, + } + } +} + +impl DeviceImpl for USART { + fn read(&mut self, addr: u32) -> u8 { + match addr { + USART_DATA => { + info!(self.log, "USART::Read(), not implemented"); + 0 + }, + USART_STATUS => self.status, + USART_CTRLA => self.ctrla, + USART_CTRLB => self.ctrlb, + USART_CTRLC => self.ctrlc, + USART_BAUDCTRLA => self.baudctrla, + USART_BAUDCTRLB => self.baudctrlb, + _ => unreachable!() + } + } + + fn write(&mut self, addr: u32, value: u8) { + match addr { + USART_DATA => { + info!(self.log, "USART::Write({} / {:?})", value, std::char::from_u32(u32::from(value))); + }, + USART_STATUS => self.status = value, + USART_CTRLA => self.ctrla = value, + USART_CTRLB => self.ctrlb = value, + USART_CTRLC => self.ctrlc = value, + USART_BAUDCTRLA => self.baudctrla = value, + USART_BAUDCTRLB => self.baudctrlb = value, + _ => panic!("Write to usart offset {} <- {:02X}", addr, value), + } + } +} \ No newline at end of file diff --git a/src/gdbstub.rs b/src/gdbstub.rs index b077887..d1c6d29 100644 --- a/src/gdbstub.rs +++ b/src/gdbstub.rs @@ -118,12 +118,12 @@ struct GDBStub<'a> { } impl<'a> GDBStub<'a> { - fn stop_reply(&self) -> String { + fn stop_reply(&mut self) -> String { // Send SIGTRAP along with SREG/SP/PC. format!( "T0520:{:02X};21:{:04X};22:{:08X};", self.chip.cpu.sreg, - self.chip.cpu.get_sp(&self.chip.ram).swap_bytes(), + self.chip.cpu.get_sp(&mut self.chip.device_tree).swap_bytes(), (2 * self.chip.cpu.pc).swap_bytes() ).to_string() } @@ -217,15 +217,14 @@ impl<'a> GDBStub<'a> { "Xfer" => { response = format!( "l\n\ - \n\ - \n\ - 0x80\n\ - ", - self.chip.ram.len(), + \n\ + \n\ + 0x80\n\ + ", + /*self.chip.ram.len()*/ 0x4000, self.chip.rom.len() - ).to_string() - .into(); - } + ).to_string().into(); + }, "C" => response = "01".into(), query => { warn!(self.log, "Unknown query: '{}'", query); @@ -247,7 +246,7 @@ impl<'a> GDBStub<'a> { // SP reg_vals.push(format!( "{:04X}", - self.chip.cpu.get_sp(&self.chip.ram).swap_bytes() + self.chip.cpu.get_sp(&mut self.chip.device_tree).swap_bytes() )); // PC reg_vals.push(format!("{:08X}", (2 * self.chip.cpu.pc).swap_bytes())); @@ -292,14 +291,14 @@ impl<'a> GDBStub<'a> { if addr & 0x00f00000 > 0 { // RAM: let addr_i = addr & 0xFFFFF; - if addr_i >= self.chip.ram.len() { + if addr_i >= 0x4000 { // Partial read case. if data.is_empty() { err = true; } break; } - data.push(format!("{:02X}", self.chip.ram[addr_i])); + data.push(format!("{:02X}", self.chip.device_tree.read(addr_i as u32))); } else { // ROM if addr >= self.chip.rom.len() { @@ -331,12 +330,11 @@ impl<'a> GDBStub<'a> { if addr & 0x00f00000 > 0 { // RAM: let addr_i = addr & 0xFFFFF; - if addr_i >= self.chip.ram.len() { + if addr_i >= 0x4000 { err = true; break; } - self.chip.ram[addr_i] = - 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 { // ROM if addr >= self.chip.rom.len() { diff --git a/src/main.rs b/src/main.rs index 97d2388..887d221 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ use slog::Drain; mod cpu; mod regs; mod decoder; +mod devices; mod chip; mod chip_definitions; mod gdbstub; @@ -46,7 +47,8 @@ fn main() { while chip.step() {} } warn!(log, "{}", &chip.cpu); - write_file("ram.dmp", &chip.ram).unwrap(); + // TODO: Figure out how to write an full ram dump easily. + // write_file("ram.dmp", &chip.ram).unwrap(); } pub fn read_file>(rom_path: P) -> Result, io::Error> {