use std::ops::{BitAnd, BitOr, BitXor}; use crate::{Inner, Memory, Register, State}; #[allow(dead_code)] enum FLAGS { Z = 7, N = 6, H = 5, C = 4, } pub struct CPU { pub memory: Memory, pub state: State, } 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 } 0x01 => self.state.bc = self.ld_immediate_word(), 0x02 => unsafe { let address = self.state.bc.as_u16; self.memory.set(address, self.state.af.as_u8s.left); }, 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 { let address = self.ld_immediate_word().as_u16; let word = self.state.sp; self.store_word(address, word); }, 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 = 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"), 0x11 => self.state.de = self.ld_immediate_word(), 0x12 => unsafe { let address = self.state.de.as_u16; let data = self.state.af.as_u8s.left; self.memory.set(address, data); }, 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 .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 = 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 = 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 = 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) }, 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 = 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 = 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) }, 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 = 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 = self.state.hl.as_u16.wrapping_sub(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; self.memory.set(address, data); }, 0x35 => unsafe { let address = self.state.hl.as_u16; let data = self.memory.get(address) - 1; self.memory.set(address, data); }, 0x36 => unsafe { let data = self.ld_immediate_byte(); self.memory.set(self.state.hl.as_u16, data); }, 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 = self.state.pc.as_u16.wrapping_add(jump_size 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 = 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) }, 0x3E => self.state.af.as_u8s.left = self.ld_immediate_byte(), 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; self.memory.set(address, self.state.af.as_u8s.left); }; } _ => { panic!("unimplemented opcode: {:#X}", opcode); } }; return opcode; } fn next_opcode(&mut self) -> u8 { unsafe { let opcode = self.memory.get(self.state.pc.as_u16); 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); self.memory.set(address + 1, word.as_u8s.right); }; } fn ld_immediate_word(&mut self) -> Register { Register { as_u8s: Inner { left: self.next_opcode(), right: self.next_opcode(), }, } } fn ld_immediate_byte(&mut self) -> u8 { self.next_opcode() } fn get_flag(&mut self, flag: FLAGS) -> u8 { unsafe { 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); }; } }