[cpu] Add all remaining instruction decodes
This commit is contained in:
@@ -36,7 +36,7 @@ impl Device {
|
|||||||
stack: Vec::with_capacity(16),
|
stack: Vec::with_capacity(16),
|
||||||
timer,
|
timer,
|
||||||
super_chip8_mode: false,
|
super_chip8_mode: false,
|
||||||
device_keyboard
|
device_keyboard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,12 +140,26 @@ impl Device {
|
|||||||
self.registers.pc += 2;
|
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) => {
|
Instruction::RandomAnd(dest, n) => {
|
||||||
self.registers.v[dest] = random::<u8>() & n;
|
self.registers.v[dest] = random::<u8>() & n;
|
||||||
}
|
}
|
||||||
Instruction::SkipIfKeyPressed(_) => {}
|
Instruction::SkipIfKeyPressed(x) => {
|
||||||
Instruction::SkipIfKeyNotPressed(_) => {}
|
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) => {
|
Instruction::Set(x, y) => {
|
||||||
self.registers.v[x] = self.registers.v[y];
|
self.registers.v[x] = self.registers.v[y];
|
||||||
}
|
}
|
||||||
@@ -170,14 +184,31 @@ impl Device {
|
|||||||
self.registers.v[x] = wrapped_subtraction_result;
|
self.registers.v[x] = wrapped_subtraction_result;
|
||||||
self.set_flag_register(is_overflow);
|
self.set_flag_register(is_overflow);
|
||||||
}
|
}
|
||||||
Instruction::RShift(_, _) => {}
|
|
||||||
Instruction::RSub(x, y) => {
|
Instruction::RSub(x, y) => {
|
||||||
let left = self.registers.v[y];
|
let left = self.registers.v[y];
|
||||||
let (wrapped_subtraction_result, is_overflow) = left.overflowing_sub(self.registers.v[x]);
|
let (wrapped_subtraction_result, is_overflow) = left.overflowing_sub(self.registers.v[x]);
|
||||||
self.registers.v[x] = wrapped_subtraction_result;
|
self.registers.v[x] = wrapped_subtraction_result;
|
||||||
self.set_flag_register(is_overflow);
|
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!()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
///
|
///
|
||||||
|
@@ -37,6 +37,24 @@ pub enum Instruction {
|
|||||||
SkipIfKeyPressed(usize),
|
SkipIfKeyPressed(usize),
|
||||||
/// EXA1 - Check if key is not pressed
|
/// EXA1 - Check if key is not pressed
|
||||||
SkipIfKeyNotPressed(usize),
|
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
|
// ALU operations going ahead
|
||||||
/// 8XY0 - x=y
|
/// 8XY0 - x=y
|
||||||
@@ -139,6 +157,43 @@ impl Instruction {
|
|||||||
let x = (instruction & 0xf00) >> 8;
|
let x = (instruction & 0xf00) >> 8;
|
||||||
Instruction::SkipIfKeyNotPressed(x as usize)
|
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")
|
todo!("Unimplemented instruction")
|
||||||
}
|
}
|
||||||
@@ -389,4 +444,59 @@ mod tests {
|
|||||||
assert_eq!(ins, SkipIfKeyNotPressed(0xb))
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user