[cpu] Add all remaining instruction decodes

This commit is contained in:
2024-03-05 19:24:45 +05:30
parent 297e72ab86
commit 90a83e131a
2 changed files with 150 additions and 9 deletions

View File

@@ -36,7 +36,7 @@ impl Device {
stack: Vec::with_capacity(16),
timer,
super_chip8_mode: false,
device_keyboard
device_keyboard,
}
}
}
@@ -140,12 +140,26 @@ impl Device {
self.registers.pc += 2;
}
}
Instruction::JumpWithOffset(_, _) => {}
Instruction::JumpWithOffset(x, num) => {
let regnum = if self.super_chip8_mode { x } else { 0 };
let new_pc = self.registers.v[regnum] as u16 + num ;
self.registers.pc = new_pc;
}
Instruction::RandomAnd(dest, n) => {
self.registers.v[dest] = random::<u8>() & n;
}
Instruction::SkipIfKeyPressed(_) => {}
Instruction::SkipIfKeyNotPressed(_) => {}
Instruction::SkipIfKeyPressed(x) => {
let key_press_expected_for = self.registers.v[x];
if self.device_keyboard.query_key_down(key_press_expected_for) {
self.registers.pc += 2;
}
}
Instruction::SkipIfKeyNotPressed(x) => {
let key_press_expected_for = self.registers.v[x];
if !self.device_keyboard.query_key_down(key_press_expected_for) {
self.registers.pc += 2;
}
}
Instruction::Set(x, y) => {
self.registers.v[x] = self.registers.v[y];
}
@@ -170,14 +184,31 @@ impl Device {
self.registers.v[x] = wrapped_subtraction_result;
self.set_flag_register(is_overflow);
}
Instruction::RShift(_, _) => {}
Instruction::RSub(x, y) => {
let left = self.registers.v[y];
let (wrapped_subtraction_result, is_overflow) = left.overflowing_sub(self.registers.v[x]);
self.registers.v[x] = wrapped_subtraction_result;
self.set_flag_register(is_overflow);
}
Instruction::LShift(_, _) => {}
Instruction::RShift(x, y) => {
if(self.super_chip8_mode){
self.registers.v[x] = self.registers.v[y];
}
let (shift_res,did_overflow) = self.registers.v[x].overflowing_shr(1);
self.registers.v[x] = shift_res;
self.set_flag_register(did_overflow);
}
Instruction::LShift(x, y) => {
if(self.super_chip8_mode){
self.registers.v[x] = self.registers.v[y];
}
let (shift_res,did_overflow) = self.registers.v[x].overflowing_shl(1);
self.registers.v[x] = shift_res;
self.set_flag_register(did_overflow);
},
_=>{
todo!()
}
};
}
///

View File

@@ -37,6 +37,24 @@ pub enum Instruction {
SkipIfKeyPressed(usize),
/// EXA1 - Check if key is not pressed
SkipIfKeyNotPressed(usize),
/// FX07 - Get delay timer, put into register
FetchDelayTimer(usize),
/// FX15 - set delay timer as register
SetDelayTimer(usize),
/// FX18 - Set sound timer as register
SetSoundTimer(usize),
/// FX1E - Add register to index
AddToIndex(usize),
/// FX0A - Wait for key as indicated by register
GetKey(usize),
/// FX29 - Set index to register-requested font char address in memory
SetIndexToFontCharacter(usize),
/// FX33 - Convert register val to bcd and store at location pointed by index
DoBCDConversion(usize),
/// FX55 - Store all registers from v0 to vx to memory location pointed to by index
StoreRegistersToMemory(usize),
/// FX65 - Load all registers from v0 to vx to memory location pointed to by index
LoadRegistersFromMemory(usize),
// ALU operations going ahead
/// 8XY0 - x=y
@@ -139,6 +157,43 @@ impl Instruction {
let x = (instruction & 0xf00) >> 8;
Instruction::SkipIfKeyNotPressed(x as usize)
}
0xF if (instruction & 0xff) == 0x07 =>{
let x = (instruction & 0xf00) >> 8;
Instruction::FetchDelayTimer(x as usize)
}
0xF if (instruction & 0xff) == 0x15 =>{
let x = (instruction & 0xf00) >> 8;
Instruction::SetDelayTimer(x as usize)
}
0xF if (instruction & 0xff) == 0x18 =>{
let x = (instruction & 0xf00) >> 8;
Instruction::SetSoundTimer(x as usize)
}
0xF if (instruction & 0xff) == 0x1E =>{
let x = (instruction & 0xf00) >> 8;
Instruction::AddToIndex(x as usize)
}
0xF if (instruction & 0xff) == 0x0A =>{
let x = (instruction & 0xf00) >> 8;
Instruction::GetKey(x as usize)
}
//TODO add tests from here
0xF if (instruction & 0xff) == 0x29 =>{
let x = (instruction & 0xf00) >> 8;
Instruction::SetIndexToFontCharacter(x as usize)
}
0xF if (instruction & 0xff) == 0x33 =>{
let x = (instruction & 0xf00) >> 8;
Instruction::DoBCDConversion(x as usize)
}
0xF if (instruction & 0xff) == 0x55 =>{
let x = (instruction & 0xf00) >> 8;
Instruction::StoreRegistersToMemory(x as usize)
}
0xF if (instruction & 0xff) == 0x65 =>{
let x = (instruction & 0xf00) >> 8;
Instruction::LoadRegistersFromMemory(x as usize)
}
_ => {
todo!("Unimplemented instruction")
}
@@ -389,4 +444,59 @@ mod tests {
assert_eq!(ins, SkipIfKeyNotPressed(0xb))
}
#[test]
fn test_fetch_delay_timer(){
let instruction_bytes = 0xfa07_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, FetchDelayTimer(0xa))
}
#[test]
fn test_set_delay_timer(){
let instruction_bytes = 0xfb15_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, SetDelayTimer(0xb))
}
#[test]
fn test_set_sound_timer(){
let instruction_bytes = 0xfc18_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, SetSoundTimer(0xc))
}
#[test]
fn test_add_to_index(){
let instruction_bytes = 0xfb1e_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, AddToIndex(0xb))
}
#[test]
fn test_get_key(){
let instruction_bytes = 0xf50a_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, GetKey(0x5))
}
#[test]
fn test_set_index_to_font_char(){
let instruction_bytes = 0xfb29_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, SetIndexToFontCharacter(0xb))
}
#[test]
fn test_do_bcd_conversion(){
let instruction_bytes = 0xfd33_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, DoBCDConversion(0xd))
}
#[test]
fn test_store_regs_to_mem(){
let instruction_bytes = 0xfb55_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, StoreRegistersToMemory(0xb))
}
#[test]
fn test_load_regs_to_mem(){
let instruction_bytes = 0xf965_u16.to_be_bytes();
let ins = Instruction::decode_instruction(&instruction_bytes);
assert_eq!(ins, LoadRegistersFromMemory(0b1001))
}
}