From e6cbedc59bb6906efd9530ea36408700ed2ff09e Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Tue, 17 Jan 2023 09:09:53 +1100 Subject: [PATCH] all opcodes implemented-ish --- src/processor.rs | 238 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 222 insertions(+), 16 deletions(-) diff --git a/src/processor.rs b/src/processor.rs index 7a62b87..d9477d4 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -1,4 +1,7 @@ -use std::ops::{BitAnd, BitOr, BitXor}; +use std::{ + mem::transmute, + ops::{BitAnd, BitOr, BitXor}, +}; use crate::{Inner, Memory, Register, State}; @@ -16,9 +19,9 @@ pub struct CPU { } impl CPU { - pub fn exec_next(&mut self) -> u8 { + pub fn exec_next(&mut self) { let opcode = self.next_opcode(); - unsafe { println!("exec {:#4X} from {:#4X}", opcode, self.state.pc.as_u16 - 1) }; + // unsafe { println!("exec {:#4X} from {:#4X}", opcode, self.state.pc.as_u16 - 1) }; match opcode { 0x0 => { // noop @@ -76,7 +79,7 @@ impl CPU { .state .pc .as_u16 - .wrapping_add(self.ld_immediate_byte() as u16) + .wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16) }, 0x19 => unsafe { self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.de.as_u16) @@ -95,7 +98,11 @@ impl CPU { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::Z) == 0 { unsafe { - self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + self.state.pc.as_u16 = self + .state + .pc + .as_u16 + .wrapping_add((as_signed(jump_size) as i16) as u16) } } } @@ -118,7 +125,11 @@ impl CPU { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::Z) == 1 { unsafe { - self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + self.state.pc.as_u16 = self + .state + .pc + .as_u16 + .wrapping_add((as_signed(jump_size) as i16) as u16) } } } @@ -140,7 +151,11 @@ impl CPU { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::C) == 0 { unsafe { - self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + self.state.pc.as_u16 = self + .state + .pc + .as_u16 + .wrapping_add((as_signed(jump_size) as i16) as u16) } } } @@ -170,7 +185,11 @@ impl CPU { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::C) == 1 { unsafe { - self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + self.state.pc.as_u16 = self + .state + .pc + .as_u16 + .wrapping_add((as_signed(jump_size) as i16) as u16) } } } @@ -723,7 +742,10 @@ impl CPU { self.state.pc = maybe_next; } } - 0xCB => println!("Undefined behaviour: opcode CB"), + 0xCB => { + let subop = self.ld_immediate_byte(); + self.cb_subop(subop); + } 0xCC => { let maybe_next = self.ld_immediate_word(); if self.get_flag(FLAGS::Z) == 1 { @@ -744,18 +766,192 @@ impl CPU { .wrapping_add(self.ld_immediate_byte() + self.get_flag(FLAGS::C)) }, 0xCF => self.rst(0x08), - - 0xEA => { + 0xD0 => unsafe { + if self.get_flag(FLAGS::C) == 0 { + let address = self.state.sp.as_u16; + self.state.pc.as_u8s.left = self.memory.get(address); + self.state.pc.as_u8s.right = self.memory.get(address + 1); + self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); + } + }, + 0xD1 => unsafe { + let address = self.state.sp.as_u16; + self.state.de.as_u8s.left = self.memory.get(address); + self.state.de.as_u8s.right = self.memory.get(address + 1); + self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); + }, + 0xD2 => { + let word = self.ld_immediate_word(); + if self.get_flag(FLAGS::C) == 0 { + self.state.pc = word; + } + } + 0xD3 => undefined(0xD3), + 0xD4 => { + let maybe_next = self.ld_immediate_word(); + if self.get_flag(FLAGS::C) == 0 { + self.push(self.state.pc); + self.state.pc = maybe_next; + } + } + 0xD5 => self.push(self.state.de), + 0xD6 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.ld_immediate_byte()) + }, + 0xD7 => self.rst(0x10), + 0xD8 => { + if self.get_flag(FLAGS::C) == 1 { + self.state.pc = self.pop_word() + } + } + 0xD9 => panic!("RETI: 0xD9"), + 0xDA => { + let maybe_next = self.ld_immediate_word(); + if self.get_flag(FLAGS::C) == 1 { + self.state.pc = maybe_next; + } + } + 0xDB => undefined(0xDB), + 0xDC => { + let maybe_next = self.ld_immediate_word(); + if self.get_flag(FLAGS::C) == 1 { + self.push(self.state.pc); + self.state.pc = maybe_next; + } + } + 0xDD => undefined(0xDE), + 0xDE => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.ld_immediate_byte() + self.get_flag(FLAGS::C)) + }, + 0xDF => self.rst(0x18), + 0xE0 => { unsafe { - let address = self.ld_immediate_word().as_u16; - self.memory.set(address, self.state.af.as_u8s.left); + let address = Register { + as_u8s: Inner { + left: self.ld_immediate_byte(), + right: 0xFF, + }, + }; + self.memory.set(address.as_u16, self.state.af.as_u8s.left); }; } - _ => { - panic!("unimplemented opcode: {:#X}", opcode); + 0xE1 => unsafe { + let address = self.state.sp.as_u16; + self.state.hl.as_u8s.left = self.memory.get(address); + self.state.hl.as_u8s.right = self.memory.get(address + 1); + self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); + }, + 0xE2 => { + unsafe { + let address = Register { + as_u8s: Inner { + left: self.state.bc.as_u8s.right, + right: 0xFF, + }, + }; + self.memory.set(address.as_u16, self.state.af.as_u8s.left); + }; } + 0xE3 => undefined(0xE3), + 0xE4 => undefined(0xE4), + 0xE5 => self.push(self.state.hl), + 0xE6 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.ld_immediate_byte()) + }, + 0xE7 => self.rst(0x20), + 0xE8 => unsafe { + self.state.sp.as_u16 = self + .state + .sp + .as_u16 + .wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16); + }, + 0xE9 => self.state.pc = self.state.hl, + 0xEA => unsafe { + let address = self.ld_immediate_word().as_u16; + self.memory.set(address, self.state.af.as_u8s.left); + }, + 0xEB => undefined(0xEB), + 0xEC => undefined(0xEC), + 0xED => undefined(0xED), + 0xEE => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.ld_immediate_byte()) + }, + 0xEF => self.rst(0x28), + 0xF0 => { + unsafe { + let address = Register { + as_u8s: Inner { + left: self.ld_immediate_byte(), + right: 0xFF, + }, + }; + self.state.af.as_u8s.left = self.memory.get(address.as_u16); + }; + } + 0xF1 => unsafe { + let address = self.state.sp.as_u16; + self.state.af.as_u8s.left = self.memory.get(address); + self.state.af.as_u8s.right = self.memory.get(address + 1); + self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); + }, + 0xF2 => { + unsafe { + let address = Register { + as_u8s: Inner { + left: self.state.bc.as_u8s.right, + right: 0xFF, + }, + }; + self.state.af.as_u8s.left = self.memory.get(address.as_u16); + }; + } + 0xF3 => panic!("DI IME instruction: 0xF3"), + 0xF4 => undefined(0xF4), + 0xF5 => self.push(self.state.af), + 0xF6 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.ld_immediate_byte()) + }, + 0xF7 => self.rst(0x30), + 0xF8 => unsafe { + self.state.hl.as_u16 = self + .state + .sp + .as_u16 + .wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16) + }, + 0xF9 => self.state.sp = self.state.hl, + 0xFA => unsafe { + let address = self.ld_immediate_word().as_u16; + self.state.af.as_u8s.left = self.memory.get(address); + }, + 0xFB => panic!("EI IME instruction: 0xFB"), + 0xFC => undefined(0xFC), + 0xFD => undefined(0xFD), + 0xFE => unsafe { + if self.ld_immediate_byte() == self.state.af.as_u8s.left { + self.set_flag(FLAGS::Z) + } + }, + 0xFF => self.rst(0x38), }; - return opcode; + } + + fn cb_subop(&mut self, subop: u8) { + panic!("Unimplemented sub-opcode: {:#X}", subop); } fn next_opcode(&mut self) -> u8 { @@ -839,3 +1035,13 @@ impl CPU { }; } } + +fn undefined(opcode: u8) { + println!("Undefined behaviour: opcode {:#X}", opcode); +} + +fn as_signed(unsigned: u8) -> i8 { + unsafe { + return transmute(unsigned); + } +}