Add logging and random stuff

This commit is contained in:
Kevin Hamacher 2018-02-13 00:42:42 +01:00
parent 7b66f79278
commit 71fecb51a9
5 changed files with 195 additions and 29 deletions

View File

@ -4,3 +4,6 @@ version = "0.1.0"
authors = ["Kevin Hamacher <kevin.hamacher@ruhr-uni-bochum.de>"] authors = ["Kevin Hamacher <kevin.hamacher@ruhr-uni-bochum.de>"]
[dependencies] [dependencies]
slog = "2"
slog-term = "2"
slog-async = "2"

View File

@ -55,6 +55,14 @@ pub enum IOAdress {
SPL = 0x03D, SPL = 0x03D,
SPH = 0x03E, SPH = 0x03E,
SREG = 0x03F, SREG = 0x03F,
CLK_CTRL = 0x040,
CLK_PSCTRL = 0x041,
CLK_LOCK = 0x042,
CLK_RTCCTRL = 0x043,
CLK_USBCTRL = 0x044,
OSC_CTRL = 0x050,
OSC_STATUS = 0x051, OSC_STATUS = 0x051,
USARTC0_DATA = 0x8A0, USARTC0_DATA = 0x8A0,
USARTC0_STATUS = 0x8A1, USARTC0_STATUS = 0x8A1,

View File

@ -8,6 +8,9 @@ use chip_definitions;
use std::fmt; use std::fmt;
use slog;
#[derive(Debug)] #[derive(Debug)]
pub enum CPUError { pub enum CPUError {
UnimplementedInstruction, UnimplementedInstruction,
@ -28,6 +31,8 @@ pub struct CPU {
// The same is true for the status register // The same is true for the status register
pub sreg: u8, pub sreg: u8,
logger: slog::Logger,
} }
@ -45,7 +50,7 @@ impl fmt::Display for CPU {
} }
write!(f, "\n")?; write!(f, "\n")?;
for i in 0..32 { 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{ if (i + 1) % 10 == 0{
write!(f, "\n")?; write!(f, "\n")?;
} }
@ -55,11 +60,12 @@ impl fmt::Display for CPU {
} }
impl CPU { impl CPU {
pub fn new() -> Self { pub fn new(logger: slog::Logger) -> Self {
CPU { 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
} }
} }
@ -86,7 +92,7 @@ impl CPU {
} }
fn set_clear_flag(&mut self, flag: StatusFlag, test: bool) { fn set_clear_flag(&mut self, flag: StatusFlag, test: bool) {
print!("[{}->{}] ", flag, test); // print!("[{}->{}] ", flag, test);
if test { if test {
self.set_flag(flag); self.set_flag(flag);
} else { } else {
@ -112,13 +118,63 @@ impl CPU {
} }
fn ram_write(&self, ram: &mut [u8], addr: u16, val: u8) -> Result<(), CPUError> { 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() { if addr as usize >= ram.len() {
Err(CPUError::OutOfBoundsException) Err(CPUError::OutOfBoundsException)
} else { } else {
// TODO: Hooks if addr < 0x2000 {
if addr == chip_definitions::IOAdress::USARTC0_DATA as _ { if addr != chip_definitions::IOAdress::SPH as u16 && addr != chip_definitions::IOAdress::SPL as u16 {
print!("USART_OUT:{: <3} ({}) ", val, (val as char).escape_debug()); // 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; ram[addr as usize] = val;
Ok(()) Ok(())
@ -126,14 +182,18 @@ impl CPU {
} }
fn ram_read(&self, ram: &[u8], addr: u16) -> Result<u8, CPUError> { fn ram_read(&self, ram: &[u8], addr: u16) -> Result<u8, CPUError> {
print!("[RAMR:{:04X}] ", addr); // print!("[RAMR:{:04X}] ", addr);
if addr as usize >= ram.len() { if addr as usize >= ram.len() {
Err(CPUError::OutOfBoundsException) Err(CPUError::OutOfBoundsException)
} else { } else {
// TODO: Hooks // TODO: Hooks
if addr == chip_definitions::IOAdress::USARTC0_DATA as _ { 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 _ { } else if addr == chip_definitions::IOAdress::USARTC0_STATUS as _ {
// info!(self.logger, "Read from USART status");
if self.pc == 0x5AC { if self.pc == 0x5AC {
// USART data check -> Yes, there is indeed data available! // USART data check -> Yes, there is indeed data available!
return Ok(0x80); return Ok(0x80);
@ -143,6 +203,52 @@ impl CPU {
} else if addr == chip_definitions::IOAdress::OSC_STATUS as _ { } else if addr == chip_definitions::IOAdress::OSC_STATUS as _ {
// HACK: Osci is set right.. // HACK: Osci is set right..
return Ok(0x02); 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]) Ok(ram[addr as usize])
} }
@ -248,7 +354,7 @@ impl CPU {
Ok(v) => v, Ok(v) => v,
Err(e) => return Err(CPUError::DecodingError(e)), 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; self.pc += (ins.size() / 2) as u32;
@ -266,7 +372,13 @@ impl CPU {
}, },
Instruction::LDI(ref r, v) => self.set_register(r, v), Instruction::LDI(ref r, v) => self.set_register(r, v),
Instruction::SER(ref r) => self.set_register(r, 0xFF), 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::CLR_FLAG(v) => self.clear_flag(v),
Instruction::SET_FLAG(v) => self.set_flag(v), Instruction::SET_FLAG(v) => self.set_flag(v),
Instruction::CPI(ref r, v) => { Instruction::CPI(ref r, v) => {
@ -313,6 +425,13 @@ impl CPU {
}, },
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);
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 { let addr = match *inc_mode {
IncrementMode::None => base, IncrementMode::None => base,
IncrementMode::PreDecrement => { IncrementMode::PreDecrement => {
@ -329,18 +448,29 @@ impl CPU {
self.set_register(dst_reg, v); self.set_register(dst_reg, v);
}, },
Instruction::ELPM(ref dst_reg, ref inc_mode) => { Instruction::ELPM(ref dst_reg, ref inc_mode) => {
// TODO: RAMPZ
let Z = self.get_register_pair(&30u8.into()); let Zb = self.get_register_pair(&30u8.into());
let d = rom[Z as usize]; // TODO: Only use required bits, other read as zero (according to datasheet)
self.set_register(dst_reg, d); let Z =
Zb as usize |
(ram[chip_definitions::IOAdress::RAMPZ as usize] as usize) << 16
;
match *inc_mode { match *inc_mode {
IncrementMode::PostIncrement => { 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 // 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) => { Instruction::LPM(ref dst_reg, ref inc_mode) => {
let Z = self.get_register_pair(&30u8.into()); let Z = self.get_register_pair(&30u8.into());
@ -507,12 +637,16 @@ 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 = 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))?; self.ram_write(ram, *addr, self.get_register(r))?;
}, },
Instruction::STS8(ref addr, ref r) => { Instruction::STS8(ref addr, ref r) => {
self.ram_write(ram, *addr as u16, self.get_register(r))?; self.ram_write(ram, *addr as u16, self.get_register(r))?;
}, },
Instruction::LDS16(ref r, ref addr) => { 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)?; let v = self.ram_read(ram, *addr)?;
self.set_register(r, v); self.set_register(r, v);
}, },

View File

@ -547,13 +547,16 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
// STS return '1010 1kkk rrrr kkkk'.replace(' ', '') // STS return '1010 1kkk rrrr kkkk'.replace(' ', '')
// LDS return '1010 0kkk dddd 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 r16 = (((v >> 4) & 0b1111) as u8).into();
let k = (((v >> 4) & 0b111_0000) | (v & 0b1111)) as u8; let k = (((v >> 4) & 0b111_0000) | (v & 0b1111)) as u8;
match v & 0b1111_1000_0000_0000 { match v & 0b1111_1000_0000_0000 {
0b1011_1000_0000_0000 => return Ok(Instruction::OUT(A, r)), 0b1011_1000_0000_0000 => return Ok(Instruction::OUT(A, r)),
0b1011_0000_0000_0000 => return Ok(Instruction::IN(r, A)), 0b1011_0000_0000_0000 => return Ok(Instruction::IN(r, A)),
0b1010_1000_0000_0000 => return Ok(Instruction::STS8(k, r16)), 0b1010_1000_0000_0001 => return Ok(Instruction::STS8(k + 0x40, r16)), // Disabled, can't be used
0b1010_0000_0000_0000 => return Ok(Instruction::LDS8(r16, k)), 0b1010_0000_0000_0001 => return Ok(Instruction::LDS8(r16, k + 0x40)), // Disabled, can't be used
_ => {} _ => {}
} }
} }

View File

@ -4,6 +4,14 @@ use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::fs; use std::fs;
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;
use slog::Drain;
mod cpu; mod cpu;
mod regs; mod regs;
mod decoder; mod decoder;
@ -11,22 +19,32 @@ mod chip;
mod chip_definitions; mod chip_definitions;
fn main() { fn main() {
println!("Hello, world!"); let decorator = slog_term::PlainDecorator::new(std::io::stdout());
let mut rom = read_file("rom.bin").unwrap(); let drain = slog_term::CompactFormat::new(decorator).build().fuse();
let mut ram = [0u8; 8 * 1024 + 8 * 1024]; let drain = slog_async::Async::new(drain).build().fuse();
let mut cpu = cpu::CPU::new();
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); let r = cpu.step(&mut rom, &mut ram);
println!("{:?}", r);
match r { match r {
Err(cpu::CPUError::OutOfBoundsException) => break, Ok(_) => {}
Err(cpu::CPUError::Exit) => break, Err(ref e) => {
Err(cpu::CPUError::UnimplementedInstruction) => break, warn!(log, "Error occured: {:?}", e);
_ => {} break;
},
} }
} }
println!("{}", cpu); warn!(log, "{}", cpu);
write_file("ram.dmp", &ram).unwrap(); write_file("ram.dmp", &ram).unwrap();
} }