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>"]
[dependencies]
slog = "2"
slog-term = "2"
slog-async = "2"

View File

@ -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,

View File

@ -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<u8, CPUError> {
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);
},

View File

@ -547,13 +547,16 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
// 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
_ => {}
}
}

View File

@ -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();
}