Adds 'name' and 'operand' to Chip8Instruction

This commit is contained in:
2024-10-18 15:34:49 -04:00
parent 1eeb746ccf
commit be6e652982
3 changed files with 243 additions and 99 deletions
+143 -87
View File
@@ -1,6 +1,6 @@
use std::arch::x86_64::_mm_xor_pd;
use std::fmt::{Debug, Display, Formatter};
use std::ops::{BitAnd, Shr};
use std::ops::{BitAnd, Deref, Shr};
use std::time::Instant;
use log::debug;
use rand::{random, Rng};
@@ -21,7 +21,7 @@ kk or byte - An 8-bit value, the lowest 8 bits of the instruction
pub enum Chip8CpuInstructions {
/// 0nnn
/// Exit to System Call at nnn
SysAddr(i16),
SysAddr(u16),
/// 00E0
/// Clear the display.
CLS,
@@ -35,13 +35,13 @@ pub enum Chip8CpuInstructions {
/// Jump to location nnn.
///
/// The interpreter sets the program counter to nnn.
JpAddr(i16),
JpAddr(u16),
/// 2nnn
/// Call subroutine at nnn.
///
/// The interpreter increments the stack pointer, then puts the current PC on the top
/// of the stack. The PC is then set to nnn.
CallAddr(i16),
CallAddr(u16),
/// 0x3xkk
/// Skip next instruction if Vx = kk.
///
@@ -215,118 +215,175 @@ pub enum Chip8CpuInstructions {
XXXXERRORINSTRUCTION,
}
impl Display for Chip8CpuInstructions {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", format!("{}", match self {
Chip8CpuInstructions::SysAddr(x) => {
format!("SYS 0x{:04x}", x)
impl Chip8CpuInstructions {
pub fn name(&self) -> &str {
match self {
Chip8CpuInstructions::SysAddr(_) => {
"SYS"
}
Chip8CpuInstructions::CLS => {
String::from("CLS")
"CLS"
}
Chip8CpuInstructions::RET => {
String::from("RET")
"RET"
}
Chip8CpuInstructions::JpAddr(x) => {
format!("JP 0x{:04x}", x)
Chip8CpuInstructions::JpAddr(_) => {
"JPA"
}
Chip8CpuInstructions::CallAddr(x) => {
format!("SUB 0x{:04x}", x)
Chip8CpuInstructions::CallAddr(_) => {
"CALL"
}
Chip8CpuInstructions::SeVxByte(x, byte) => {
format!("SeVxByte 0x{:02x}, 0x{:02x}", x, byte)
Chip8CpuInstructions::SeVxByte(_, _) => {
"SeVxByte"
}
Chip8CpuInstructions::SneVxByte(x, byte) => {
format!("SneVxByte 0x{:02x}, 0x{:02x}", x, byte)
Chip8CpuInstructions::SneVxByte(_, _) => {
"SneVxByte"
}
Chip8CpuInstructions::SeVxVy(x, y) => {
format!("SeVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::SeVxVy(_, _) => {
"SeVeVy"
}
Chip8CpuInstructions::LdVxByte(x, byte) => {
format!("LdVxByte 0x{:02x}, 0x{:02x}", x, byte)
Chip8CpuInstructions::LdVxByte(_, _) => {
"LdVxByte"
}
Chip8CpuInstructions::AddVxByte(x, byte) => {
format!("AddVxByte 0x{:02x}, 0x{:02x}", x, byte)
Chip8CpuInstructions::AddVxByte(_, _) => {
"AddVxByte"
}
Chip8CpuInstructions::LdVxVy(x, y) => {
format!("LdVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::LdVxVy(_, _) => {
"LdVxVy"
}
Chip8CpuInstructions::OrVxVy(x, y) => {
format!("OrVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::OrVxVy(_, _) => {
"OrVxVy"
}
Chip8CpuInstructions::AndVxVy(x, y) => {
format!("AndVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::AndVxVy(_, _) => {
"AndVxVy"
}
Chip8CpuInstructions::XorVxVy(x, y) => {
format!("XorVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::XorVxVy(_, _) => {
"XorVxVy"
}
Chip8CpuInstructions::AddVxVy(x, y) => {
format!("AddVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::AddVxVy(_, _) => {
"AddVxVy"
}
Chip8CpuInstructions::SubVxVy(x, y) => {
format!("SubVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::SubVxVy(_, _) => {
"SubVxVy"
}
Chip8CpuInstructions::ShrVxVy(x, y) => {
format!("ShrVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::ShrVxVy(_, _) => {
"ShrVxVy"
}
Chip8CpuInstructions::SubnVxVy(x, y) => {
format!("SubnVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::SubnVxVy(_, _) => {
"SubnVxVy"
}
Chip8CpuInstructions::ShlVxVy(x, y) => {
format!("ShlVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::ShlVxVy(_, _) => {
"ShlVxVy"
}
Chip8CpuInstructions::SneVxVy(x, y) => {
format!("SneVxVy 0x{:02x}, 0x{:02x}", x, y)
Chip8CpuInstructions::SneVxVy(_, _) => {
"SneVxVy"
}
Chip8CpuInstructions::LdIAddr(addr) => {
format!("LdIAddr 0x{:04x}", addr)
Chip8CpuInstructions::LdIAddr(_) => {
"LdIAddr"
}
Chip8CpuInstructions::JpV0Addr(addr) => {
format!("JpV0Addr 0x{:04x}", addr)
Chip8CpuInstructions::JpV0Addr(_) => {
"JpV0Addr"
}
Chip8CpuInstructions::RndVxByte(x, byte) => {
format!("RndVxByte 0x:{:02x}, 0x{:02x}", x, byte)
Chip8CpuInstructions::RndVxByte(_, _) => {
"RndVxByte"
}
Chip8CpuInstructions::DrawVxVyNibble(x, y, nibble) => {
format!("DrawVxVyNibble 0x:{:02x}, 0x{:02x}, 0x{:02x}", x, y, nibble)
Chip8CpuInstructions::DrawVxVyNibble(_, _, _) => {
"DrawVxVyNibble"
}
Chip8CpuInstructions::SkpVx(x) => {
format!("SkpVx 0x{:02x}", x)
Chip8CpuInstructions::SkpVx(_) => {
"SkpVx"
}
Chip8CpuInstructions::SnkpVx(x) => {
format!("SnkpVx 0x{:02x}", x)
Chip8CpuInstructions::SnkpVx(_) => {
"SnkpVx"
}
Chip8CpuInstructions::LdVxDt(x) => {
format!("LdVxDt 0x{:02x}", x)
Chip8CpuInstructions::LdVxDt(_) => {
"LdVxDt"
}
Chip8CpuInstructions::LdVxK(x) => {
format!("LdVxK 0x{:02x}", x)
Chip8CpuInstructions::LdVxK(_) => {
"LdVxK"
}
Chip8CpuInstructions::LdDtVx(x) => {
format!("LdDtVx 0x{:02x}", x)
Chip8CpuInstructions::LdDtVx(_) => {
"LdDtVx"
}
Chip8CpuInstructions::LdStVx(x) => {
format!("LdStVx 0x{:02x}", x)
Chip8CpuInstructions::LdStVx(_) => {
"LdStVx"
}
Chip8CpuInstructions::AddIVx(x) => {
format!("AddIVx 0x{:02x}", x)
Chip8CpuInstructions::AddIVx(_) => {
"AddIVx"
}
Chip8CpuInstructions::LdFVx(x) => {
format!("LdFVx 0x{:02x}", x)
Chip8CpuInstructions::LdFVx(_) => {
"LdFVx"
}
Chip8CpuInstructions::LdBVx(x) => {
format!("LdBVx 0x{:02x}", x)
Chip8CpuInstructions::LdBVx(_) => {
"LdBVx"
}
Chip8CpuInstructions::LdIVx(x) => {
format!("LdIVx 0x{:02x}", x)
Chip8CpuInstructions::LdIVx(_) => {
"LdIVx"
}
Chip8CpuInstructions::LdVxI(i) => {
format!("LdVxI 0x{:02x}", i)
Chip8CpuInstructions::LdVxI(_) => {
"LdVxI"
}
XXXXERRORINSTRUCTION => {
String::from("INVALID INSTRUCTION")
"XX ERROR XX"
}
}))
}
}
pub fn operands(&self) -> String {
match self {
Chip8CpuInstructions::SysAddr(addr) |
Chip8CpuInstructions::JpV0Addr(addr) |
Chip8CpuInstructions::JpAddr(addr) |
Chip8CpuInstructions::LdIAddr(addr) |
Chip8CpuInstructions::CallAddr(addr) => {
format!("{addr:04x}")
}
Chip8CpuInstructions::SeVxByte(x, byte) |
Chip8CpuInstructions::SneVxByte(x, byte) |
Chip8CpuInstructions::LdVxByte(x, byte) |
Chip8CpuInstructions::RndVxByte(x, byte) |
Chip8CpuInstructions::AddVxByte(x, byte) => {
format!("{x:02x}, {byte:04x}")
}
Chip8CpuInstructions::SeVxVy(x,y) |
Chip8CpuInstructions::LdVxVy(x,y) |
Chip8CpuInstructions::OrVxVy(x,y) |
Chip8CpuInstructions::AndVxVy(x,y) |
Chip8CpuInstructions::XorVxVy(x,y) |
Chip8CpuInstructions::AddVxVy(x,y) |
Chip8CpuInstructions::SubVxVy(x,y) |
Chip8CpuInstructions::ShrVxVy(x,y) |
Chip8CpuInstructions::SubnVxVy(x,y) |
Chip8CpuInstructions::ShlVxVy(x,y) |
Chip8CpuInstructions::SneVxVy(x,y) => {
format!("{x:02x}, {y:02x}")
}
Chip8CpuInstructions::DrawVxVyNibble(x,y,nibble) => {
format!("{x:02x}, {y:02x}, {nibble:02x}")
}
Chip8CpuInstructions::LdDtVx(x) |
Chip8CpuInstructions::LdStVx(x) |
Chip8CpuInstructions::AddIVx(x) |
Chip8CpuInstructions::LdFVx(x) |
Chip8CpuInstructions::LdBVx(x) |
Chip8CpuInstructions::LdIVx(x) |
Chip8CpuInstructions::SkpVx(x) |
Chip8CpuInstructions::LdVxDt(x) |
Chip8CpuInstructions::LdVxK(x) |
Chip8CpuInstructions::LdVxI(x) |
Chip8CpuInstructions::SnkpVx(x) => {
format!("{x:02x}")
}
_ => {
"".parse().unwrap()
}
}
}
}
impl Display for Chip8CpuInstructions {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {}", self.name(), self.operands())
}
}
@@ -386,9 +443,9 @@ impl Chip8CpuInstructions {
match input {
0x00E0 => Chip8CpuInstructions::CLS,
0x00EE => Chip8CpuInstructions::RET,
0x0000..=0x0FFF => Chip8CpuInstructions::SysAddr(addr_param as i16),
0x1000..=0x1FFF => Chip8CpuInstructions::JpAddr(addr_param as i16),
0x2000..=0x2FFF => Chip8CpuInstructions::CallAddr(addr_param as i16),
0x0000..=0x0FFF => Chip8CpuInstructions::SysAddr(addr_param),
0x1000..=0x1FFF => Chip8CpuInstructions::JpAddr(addr_param),
0x2000..=0x2FFF => Chip8CpuInstructions::CallAddr(addr_param),
0x3000..=0x3FFF => Chip8CpuInstructions::SeVxByte(x_param, byte_param),
0x4000..=0x4FFF => Chip8CpuInstructions::SneVxByte(x_param, byte_param),
0x5000..=0x5FF0 if input & 0x01 == 0 => Chip8CpuInstructions::SeVxVy(x_param, y_param),
@@ -412,9 +469,9 @@ impl Chip8CpuInstructions {
0xC000..=0xCFFF => Chip8CpuInstructions::RndVxByte(x_param, byte_param),
0xD000..=0xDFFF => Chip8CpuInstructions::DrawVxVyNibble(x_param, y_param, nibble_param),
0xE09E..=0xEFA1 => match last_byte {
0x9E => Chip8CpuInstructions::SkpVx(ubln),
0xA1 => Chip8CpuInstructions::SnkpVx(ubln),
_ => XXXXERRORINSTRUCTION
0x9E => Chip8CpuInstructions::SkpVx(ubln),
0xA1 => Chip8CpuInstructions::SnkpVx(ubln),
_ => XXXXERRORINSTRUCTION
}
0xF007..=0xFF65 => match last_byte {
0x07 => Chip8CpuInstructions::LdVxDt(ubln),
@@ -432,7 +489,7 @@ impl Chip8CpuInstructions {
}
}
pub fn execute(&self, input: &mut Chip8Computer) -> Chip8Computer {
// print!("INSTRUCTION {}", self);
// print!("INSTRUCTION {}", self);
let start_time = Instant::now();
let start_pc = input.registers.peek_pc();
input.registers.poke_pc(start_pc + 2);
@@ -624,7 +681,7 @@ impl Chip8CpuInstructions {
// Set I = nnn.
//
// The value of register I is set to nnn.
// debug!("LdiAddr [0x{new_index:3x}]");
// debug!("LdiAddr [0x{new_index:3x}]");
input.registers.poke_i(*new_index);
}
// 0xBnnn Jump to nnn+V0
@@ -680,7 +737,6 @@ impl Chip8CpuInstructions {
};
input.registers.poke(0xf, target);
}
Chip8CpuInstructions::SkpVx(x) => {
// Ex9E - SKP Vx
@@ -811,7 +867,7 @@ impl Chip8CpuInstructions {
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {}
};
let cycle_time = Instant::now().duration_since(start_time).as_nanos();
// println!("\t\tTook {cycle_time}ms");
// println!("\t\tTook {cycle_time}ms");
input.to_owned()
}
}