This commit is contained in:
Kevin Hamacher 2018-02-17 00:37:15 +01:00
parent d96f4b9ad5
commit 107b901c27
5 changed files with 54 additions and 57 deletions

View File

@ -14,7 +14,7 @@ impl Chip {
pub fn new(log: slog::Logger, rom: Box<[u8]>) -> Chip { pub fn new(log: slog::Logger, rom: Box<[u8]>) -> Chip {
Self { Self {
log: log.clone(), log: log.clone(),
cpu: CPU::new(log.clone()), cpu: CPU::new(log),
rom: rom, rom: rom,
ram: Box::new([0u8; 0x4000]), ram: Box::new([0u8; 0x4000]),
} }

View File

@ -74,8 +74,8 @@ impl CPU {
} }
pub fn get_sp(&self, mem: &[u8]) -> u16 { pub fn get_sp(&self, mem: &[u8]) -> u16 {
mem[chip_definitions::IOAdress::SPL as usize] as u16 u16::from(mem[chip_definitions::IOAdress::SPL as usize])
| ((mem[chip_definitions::IOAdress::SPH as usize] as u16) << 8) | (u16::from(mem[chip_definitions::IOAdress::SPH as usize]) << 8)
} }
fn set_sp(&self, mem: &mut [u8], val: u16) { fn set_sp(&self, mem: &mut [u8], val: u16) {
@ -105,7 +105,7 @@ impl CPU {
} }
fn get_register_pair(&self, r: &GeneralPurposeRegisterPair) -> u16 { fn get_register_pair(&self, r: &GeneralPurposeRegisterPair) -> u16 {
((self.registers[r.high()] as u16) << 8) | self.registers[r.low()] as u16 (u16::from(self.registers[r.high()]) << 8) | u16::from(self.registers[r.low()])
} }
fn set_register_pair(&mut self, r: &GeneralPurposeRegisterPair, v: u16) { fn set_register_pair(&mut self, r: &GeneralPurposeRegisterPair, v: u16) {
@ -268,14 +268,14 @@ impl CPU {
} }
fn push(&mut self, ram: &mut [u8], val: u8) -> Result<(), CPUError> { fn push(&mut self, ram: &mut [u8], val: u8) -> Result<(), CPUError> {
let sp = self.get_sp(&ram); let sp = self.get_sp(ram);
self.ram_write(ram, sp, val)?; self.ram_write(ram, sp, val)?;
self.set_sp(ram, sp.wrapping_sub(1)); self.set_sp(ram, sp.wrapping_sub(1));
Ok(()) Ok(())
} }
fn pop(&mut self, ram: &mut [u8]) -> Result<u8, CPUError> { fn pop(&mut self, ram: &mut [u8]) -> Result<u8, CPUError> {
let sp = self.get_sp(&ram); let sp = self.get_sp(ram);
self.set_sp(ram, sp.wrapping_add(1)); self.set_sp(ram, sp.wrapping_add(1));
self.ram_read(ram, sp.wrapping_add(1)) self.ram_read(ram, sp.wrapping_add(1))
} }
@ -402,7 +402,7 @@ impl CPU {
Instruction::SER(ref r) => self.set_register(r, 0xFF), Instruction::SER(ref r) => self.set_register(r, 0xFF),
Instruction::RJMP(v) => { Instruction::RJMP(v) => {
self.pc = self.pc.wrapping_add(v as _); self.pc = self.pc.wrapping_add(v as _);
if v == -1 && self.test_flag(StatusFlag::GlobalInterruptEnable) == false { if v == -1 && !self.test_flag(StatusFlag::GlobalInterruptEnable) {
info!(self.logger, "HALTED "); info!(self.logger, "HALTED ");
return Err(CPUError::Exit); return Err(CPUError::Exit);
} }
@ -447,7 +447,7 @@ impl CPU {
self.set_register_pair(ptr, base.wrapping_add(1)); self.set_register_pair(ptr, base.wrapping_add(1));
base base
} }
IncrementMode::ConstantOffset(o) => base.wrapping_add(o as _), IncrementMode::ConstantOffset(o) => base.wrapping_add(u16::from(o)),
}; };
self.ram_write(ram, addr, self.get_register(src_reg))?; self.ram_write(ram, addr, self.get_register(src_reg))?;
} }
@ -470,7 +470,7 @@ impl CPU {
self.set_register_pair(ptr, base.wrapping_add(1)); self.set_register_pair(ptr, base.wrapping_add(1));
base base
} }
IncrementMode::ConstantOffset(o) => base.wrapping_add(o as _), IncrementMode::ConstantOffset(o) => base.wrapping_add(u16::from(o)),
}; };
let v = self.ram_read(ram, addr)?; let v = self.ram_read(ram, addr)?;
self.set_register(dst_reg, v); self.set_register(dst_reg, v);
@ -537,12 +537,12 @@ impl CPU {
self.push(ram, ((ret_to >> 16) & 0xFF) as u8)?; self.push(ram, ((ret_to >> 16) & 0xFF) as u8)?;
self.push(ram, ((ret_to >> 8) & 0xFF) as u8)?; self.push(ram, ((ret_to >> 8) & 0xFF) as u8)?;
self.push(ram, (ret_to & 0xFF) as u8)?; self.push(ram, (ret_to & 0xFF) as u8)?;
self.pc = (self.pc as i32 + *addr as i32) as u32; self.pc = ((self.pc as i32) + i32::from(*addr)) as u32;
} }
Instruction::RET => { Instruction::RET => {
let mut ret_to = self.pop(ram)? as u32; let mut ret_to = u32::from(self.pop(ram)?);
ret_to += (self.pop(ram)? as u32) << 8; ret_to += u32::from(self.pop(ram)?) << 8;
ret_to += (self.pop(ram)? as u32) << 16; ret_to += u32::from(self.pop(ram)?) << 16;
self.pc = ret_to as _; self.pc = ret_to as _;
} }
Instruction::POP(ref reg) => { Instruction::POP(ref reg) => {
@ -675,17 +675,17 @@ 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; let rampd = u32::from(ram[chip_definitions::IOAdress::RAMPD as usize]);
if rampd != 0 { if rampd != 0 {
panic!("This is unexpected (for now)"); 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, u16::from(*addr), 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; let rampd = u32::from(ram[chip_definitions::IOAdress::RAMPD as usize]);
if rampd != 0 { if rampd != 0 {
panic!("This is unexpected (for now)"); panic!("This is unexpected (for now)");
} }
@ -693,7 +693,7 @@ impl CPU {
self.set_register(r, v); self.set_register(r, v);
} }
Instruction::LDS8(ref r, ref addr) => { Instruction::LDS8(ref r, ref addr) => {
let v = self.ram_read(ram, *addr as u16)?; let v = self.ram_read(ram, u16::from(*addr))?;
self.set_register(r, v); self.set_register(r, v);
} }
Instruction::LSL(ref r) => { Instruction::LSL(ref r) => {
@ -772,8 +772,8 @@ impl CPU {
} }
Instruction::MUL(ref r, ref d) => { Instruction::MUL(ref r, ref d) => {
// R1:R0 ← Rd × Rr(unsigned ← unsigned × unsigned) // R1:R0 ← Rd × Rr(unsigned ← unsigned × unsigned)
let r = self.get_register(r) as u16; let r = u16::from(self.get_register(r));
let d = self.get_register(d) as u16; let d = u16::from(self.get_register(d));
let v = r * d; let v = r * d;
self.registers[0] = (v & 0xFF) as u8; self.registers[0] = (v & 0xFF) as u8;
self.registers[1] = ((v >> 8) & 0xFF) as u8; self.registers[1] = ((v >> 8) & 0xFF) as u8;

View File

@ -206,7 +206,7 @@ impl Instruction {
// LDS32 STS32 // LDS32 STS32
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
match *self { match *self {
Instruction::JMP(_) | Instruction::CALL(_) => 4, Instruction::JMP(_) | Instruction::CALL(_) |
Instruction::STS16(_, _) | Instruction::LDS16(_, _) => 4, Instruction::STS16(_, _) | Instruction::LDS16(_, _) => 4,
_ => 2, _ => 2,
} }
@ -223,11 +223,11 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
return Err(DecodingError::TruncatedInstruction); return Err(DecodingError::TruncatedInstruction);
} }
// Try to match 2b instructions without any parameters first. // Try to match 2b instructions without any parameters first.
let v: u16 = ((data[1] as u16) << 8) | (data[0] as u16); let v: u16 = (u16::from(data[1]) << 8) | u16::from(data[0]);
// Load second u16 as well if possible // Load second u16 as well if possible
let v2: Option<u16> = if data.len() >= 4 { let v2: Option<u16> = if data.len() >= 4 {
Some(((data[3] as u16) << 8) | (data[2] as u16)) Some((u16::from(data[3]) << 8) | u16::from(data[2]))
} else { } else {
None None
}; };
@ -277,21 +277,18 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
0000_0011_1: <class 'FMULS'> <class 'FMULSU'> 0000_0011_1: <class 'FMULS'> <class 'FMULSU'>
0000_0011_0: <class 'FMUL'> <class 'MULSU'> 0000_0011_0: <class 'FMUL'> <class 'MULSU'>
*/ */
match v & 0b1111_1111_0000_0000 { if v & 0b1111_1111_0000_0000 == 0b0000_0011_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())), 0b0000_1000 => return Ok(Instruction::FMUL((d + 16).into(), (r + 16).into())),
0b0000_1000 => return Ok(Instruction::FMUL((d + 16).into(), (r + 16).into())), 0b1000_0000 => return Ok(Instruction::FMULS((d + 16).into(), (r + 16).into())),
0b1000_0000 => return Ok(Instruction::FMULS((d + 16).into(), (r + 16).into())), 0b1000_1000 => return Ok(Instruction::FMULSU((d + 16).into(), (r + 16).into())),
0b1000_1000 => return Ok(Instruction::FMULSU((d + 16).into(), (r + 16).into())), _ => unreachable!(),
_ => unreachable!(),
}
} }
_ => {}
} }
/* /*
@ -309,16 +306,16 @@ 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 = ((v & 0b1111_1000) >> 3) as u16; let A = u16::from((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 => {
return Ok(Instruction::ADIW(((d & 0b11) * 2 + 24).into(), K as u16)) return Ok(Instruction::ADIW(((d & 0b11) * 2 + 24).into(), u16::from(K)))
} }
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(((d & 0b11) * 2 + 24).into(), K as u16)) return Ok(Instruction::SBIW(((d & 0b11) * 2 + 24).into(), u16::from(K)))
} }
0b1110_1111_0000_0000 => if r == 0b1111 { 0b1110_1111_0000_0000 => if r == 0b1111 {
return Ok(Instruction::SER((d + 16).into())); return Ok(Instruction::SER((d + 16).into()));
@ -491,7 +488,7 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
let d = (((v >> 4) & 0b1_1111) as u8).into(); let d = (((v >> 4) & 0b1_1111) as u8).into();
let b = (v & 0b111) as u8; let b = (v & 0b111) as u8;
if (v & 0b1000) == 0 { if (v & 0b1000) == 0 {
if ((v >> 9) & 1) == 9 { if ((v >> 9) & 1) == 1 {
return Ok(Instruction::BLD(d, b)); return Ok(Instruction::BLD(d, b));
} else { } else {
return Ok(Instruction::BST(d, b)); return Ok(Instruction::BST(d, b));
@ -528,7 +525,7 @@ pub fn decode(data: &[u8]) -> Result<Instruction, DecodingError> {
match v2 { match v2 {
None => return Err(DecodingError::TruncatedInstruction), None => return Err(DecodingError::TruncatedInstruction),
Some(kl) => { Some(kl) => {
let k = (((v & 0b1111_0000) as u32) << 12) | (kl as u32); let k = (u32::from(v & 0b1111_0000) << 12) | (u32::from(kl));
if v & 0b10 == 0 { if v & 0b10 == 0 {
return Ok(Instruction::JMP(k)); return Ok(Instruction::JMP(k));
} else { } else {

View File

@ -26,7 +26,7 @@ pub enum GDBPacketError {
} }
impl GDBPacket { impl GDBPacket {
pub fn from_packet(data: &Vec<u8>) -> Result<GDBPacket, GDBPacketError> { pub fn from_packet(data: &[u8]) -> Result<GDBPacket, GDBPacketError> {
let mut is_escaped = false; let mut is_escaped = false;
let mut in_checksum = false; let mut in_checksum = false;
let mut decoded_data = Vec::new(); let mut decoded_data = Vec::new();
@ -77,7 +77,7 @@ impl GDBPacket {
fn escaped_data(&self) -> Vec<u8> { fn escaped_data(&self) -> Vec<u8> {
let mut r = Vec::new(); let mut r = Vec::new();
for e in self.raw_data.iter() { for e in &self.raw_data {
match *e { match *e {
b'$' | b'#' | b'}' | b'*' => { b'$' | b'#' | b'}' | b'*' => {
r.push(b'}'); r.push(b'}');
@ -101,8 +101,8 @@ impl GDBPacket {
fn split_definitions(pkg: &str) -> Vec<(String, String)> { 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.nth(0).unwrap().to_string();
res.push((first, v.collect::<String>())); res.push((first, v.collect::<String>()));
} }
@ -139,7 +139,7 @@ impl<'a> GDBStub<'a> {
panic!("Connection closed?") panic!("Connection closed?")
} }
// Wait for beginning of pkg. // Wait for beginning of pkg.
if buf.len() == 0 && s[0] != b'$' { if buf.is_empty() && s[0] != b'$' {
continue; continue;
} }
buf.push(s[0]); buf.push(s[0]);
@ -169,7 +169,7 @@ impl<'a> GDBStub<'a> {
// Split it into command and values. // Split it into command and values.
if response.chars().nth(0).ok_or(())? == 'v' { if response.chars().nth(0).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[0].to_string(),
word_payload[1..].join(";").to_string(), word_payload[1..].join(";").to_string(),
@ -202,7 +202,7 @@ impl<'a> GDBStub<'a> {
let response: Cow<str>; let response: Cow<str>;
info!(self.log, "<- {} {}", cmd, payload); info!(self.log, "<- {} {}", cmd, payload);
// Send ACK. // Send ACK.
conn.write_all(&"+".as_bytes()).unwrap(); conn.write_all(b"+").unwrap();
match &*cmd { match &*cmd {
"q" => { "q" => {
let query_data = split_definitions(&payload); let query_data = split_definitions(&payload);
@ -282,7 +282,7 @@ impl<'a> GDBStub<'a> {
} }
"m" => { "m" => {
// Read memory. // Read memory.
let parts = payload.split(",").collect::<Vec<_>>(); let parts = payload.split(',').collect::<Vec<_>>();
let mem_addr = usize::from_str_radix(parts[0], 16).unwrap_or(0); let mem_addr = usize::from_str_radix(parts[0], 16).unwrap_or(0);
let len = usize::from_str_radix(parts[1], 16).unwrap_or(0); let len = usize::from_str_radix(parts[1], 16).unwrap_or(0);
let mut data = Vec::new(); let mut data = Vec::new();
@ -294,7 +294,7 @@ impl<'a> GDBStub<'a> {
let addr_i = addr & 0xFFFFF; let addr_i = addr & 0xFFFFF;
if addr_i >= self.chip.ram.len() { if addr_i >= self.chip.ram.len() {
// Partial read case. // Partial read case.
if data.len() == 0 { if data.is_empty() {
err = true; err = true;
} }
break; break;
@ -304,7 +304,7 @@ impl<'a> GDBStub<'a> {
// ROM // ROM
if addr >= self.chip.rom.len() { if addr >= self.chip.rom.len() {
// Partial read case. // Partial read case.
if data.len() == 0 { if data.is_empty() {
err = true; err = true;
} }
break; break;
@ -320,8 +320,8 @@ impl<'a> GDBStub<'a> {
} }
"M" => { "M" => {
// Write memory. // Write memory.
let addrlen_content = payload.split(":").collect::<Vec<_>>(); let addrlen_content = payload.split(':').collect::<Vec<_>>();
let parts = addrlen_content[0].split(",").collect::<Vec<_>>(); let parts = addrlen_content[0].split(',').collect::<Vec<_>>();
let value = addrlen_content[1]; let value = addrlen_content[1];
let mem_addr = usize::from_str_radix(parts[0], 16).unwrap(); let mem_addr = usize::from_str_radix(parts[0], 16).unwrap();
let len = usize::from_str_radix(parts[1], 16).unwrap(); let len = usize::from_str_radix(parts[1], 16).unwrap();
@ -355,9 +355,9 @@ impl<'a> GDBStub<'a> {
} }
"z" | "Z" => { "z" | "Z" => {
// insert(Z)/remove(z) breakpoint. // insert(Z)/remove(z) breakpoint.
let values = payload.split(",").collect::<Vec<_>>(); let values = payload.split(',').collect::<Vec<_>>();
let bp_type = values[0]; let bp_type = values[0];
let bp_addr = u32::from_str_radix(&values[1], 16).unwrap(); let bp_addr = u32::from_str_radix(values[1], 16).unwrap();
let _bp_length = values[2]; let _bp_length = values[2];
if bp_type == "0" || bp_type == "1" && bp_addr & 1 == 0 { if bp_type == "0" || bp_type == "1" && bp_addr & 1 == 0 {
let cpu_addr = bp_addr >> 1; let cpu_addr = bp_addr >> 1;

View File

@ -29,7 +29,7 @@ fn main() {
); );
info!(log, "AVREmu starting up"); info!(log, "AVREmu starting up");
let rom = read_file(std::env::args().nth(1).unwrap_or("rom.bin".to_string())).unwrap(); let rom = read_file(std::env::args().nth(1).unwrap_or_else(|| "rom.bin".to_string())).unwrap();
let mut chip = chip::Chip::new(log.clone(), rom); let mut chip = chip::Chip::new(log.clone(), rom);
@ -49,6 +49,6 @@ pub fn read_file<P: AsRef<Path>>(rom_path: P) -> Result<Box<[u8]>, io::Error> {
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 = try!(fs::File::create(path));
try!(file.write_all(&data)); try!(file.write_all(data));
Ok(()) Ok(())
} }