diff --git a/src/processor.rs b/src/processor.rs index 92da6a4..7a62b87 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -1,3 +1,5 @@ +use std::ops::{BitAnd, BitOr, BitXor}; + use crate::{Inner, Memory, Register, State}; #[allow(dead_code)] @@ -16,6 +18,7 @@ pub struct CPU { impl CPU { pub fn exec_next(&mut self) -> u8 { let opcode = self.next_opcode(); + unsafe { println!("exec {:#4X} from {:#4X}", opcode, self.state.pc.as_u16 - 1) }; match opcode { 0x0 => { // noop @@ -25,9 +28,13 @@ impl CPU { let address = self.state.bc.as_u16; self.memory.set(address, self.state.af.as_u8s.left); }, - 0x03 => unsafe { self.state.bc.as_u16 += 1 }, - 0x04 => unsafe { self.state.bc.as_u8s.left += 1 }, - 0x05 => unsafe { self.state.bc.as_u8s.left -= 1 }, + 0x03 => unsafe { self.state.bc.as_u16 = self.state.bc.as_u16.wrapping_add(1) }, + 0x04 => unsafe { + self.state.bc.as_u8s.left = self.state.bc.as_u8s.left.wrapping_add(1) + }, + 0x05 => unsafe { + self.state.bc.as_u8s.left = self.state.bc.as_u8s.left.wrapping_sub(1) + }, 0x06 => self.state.bc.as_u8s.left = self.ld_immediate_byte(), 0x07 => panic!("RCLA instruction: 0x07"), 0x08 => unsafe { @@ -35,11 +42,17 @@ impl CPU { let word = self.state.sp; self.store_word(address, word); }, - 0x09 => unsafe { self.state.hl.as_u16 += self.state.bc.as_u16 }, + 0x09 => unsafe { + self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.bc.as_u16) + }, 0x0A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.bc.as_u16) }, - 0x0B => unsafe { self.state.bc.as_u16 -= 0x1 }, - 0x0C => unsafe { self.state.bc.as_u8s.right += 0x1 }, - 0x0D => unsafe { self.state.bc.as_u8s.right -= 0x1 }, + 0x0B => unsafe { self.state.bc.as_u16 = self.state.bc.as_u16.wrapping_sub(0x1) }, + 0x0C => unsafe { + self.state.bc.as_u8s.right = self.state.bc.as_u8s.right.wrapping_add(0x1) + }, + 0x0D => unsafe { + self.state.bc.as_u8s.right = self.state.bc.as_u8s.right.wrapping_sub(0x1) + }, 0x0E => self.state.bc.as_u8s.right = self.ld_immediate_byte(), 0x0F => panic!("RRCA instruction: 0x0F"), 0x10 => panic!("STOP instruction"), @@ -49,65 +62,95 @@ impl CPU { let data = self.state.af.as_u8s.left; self.memory.set(address, data); }, - 0x13 => unsafe { self.state.de.as_u16 -= 0x1 }, - 0x14 => unsafe { self.state.de.as_u8s.left += 0x1 }, - 0x15 => unsafe { self.state.de.as_u8s.left -= 0x1 }, + 0x13 => unsafe { self.state.de.as_u16 = self.state.de.as_u16.wrapping_sub(0x1) }, + 0x14 => unsafe { + self.state.de.as_u8s.left = self.state.de.as_u8s.left.wrapping_add(0x1) + }, + 0x15 => unsafe { + self.state.de.as_u8s.left = self.state.de.as_u8s.left.wrapping_sub(0x1) + }, 0x16 => self.state.de.as_u8s.left = self.ld_immediate_byte(), 0x17 => panic!("RLA instruction: 0x17"), - 0x18 => unsafe { self.state.pc.as_u16 += self.ld_immediate_byte() as u16 }, - 0x19 => unsafe { self.state.hl.as_u16 += self.state.de.as_u16 }, + 0x18 => unsafe { + self.state.pc.as_u16 = self + .state + .pc + .as_u16 + .wrapping_add(self.ld_immediate_byte() as u16) + }, + 0x19 => unsafe { + self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.de.as_u16) + }, 0x1A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.de.as_u16) }, - 0x1B => unsafe { self.state.de.as_u16 -= 1 }, - 0x1C => unsafe { self.state.de.as_u8s.right += 1 }, - 0x1D => unsafe { self.state.de.as_u8s.right -= 1 }, + 0x1B => unsafe { self.state.de.as_u16 = self.state.de.as_u16.wrapping_sub(1) }, + 0x1C => unsafe { + self.state.de.as_u8s.right = self.state.de.as_u8s.right.wrapping_add(1) + }, + 0x1D => unsafe { + self.state.de.as_u8s.right = self.state.de.as_u8s.right.wrapping_sub(1) + }, 0x1E => self.state.de.as_u8s.right = self.ld_immediate_byte(), 0x1F => panic!("RRA instruction: 0x1F"), 0x20 => { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::Z) == 0 { - unsafe { self.state.pc.as_u16 += jump_size as u16 } + unsafe { + self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + } } } 0x21 => self.state.hl = self.ld_immediate_word(), 0x22 => unsafe { self.memory .set(self.state.hl.as_u16, self.state.af.as_u8s.left); - self.state.hl.as_u16 += 1; + self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(1); + }, + 0x23 => unsafe { self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(1) }, + 0x24 => unsafe { + self.state.hl.as_u8s.left = self.state.hl.as_u8s.left.wrapping_add(1) + }, + 0x25 => unsafe { + self.state.hl.as_u8s.left = self.state.hl.as_u8s.left.wrapping_sub(1) }, - 0x23 => unsafe { self.state.hl.as_u16 += 1 }, - 0x24 => unsafe { self.state.hl.as_u8s.left += 1 }, - 0x25 => unsafe { self.state.hl.as_u8s.left -= 1 }, 0x26 => self.state.hl.as_u8s.left = self.ld_immediate_byte(), 0x27 => panic!("DAA instruction: 0x27"), 0x28 => { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::Z) == 1 { - unsafe { self.state.pc.as_u16 += jump_size as u16 } + unsafe { + self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + } } } 0x29 => unsafe { self.state.hl.as_u16 *= 2 }, 0x2A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16); - self.state.hl.as_u16 += 1; + self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(1); + }, + 0x2B => unsafe { self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_sub(1) }, + 0x2C => unsafe { + self.state.hl.as_u8s.right = self.state.hl.as_u8s.right.wrapping_add(1) + }, + 0x2D => unsafe { + self.state.hl.as_u8s.right = self.state.hl.as_u8s.right.wrapping_sub(1) }, - 0x2B => unsafe { self.state.hl.as_u16 -= 1 }, - 0x2C => unsafe { self.state.hl.as_u8s.right += 1 }, - 0x2D => unsafe { self.state.hl.as_u8s.right -= 1 }, 0x2E => self.state.hl.as_u8s.right = self.ld_immediate_byte(), 0x2F => unsafe { self.state.af.as_u8s.left = !self.state.af.as_u8s.left }, 0x30 => { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::C) == 0 { - unsafe { self.state.pc.as_u16 += jump_size as u16 } + unsafe { + self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + } } } 0x31 => self.state.sp = self.ld_immediate_word(), 0x32 => unsafe { self.memory .set(self.state.hl.as_u16, self.state.af.as_u8s.left); - self.state.hl.as_u16 -= 1; + self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_sub(1); }, - 0x33 => unsafe { self.state.sp.as_u16 += 1 }, + 0x33 => unsafe { self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(1) }, 0x34 => unsafe { let address = self.state.hl.as_u16; let data = self.memory.get(address) + 1; @@ -122,46 +165,586 @@ impl CPU { let data = self.ld_immediate_byte(); self.memory.set(self.state.hl.as_u16, data); }, - 0x37 => panic!("SCF instruction: 0x37 - set carry flag"), + 0x37 => self.set_flag(FLAGS::C), 0x38 => { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::C) == 1 { - unsafe { self.state.pc.as_u16 += jump_size as u16 } + unsafe { + self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16) + } } } - 0x39 => unsafe { self.state.hl.as_u16 += self.state.sp.as_u16 }, + 0x39 => unsafe { + self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.sp.as_u16) + }, 0x3A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16); - self.state.hl.as_u16 -= 1; + self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_sub(1); + }, + 0x3B => unsafe { self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_sub(1) }, + 0x3C => unsafe { + self.state.af.as_u8s.left = self.state.af.as_u8s.left.wrapping_add(1) + }, + 0x3D => unsafe { + self.state.af.as_u8s.left = self.state.af.as_u8s.left.wrapping_sub(1) }, - 0x3B => unsafe { self.state.sp.as_u16 -= 1 }, - 0x3C => unsafe { self.state.af.as_u8s.left += 1 }, - 0x3D => unsafe { self.state.af.as_u8s.left -= 1 }, 0x3E => self.state.af.as_u8s.left = self.ld_immediate_byte(), - 0x3F => panic!("CCF instruction: 0x3F - flip carry flag"), - 0x4A => { - unsafe { - self.state.bc.as_u8s.right = self.state.de.as_u8s.left; - }; - } - 0x4B => { - unsafe { - self.state.bc.as_u8s.right = self.state.de.as_u8s.right; - }; - } - 0x53 => { - unsafe { - self.state.de.as_u8s.left = self.state.de.as_u8s.right; - }; - } - 0x66 => { - unsafe { - self.state.hl.as_u8s.left = self.memory.get(self.state.hl.as_u16); - }; + 0x3F => self.toggle_flag(FLAGS::C), + 0x40 => {} + 0x41 => unsafe { self.state.bc.as_u8s.left = self.state.bc.as_u8s.right }, + 0x42 => unsafe { self.state.bc.as_u8s.left = self.state.de.as_u8s.left }, + 0x43 => unsafe { self.state.bc.as_u8s.left = self.state.de.as_u8s.right }, + 0x44 => unsafe { self.state.bc.as_u8s.left = self.state.hl.as_u8s.left }, + 0x45 => unsafe { self.state.bc.as_u8s.left = self.state.hl.as_u8s.right }, + 0x46 => unsafe { self.state.bc.as_u8s.left = self.memory.get(self.state.hl.as_u16) }, + 0x47 => unsafe { self.state.bc.as_u8s.left = self.state.af.as_u8s.left }, + 0x48 => unsafe { self.state.bc.as_u8s.right = self.state.bc.as_u8s.left }, + 0x49 => {} + 0x4A => unsafe { self.state.bc.as_u8s.right = self.state.de.as_u8s.left }, + 0x4B => unsafe { self.state.bc.as_u8s.right = self.state.de.as_u8s.right }, + 0x4C => unsafe { self.state.bc.as_u8s.right = self.state.hl.as_u8s.left }, + 0x4D => unsafe { self.state.bc.as_u8s.right = self.state.hl.as_u8s.right }, + 0x4E => unsafe { self.state.bc.as_u8s.right = self.memory.get(self.state.hl.as_u16) }, + 0x4F => unsafe { self.state.bc.as_u8s.right = self.state.af.as_u8s.left }, + 0x50 => unsafe { self.state.de.as_u8s.left = self.state.bc.as_u8s.left }, + 0x51 => unsafe { self.state.de.as_u8s.left = self.state.bc.as_u8s.right }, + 0x52 => {} + 0x53 => unsafe { self.state.de.as_u8s.left = self.state.de.as_u8s.right }, + 0x54 => unsafe { self.state.de.as_u8s.left = self.state.hl.as_u8s.left }, + 0x55 => unsafe { self.state.de.as_u8s.left = self.state.hl.as_u8s.right }, + 0x56 => unsafe { self.state.de.as_u8s.left = self.memory.get(self.state.hl.as_u16) }, + 0x57 => unsafe { self.state.de.as_u8s.left = self.state.af.as_u8s.left }, + 0x58 => unsafe { self.state.de.as_u8s.right = self.state.bc.as_u8s.left }, + 0x59 => unsafe { self.state.de.as_u8s.right = self.state.bc.as_u8s.right }, + 0x5A => unsafe { self.state.de.as_u8s.right = self.state.de.as_u8s.left }, + 0x5B => {} + 0x5C => unsafe { self.state.de.as_u8s.right = self.state.hl.as_u8s.left }, + 0x5D => unsafe { self.state.de.as_u8s.right = self.state.hl.as_u8s.right }, + 0x5E => unsafe { self.state.de.as_u8s.right = self.memory.get(self.state.hl.as_u16) }, + 0x5F => unsafe { self.state.de.as_u8s.right = self.state.af.as_u8s.left }, + 0x60 => unsafe { self.state.hl.as_u8s.left = self.state.bc.as_u8s.left }, + 0x61 => unsafe { self.state.hl.as_u8s.left = self.state.bc.as_u8s.right }, + 0x62 => unsafe { self.state.hl.as_u8s.left = self.state.de.as_u8s.left }, + 0x63 => unsafe { self.state.hl.as_u8s.left = self.state.de.as_u8s.right }, + 0x64 => {} + 0x65 => unsafe { self.state.hl.as_u8s.left = self.state.hl.as_u8s.right }, + 0x66 => unsafe { self.state.hl.as_u8s.left = self.memory.get(self.state.hl.as_u16) }, + 0x67 => unsafe { self.state.hl.as_u8s.left = self.state.af.as_u8s.left }, + 0x68 => unsafe { self.state.hl.as_u8s.right = self.state.bc.as_u8s.left }, + 0x69 => unsafe { self.state.hl.as_u8s.right = self.state.bc.as_u8s.right }, + 0x6A => unsafe { self.state.hl.as_u8s.right = self.state.de.as_u8s.left }, + 0x6B => unsafe { self.state.hl.as_u8s.right = self.state.de.as_u8s.right }, + 0x6C => unsafe { self.state.hl.as_u8s.right = self.state.hl.as_u8s.left }, + 0x6D => {} + 0x6E => unsafe { self.state.hl.as_u8s.right = self.memory.get(self.state.hl.as_u16) }, + 0x6F => unsafe { self.state.hl.as_u8s.right = self.state.af.as_u8s.left }, + 0x70 => unsafe { + self.memory + .set(self.state.hl.as_u16, self.state.bc.as_u8s.left) + }, + 0x71 => unsafe { + self.memory + .set(self.state.hl.as_u16, self.state.bc.as_u8s.right) + }, + 0x72 => unsafe { + self.memory + .set(self.state.hl.as_u16, self.state.de.as_u8s.left) + }, + 0x73 => unsafe { + self.memory + .set(self.state.hl.as_u16, self.state.de.as_u8s.right) + }, + 0x74 => unsafe { + self.memory + .set(self.state.hl.as_u16, self.state.hl.as_u8s.left) + }, + 0x75 => unsafe { + self.memory + .set(self.state.hl.as_u16, self.state.hl.as_u8s.right) + }, + 0x76 => panic!("HALT instruction: 0x76"), + 0x77 => unsafe { + self.memory + .set(self.state.hl.as_u16, self.state.af.as_u8s.left) + }, + 0x78 => unsafe { self.state.af.as_u8s.left = self.state.bc.as_u8s.left }, + 0x79 => unsafe { self.state.af.as_u8s.left = self.state.bc.as_u8s.right }, + 0x7A => unsafe { self.state.af.as_u8s.left = self.state.de.as_u8s.left }, + 0x7B => unsafe { self.state.af.as_u8s.left = self.state.de.as_u8s.right }, + 0x7C => unsafe { self.state.af.as_u8s.left = self.state.hl.as_u8s.left }, + 0x7D => unsafe { self.state.af.as_u8s.left = self.state.hl.as_u8s.right }, + 0x7E => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16) }, + 0x7F => {} + 0x80 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.bc.as_u8s.left) + }, + 0x81 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.bc.as_u8s.right) + }, + 0x82 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.de.as_u8s.left) + }, + 0x83 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.de.as_u8s.right) + }, + 0x84 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.hl.as_u8s.left) + }, + 0x85 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.hl.as_u8s.right) + }, + 0x86 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.memory.get(self.state.hl.as_u16)) + }, + 0x87 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.af.as_u8s.left) + }, + 0x88 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.bc.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0x89 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.bc.as_u8s.right + self.get_flag(FLAGS::C)) + }, + 0x8A => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.de.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0x8B => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.de.as_u8s.right + self.get_flag(FLAGS::C)) + }, + 0x8C => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.hl.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0x8D => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.hl.as_u8s.right + self.get_flag(FLAGS::C)) + }, + 0x8E => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.wrapping_add( + self.memory.get(self.state.hl.as_u16) + self.get_flag(FLAGS::C), + ) + }, + 0x8F => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.state.af.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0x90 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.bc.as_u8s.left) + }, + 0x91 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.bc.as_u8s.right) + }, + 0x92 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.de.as_u8s.left) + }, + 0x93 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.de.as_u8s.right) + }, + 0x94 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.hl.as_u8s.left) + }, + 0x95 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.hl.as_u8s.right) + }, + 0x96 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.memory.get(self.state.hl.as_u16)) + }, + 0x97 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.af.as_u8s.left) + }, + 0x98 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.bc.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0x99 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.bc.as_u8s.right + self.get_flag(FLAGS::C)) + }, + 0x9A => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.de.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0x9B => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.de.as_u8s.right + self.get_flag(FLAGS::C)) + }, + 0x9C => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.hl.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0x9D => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.hl.as_u8s.right + self.get_flag(FLAGS::C)) + }, + 0x9E => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.wrapping_sub( + self.memory.get(self.state.hl.as_u16) + self.get_flag(FLAGS::C), + ) + }, + 0x9F => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_sub(self.state.af.as_u8s.left + self.get_flag(FLAGS::C)) + }, + 0xA0 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.state.bc.as_u8s.left) + }, + 0xA1 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.state.bc.as_u8s.right) + }, + 0xA2 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.state.de.as_u8s.left) + }, + 0xA3 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.state.de.as_u8s.right) + }, + 0xA4 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.state.hl.as_u8s.left) + }, + 0xA5 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.state.hl.as_u8s.right) + }, + 0xA6 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .bitand(self.memory.get(self.state.hl.as_u16)) + }, + 0xA7 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitand(self.state.af.as_u8s.left) + }, + 0xA8 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.state.bc.as_u8s.left) + }, + 0xA9 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.state.bc.as_u8s.right) + }, + 0xAA => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.state.de.as_u8s.left) + }, + 0xAB => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.state.de.as_u8s.right) + }, + 0xAC => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.state.hl.as_u8s.left) + }, + 0xAD => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.state.hl.as_u8s.right) + }, + 0xAE => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .bitxor(self.memory.get(self.state.hl.as_u16)) + }, + 0xAF => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitxor(self.state.af.as_u8s.left) + }, + 0xB0 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.state.bc.as_u8s.left) + }, + 0xB1 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.state.bc.as_u8s.right) + }, + 0xB2 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.state.de.as_u8s.left) + }, + 0xB3 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.state.de.as_u8s.right) + }, + 0xB4 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.state.hl.as_u8s.left) + }, + 0xB5 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.state.hl.as_u8s.right) + }, + 0xB6 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .bitor(self.memory.get(self.state.hl.as_u16)) + }, + 0xB7 => unsafe { + self.state.af.as_u8s.left = + self.state.af.as_u8s.left.bitor(self.state.af.as_u8s.left) + }, + 0xB8 => unsafe { + if self.state.af.as_u8s.left == self.state.bc.as_u8s.left { + self.set_flag(FLAGS::Z); + } + }, + 0xB9 => unsafe { + if self.state.af.as_u8s.left == self.state.bc.as_u8s.right { + self.set_flag(FLAGS::Z); + } + }, + 0xBA => unsafe { + if self.state.af.as_u8s.left == self.state.de.as_u8s.left { + self.set_flag(FLAGS::Z); + } + }, + 0xBB => unsafe { + if self.state.af.as_u8s.left == self.state.de.as_u8s.right { + self.set_flag(FLAGS::Z); + } + }, + 0xBC => unsafe { + if self.state.af.as_u8s.left == self.state.hl.as_u8s.left { + self.set_flag(FLAGS::Z); + } + }, + 0xBD => unsafe { + if self.state.af.as_u8s.left == self.state.hl.as_u8s.right { + self.set_flag(FLAGS::Z); + } + }, + 0xBE => unsafe { + if self.state.af.as_u8s.left == self.memory.get(self.state.hl.as_u16) { + self.set_flag(FLAGS::Z); + } + }, + 0xBF => self.set_flag(FLAGS::Z), + 0xC0 => unsafe { + if self.get_flag(FLAGS::Z) == 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); + } + }, + 0xC1 => unsafe { + let address = self.state.sp.as_u16; + self.state.bc.as_u8s.left = self.memory.get(address); + self.state.bc.as_u8s.right = self.memory.get(address + 1); + self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); + }, + 0xC2 => { + let word = self.ld_immediate_word(); + if self.get_flag(FLAGS::Z) == 0 { + self.state.pc = word; + } } 0xC3 => { self.state.pc = self.ld_immediate_word(); } + 0xC4 => { + let maybe_next = self.ld_immediate_word(); + if self.get_flag(FLAGS::Z) == 0 { + self.push(self.state.pc); + self.state.pc = maybe_next; + } + } + 0xC5 => self.push(self.state.bc), + 0xC6 => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.ld_immediate_byte()) + }, + 0xC7 => self.rst(0x00), + 0xC8 => { + if self.get_flag(FLAGS::Z) == 1 { + self.state.pc = self.pop_word() + } + } + 0xC9 => self.state.pc = self.pop_word(), + 0xCA => { + let maybe_next = self.ld_immediate_word(); + if self.get_flag(FLAGS::Z) == 1 { + self.state.pc = maybe_next; + } + } + 0xCB => println!("Undefined behaviour: opcode CB"), + 0xCC => { + let maybe_next = self.ld_immediate_word(); + if self.get_flag(FLAGS::Z) == 1 { + self.push(self.state.pc); + self.state.pc = maybe_next; + } + } + 0xCD => { + self.push(self.state.pc); + self.state.pc = self.ld_immediate_word(); + } + 0xCE => unsafe { + self.state.af.as_u8s.left = self + .state + .af + .as_u8s + .left + .wrapping_add(self.ld_immediate_byte() + self.get_flag(FLAGS::C)) + }, + 0xCF => self.rst(0x08), + 0xEA => { unsafe { let address = self.ld_immediate_word().as_u16; @@ -178,11 +761,39 @@ impl CPU { fn next_opcode(&mut self) -> u8 { unsafe { let opcode = self.memory.get(self.state.pc.as_u16); - self.state.pc.as_u16 += 0x1; + self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(0x1); return opcode; }; } + fn rst(&mut self, address: u16) { + self.push(self.state.pc); + self.state.pc.as_u8s.left = 0x0; + self.state.pc.as_u8s.right = self.memory.get(address); + } + + fn push(&mut self, register: Register) { + unsafe { + let address = self.state.sp.as_u16; + self.memory.set(address - 1, register.as_u8s.right); + self.memory.set(address - 2, register.as_u8s.left); + self.state.sp.as_u16 = address - 2; + } + } + + fn pop_word(&mut self) -> Register { + unsafe { + let address = self.state.sp.as_u16; + self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); + Register { + as_u8s: Inner { + left: self.memory.get(address), + right: self.memory.get(address + 1), + }, + } + } + } + fn store_word(&mut self, address: u16, word: Register) { unsafe { self.memory.set(address, word.as_u8s.left); @@ -208,4 +819,23 @@ impl CPU { return self.state.af.as_u8s.right & (1 << flag as u8); } } + + fn set_flag(&mut self, flag: FLAGS) { + unsafe { + self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitor(1 << flag as u8); + }; + } + + #[allow(dead_code)] + fn clear_flag(&mut self, flag: FLAGS) { + unsafe { + self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitand(!(1 << flag as u8)); + }; + } + + fn toggle_flag(&mut self, flag: FLAGS) { + unsafe { + self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitxor(1 << flag as u8); + }; + } }