From 71fecb51a9d55db482b8615cfe2960b27b9689ac Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Tue, 13 Feb 2018 00:42:42 +0100 Subject: [PATCH] Add logging and random stuff --- Cargo.toml | 3 + src/chip_definitions.rs | 8 ++ src/cpu.rs | 166 ++++++++++++++++++++++++++++++++++++---- src/decoder.rs | 7 +- src/main.rs | 40 +++++++--- 5 files changed, 195 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f003cac..42aeaee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,6 @@ version = "0.1.0" authors = ["Kevin Hamacher "] [dependencies] +slog = "2" +slog-term = "2" +slog-async = "2" diff --git a/src/chip_definitions.rs b/src/chip_definitions.rs index cc5a597..b368d10 100644 --- a/src/chip_definitions.rs +++ b/src/chip_definitions.rs @@ -55,6 +55,14 @@ pub enum IOAdress { SPL = 0x03D, SPH = 0x03E, SREG = 0x03F, + + CLK_CTRL = 0x040, + CLK_PSCTRL = 0x041, + CLK_LOCK = 0x042, + CLK_RTCCTRL = 0x043, + CLK_USBCTRL = 0x044, + + OSC_CTRL = 0x050, OSC_STATUS = 0x051, USARTC0_DATA = 0x8A0, USARTC0_STATUS = 0x8A1, diff --git a/src/cpu.rs b/src/cpu.rs index db8165a..c041bad 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -8,6 +8,9 @@ use chip_definitions; use std::fmt; +use slog; + + #[derive(Debug)] pub enum CPUError { UnimplementedInstruction, @@ -28,6 +31,8 @@ pub struct CPU { // The same is true for the status register pub sreg: u8, + + logger: slog::Logger, } @@ -45,7 +50,7 @@ impl fmt::Display for CPU { } write!(f, "\n")?; for i in 0..32 { - write!(f, " R{:-2} = 0x{:02X} ", i, self.registers[i])?; + write!(f, " R{:-2}={:02X} ", i, self.registers[i])?; if (i + 1) % 10 == 0{ write!(f, "\n")?; } @@ -55,11 +60,12 @@ impl fmt::Display for CPU { } impl CPU { - pub fn new() -> Self { + pub fn new(logger: slog::Logger) -> Self { CPU { registers: [0u8; 32], pc: 0, // Reset vector sreg: 0, // Uninitialized as well + logger: logger } } @@ -86,7 +92,7 @@ impl CPU { } fn set_clear_flag(&mut self, flag: StatusFlag, test: bool) { - print!("[{}->{}] ", flag, test); + // print!("[{}->{}] ", flag, test); if test { self.set_flag(flag); } else { @@ -112,13 +118,63 @@ impl CPU { } fn ram_write(&self, ram: &mut [u8], addr: u16, val: u8) -> Result<(), CPUError> { - print!("[RAMW:{:04X}={:02X}] ", addr, val); + // print!("[RAMW:{:04X}={:02X}] ", addr, val); if addr as usize >= ram.len() { Err(CPUError::OutOfBoundsException) } else { - // TODO: Hooks - if addr == chip_definitions::IOAdress::USARTC0_DATA as _ { - print!("USART_OUT:{: <3} ({}) ", val, (val as char).escape_debug()); + 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(()) @@ -126,14 +182,18 @@ impl CPU { } fn ram_read(&self, ram: &[u8], addr: u16) -> Result { - print!("[RAMR:{:04X}] ", addr); + // print!("[RAMR:{:04X}] ", addr); if addr as usize >= ram.len() { Err(CPUError::OutOfBoundsException) } else { // TODO: Hooks if addr == chip_definitions::IOAdress::USARTC0_DATA as _ { - return Err(CPUError::Exit); + 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); @@ -143,6 +203,52 @@ impl CPU { } 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]) } @@ -248,7 +354,7 @@ impl CPU { Ok(v) => v, Err(e) => return Err(CPUError::DecodingError(e)), }; - print!("CPU: pc={:06X} sp={:04X} Fetch: {: <40} -> ", self.pc, self.get_sp(ram), format!("{}", ins)); + debug!(self.logger, "CPU: pc={:06X} sp={:04X} Fetch: {: <40}", self.pc, self.get_sp(ram), format!("{}", ins)); self.pc += (ins.size() / 2) as u32; @@ -266,7 +372,13 @@ impl CPU { }, Instruction::LDI(ref r, v) => self.set_register(r, v), Instruction::SER(ref r) => self.set_register(r, 0xFF), - Instruction::RJMP(v) => self.pc = self.pc.wrapping_add(v as _), + Instruction::RJMP(v) => { + if v == -1 && self.test_flag(StatusFlag::GlobalInterruptEnable) == false { + info!(self.logger, "HALTED "); + return Err(CPUError::Exit); + } + self.pc = self.pc.wrapping_add(v as _); + }, Instruction::CLR_FLAG(v) => self.clear_flag(v), Instruction::SET_FLAG(v) => self.set_flag(v), Instruction::CPI(ref r, v) => { @@ -313,6 +425,13 @@ impl CPU { }, Instruction::LD(ref dst_reg, ref ptr, ref inc_mode) => { let base = self.get_register_pair(ptr); + 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 { + panic!("Unexpected"); + } 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 => { @@ -329,18 +448,29 @@ impl CPU { self.set_register(dst_reg, v); }, Instruction::ELPM(ref dst_reg, ref inc_mode) => { - // TODO: RAMPZ - let Z = self.get_register_pair(&30u8.into()); - let d = rom[Z as usize]; - self.set_register(dst_reg, d); + + 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 + ; match *inc_mode { IncrementMode::PostIncrement => { - self.set_register_pair(&30u8.into(), Z.wrapping_add(1)); + self.set_register_pair(&30u8.into(), Zb.wrapping_add(1)); + ram[chip_definitions::IOAdress::RAMPZ as usize] = (Z.wrapping_add(1) >> 16) as u8; }, _ => { // This instruction does only support None + PostIncrement }, } + if Z >= rom.len() { + warn!(self.logger, "ELPM OOB: RAMPZ={:02X} Z={:04X} len={:06X} ", Z >> 16, Zb, rom.len()); + // return Err(CPUError::OutOfBoundsException); + return Ok(0xFF); // Hack I kno but emulator does it like that + } + let d = rom[Z as usize]; + self.set_register(dst_reg, d); }, Instruction::LPM(ref dst_reg, ref inc_mode) => { let Z = self.get_register_pair(&30u8.into()); @@ -507,12 +637,16 @@ impl CPU { self.update_flags_zns_8(res); }, Instruction::STS16(ref addr, ref r) => { + let rampd = ram[chip_definitions::IOAdress::RAMPD as usize] as u32; + if rampd != 0 { panic!("This is unexpected (for now)"); } self.ram_write(ram, *addr, self.get_register(r))?; }, Instruction::STS8(ref addr, ref r) => { self.ram_write(ram, *addr as u16, self.get_register(r))?; }, Instruction::LDS16(ref r, ref addr) => { + let rampd = ram[chip_definitions::IOAdress::RAMPD as usize] as u32; + if rampd != 0 { panic!("This is unexpected (for now)"); } let v = self.ram_read(ram, *addr)?; self.set_register(r, v); }, diff --git a/src/decoder.rs b/src/decoder.rs index 996f8dd..a8db18f 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -547,13 +547,16 @@ pub fn decode(data: &[u8]) -> Result { // STS return '1010 1kkk rrrr kkkk'.replace(' ', '') // LDS return '1010 0kkk dddd kkkk'.replace(' ', '') + // 1010 0kkk dddd kkkk + // ST_ return "10q0 qq1r rrrr 0qqq".replace(' ', '') + // 10q0 qq1r rrrr 0qqq let r16 = (((v >> 4) & 0b1111) as u8).into(); let k = (((v >> 4) & 0b111_0000) | (v & 0b1111)) as u8; match v & 0b1111_1000_0000_0000 { 0b1011_1000_0000_0000 => return Ok(Instruction::OUT(A, r)), 0b1011_0000_0000_0000 => return Ok(Instruction::IN(r, A)), - 0b1010_1000_0000_0000 => return Ok(Instruction::STS8(k, r16)), - 0b1010_0000_0000_0000 => return Ok(Instruction::LDS8(r16, k)), + 0b1010_1000_0000_0001 => return Ok(Instruction::STS8(k + 0x40, r16)), // Disabled, can't be used + 0b1010_0000_0000_0001 => return Ok(Instruction::LDS8(r16, k + 0x40)), // Disabled, can't be used _ => {} } } diff --git a/src/main.rs b/src/main.rs index fd02617..aba3731 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,14 @@ use std::io; use std::io::{Read, Write}; use std::fs; +#[macro_use] +extern crate slog; +extern crate slog_term; +extern crate slog_async; + +use slog::Drain; + + mod cpu; mod regs; mod decoder; @@ -11,22 +19,32 @@ mod chip; mod chip_definitions; fn main() { - println!("Hello, world!"); - let mut rom = read_file("rom.bin").unwrap(); - let mut ram = [0u8; 8 * 1024 + 8 * 1024]; - let mut cpu = cpu::CPU::new(); + let decorator = slog_term::PlainDecorator::new(std::io::stdout()); + let drain = slog_term::CompactFormat::new(decorator).build().fuse(); + let drain = slog_async::Async::new(drain).build().fuse(); - for _ in 0..280000 { + let log = slog::Logger::root( + slog::LevelFilter::new(drain, slog::Level::Info).fuse(), + o!("version" => "0.1") + ); + info!(log, "AVREmu starting up"); + + let mut rom = read_file( + std::env::args().nth(1).unwrap_or("rom.bin".to_string())).unwrap(); + let mut ram = [0u8; 8 * 1024 + 8 * 1024]; + let mut cpu = cpu::CPU::new(log.clone()); + + loop { let r = cpu.step(&mut rom, &mut ram); - println!("{:?}", r); match r { - Err(cpu::CPUError::OutOfBoundsException) => break, - Err(cpu::CPUError::Exit) => break, - Err(cpu::CPUError::UnimplementedInstruction) => break, - _ => {} + Ok(_) => {} + Err(ref e) => { + warn!(log, "Error occured: {:?}", e); + break; + }, } } - println!("{}", cpu); + warn!(log, "{}", cpu); write_file("ram.dmp", &ram).unwrap(); }