use std::{ mem::transmute, ops::{BitAnd, BitOr, BitXor}, }; use crate::{Inner, Memory, Register, State}; #[allow(dead_code)] #[derive(PartialEq)] enum FLAGS { Z = 7, N = 6, H = 5, C = 4, } enum Direction { Left, Right, } pub struct CPU { pub memory: Memory, pub state: State, pub last_instruction: u8, pub last_instruction_addr: u16, } impl CPU { pub fn exec_next(&mut self) { unsafe { self.last_instruction_addr = self.state.pc.as_u16 }; let opcode = self.next_opcode(); self.last_instruction = opcode; 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.add_u16s(self.state.bc.as_u16, 1) }, 0x04 => unsafe { self.state.bc.as_u8s.left = self.add_u8s(self.state.bc.as_u8s.left, 1) }, 0x05 => unsafe { self.state.bc.as_u8s.left = self.sub_u8s(self.state.bc.as_u8s.left, 1) }, 0x06 => self.state.bc.as_u8s.left = self.ld_immediate_byte(), 0x07 => unsafe { self.state.af.as_u8s.left = self.rlc(self.state.af.as_u8s.left) }, 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.add_u16s(self.state.hl.as_u16, 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.sub_u16s(self.state.bc.as_u16, 0x1) }, 0x0C => unsafe { self.state.bc.as_u8s.right = self.add_u8s(self.state.bc.as_u8s.right, 0x1) }, 0x0D => unsafe { self.state.bc.as_u8s.right = self.sub_u8s(self.state.bc.as_u8s.right, 0x1) }, 0x0E => self.state.bc.as_u8s.right = self.ld_immediate_byte(), 0x0F => unsafe { self.state.af.as_u8s.left = self.rrc(self.state.af.as_u8s.left) }, 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.sub_u16s(self.state.de.as_u16, 0x1) }, 0x14 => unsafe { self.state.de.as_u8s.left = self.add_u8s(self.state.de.as_u8s.left, 0x1) }, 0x15 => unsafe { self.state.de.as_u8s.left = self.sub_u8s(self.state.de.as_u8s.left, 0x1) }, 0x16 => self.state.de.as_u8s.left = self.ld_immediate_byte(), 0x17 => unsafe { self.state.af.as_u8s.left = self.rl(self.state.af.as_u8s.left); }, 0x18 => unsafe { let t = (as_signed(self.ld_immediate_byte()) as i16) as u16; self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(t) }, 0x19 => unsafe { self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, self.state.de.as_u16) }, 0x1A => unsafe { // println!("loading from {:#X}", self.state.de.as_u16); self.state.af.as_u8s.left = self.memory.get(self.state.de.as_u16); }, 0x1B => unsafe { self.state.de.as_u16 = self.sub_u16s(self.state.de.as_u16, 1) }, 0x1C => unsafe { self.state.de.as_u8s.right = self.add_u8s(self.state.de.as_u8s.right, 1) }, 0x1D => unsafe { self.state.de.as_u8s.right = self.sub_u8s(self.state.de.as_u8s.right, 1) }, 0x1E => self.state.de.as_u8s.right = self.ld_immediate_byte(), 0x1F => unsafe { self.state.af.as_u8s.left = self.rr(self.state.af.as_u8s.left); }, 0x20 => { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::Z) == 0 { println!("z flag is 0... so doing jump..."); unsafe { self.state.pc.as_u16 = self .state .pc .as_u16 .wrapping_add((as_signed(jump_size) as i16) as u16) } } else { unsafe { println!( "not jumping! z flag is {0:#b}, flags are {1:#b} / {1:#X}", self.get_flag(FLAGS::Z), self.state.af.as_u8s.right ); } } } 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.add_u16s(self.state.hl.as_u16, 1); }, 0x23 => unsafe { self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, 1) }, 0x24 => unsafe { self.state.hl.as_u8s.left = self.add_u8s(self.state.hl.as_u8s.left, 1) }, 0x25 => unsafe { self.state.hl.as_u8s.left = self.sub_u8s(self.state.hl.as_u8s.left, 1) }, 0x26 => self.state.hl.as_u8s.left = self.ld_immediate_byte(), 0x27 => unsafe { println!("Running DAA instruction (0x27) that I'm not too sure about..."); if self.get_flag(FLAGS::N) == 0 { if self.get_flag(FLAGS::C) == 1 || self.state.af.as_u8s.left > 0x99 { self.state.af.as_u8s.left += 0x60; } if self.get_flag(FLAGS::H) == 1 || (self.state.af.as_u8s.left & 0x0f) > 0x09 { self.state.af.as_u8s.left += 0x6; } } else { if self.get_flag(FLAGS::C) == 1 { self.state.af.as_u8s.left -= 0x60; } if self.get_flag(FLAGS::H) == 1 { self.state.af.as_u8s.left -= 0x6; } } println!( " ...this set register a to {:#X}...", self.state.af.as_u8s.left ); }, 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((as_signed(jump_size) as i16) as u16) } } } 0x29 => unsafe { self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, self.state.hl.as_u16) }, 0x2A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16); self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, 1); }, 0x2B => unsafe { self.state.hl.as_u16 = self.sub_u16s(self.state.hl.as_u16, 1) }, 0x2C => unsafe { self.state.hl.as_u8s.right = self.add_u8s(self.state.hl.as_u8s.right, 1) }, 0x2D => unsafe { self.state.hl.as_u8s.right = self.sub_u8s(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 = self .state .pc .as_u16 .wrapping_add((as_signed(jump_size) as i16) 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.sub_u16s(self.state.hl.as_u16, 1); }, 0x33 => unsafe { self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 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((as_signed(jump_size) as i16) as u16) } } } 0x39 => unsafe { self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, 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.sub_u16s(self.state.hl.as_u16, 1); }, 0x3B => unsafe { self.state.sp.as_u16 = self.sub_u16s(self.state.sp.as_u16, 1) }, 0x3C => unsafe { self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, 1) }, 0x3D => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, 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 until interrupt... 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.add_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left) }, 0x81 => unsafe { self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.right) }, 0x82 => unsafe { self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left) }, 0x83 => unsafe { self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right) }, 0x84 => unsafe { self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left) }, 0x85 => unsafe { self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right) }, 0x86 => unsafe { self.state.af.as_u8s.left = self.add_u8s( self.state.af.as_u8s.left, self.memory.get(self.state.hl.as_u16), ) }, 0x87 => unsafe { self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left) }, 0x88 => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left + f) }, 0x89 => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s( self.state.af.as_u8s.left, self.state.bc.as_u8s.right.wrapping_add(f), ) }, 0x8A => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left + f) }, 0x8B => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right + f) }, 0x8C => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left + f) }, 0x8D => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right + f) }, 0x8E => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s( self.state.af.as_u8s.left, self.memory.get(self.state.hl.as_u16).wrapping_add(f), ) }, 0x8F => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left + f) }, 0x90 => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left) }, 0x91 => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.right) }, 0x92 => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left) }, 0x93 => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right) }, 0x94 => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left) }, 0x95 => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right) }, 0x96 => unsafe { self.state.af.as_u8s.left = self.sub_u8s( self.state.af.as_u8s.left, self.memory.get(self.state.hl.as_u16), ) }, 0x97 => unsafe { self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left) }, 0x98 => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left + f) }, 0x99 => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.right + f) }, 0x9A => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left + f) }, 0x9B => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right + f) }, 0x9C => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left + f) }, 0x9D => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right + f) }, 0x9E => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s( self.state.af.as_u8s.left, self.memory.get(self.state.hl.as_u16) + f, ) }, 0x9F => unsafe { let f = self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left + f) }, 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.add_u16s(self.state.sp.as_u16, 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.add_u16s(self.state.sp.as_u16, 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 { let t = self.ld_immediate_byte(); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, t) }, 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 => { 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 { 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 { let t = self.ld_immediate_byte() + self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, t) }, 0xCF => self.rst(0x08), 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.add_u16s(self.state.sp.as_u16, 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.add_u16s(self.state.sp.as_u16, 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 { let t = self.ld_immediate_byte(); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, t) }, 0xD7 => self.rst(0x10), 0xD8 => { if self.get_flag(FLAGS::C) == 1 { self.state.pc = self.pop_word() } } 0xD9 => { self.state.pc = self.pop_word(); self.memory.ime = true; } 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 { let t = self.ld_immediate_byte() + self.get_flag(FLAGS::C); self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, t) }, 0xDF => self.rst(0x18), 0xE0 => { unsafe { 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); }; } 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.add_u16s(self.state.sp.as_u16, 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 { let t = (as_signed(self.ld_immediate_byte()) as i16) as u16; self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, t); }, 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.add_u16s(self.state.sp.as_u16, 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 => self.memory.ime = false, 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 { let t = (as_signed(self.ld_immediate_byte()) as i16) as u16; self.state.hl.as_u16 = self.add_u16s(self.state.sp.as_u16, t) }, 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 => self.memory.ime = true, 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), }; } fn cb_subop(&mut self, subop: u8) { match subop { 0x00 => unsafe { self.state.bc.as_u8s.left = self.rlc(self.state.bc.as_u8s.left) }, 0x01 => unsafe { self.state.bc.as_u8s.right = self.rlc(self.state.bc.as_u8s.right) }, 0x02 => unsafe { self.state.de.as_u8s.left = self.rlc(self.state.de.as_u8s.left) }, 0x03 => unsafe { self.state.de.as_u8s.right = self.rlc(self.state.de.as_u8s.right) }, 0x04 => unsafe { self.state.hl.as_u8s.left = self.rlc(self.state.hl.as_u8s.left) }, 0x05 => unsafe { self.state.hl.as_u8s.right = self.rlc(self.state.hl.as_u8s.right) }, 0x06 => unsafe { let rotated = self.rlc(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x07 => unsafe { self.state.af.as_u8s.left = self.rlc(self.state.af.as_u8s.left) }, 0x08 => unsafe { self.state.bc.as_u8s.left = self.rrc(self.state.bc.as_u8s.left) }, 0x09 => unsafe { self.state.bc.as_u8s.right = self.rrc(self.state.bc.as_u8s.right) }, 0x0A => unsafe { self.state.de.as_u8s.left = self.rrc(self.state.de.as_u8s.left) }, 0x0B => unsafe { self.state.de.as_u8s.right = self.rrc(self.state.de.as_u8s.right) }, 0x0C => unsafe { self.state.hl.as_u8s.left = self.rrc(self.state.hl.as_u8s.left) }, 0x0D => unsafe { self.state.hl.as_u8s.right = self.rrc(self.state.hl.as_u8s.right) }, 0x0E => unsafe { let rotated = self.rrc(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x0F => unsafe { self.state.af.as_u8s.left = self.rrc(self.state.af.as_u8s.left) }, 0x10 => unsafe { self.state.bc.as_u8s.left = self.rl(self.state.bc.as_u8s.left) }, 0x11 => unsafe { self.state.bc.as_u8s.right = self.rl(self.state.bc.as_u8s.right) }, 0x12 => unsafe { self.state.de.as_u8s.left = self.rl(self.state.de.as_u8s.left) }, 0x13 => unsafe { self.state.de.as_u8s.right = self.rl(self.state.de.as_u8s.right) }, 0x14 => unsafe { self.state.hl.as_u8s.left = self.rl(self.state.hl.as_u8s.left) }, 0x15 => unsafe { self.state.hl.as_u8s.right = self.rl(self.state.hl.as_u8s.right) }, 0x16 => unsafe { let rotated = self.rl(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x17 => unsafe { self.state.af.as_u8s.left = self.rl(self.state.af.as_u8s.left) }, 0x18 => unsafe { self.state.bc.as_u8s.left = self.rr(self.state.bc.as_u8s.left) }, 0x19 => unsafe { self.state.bc.as_u8s.right = self.rr(self.state.bc.as_u8s.right) }, 0x1A => unsafe { self.state.de.as_u8s.left = self.rr(self.state.de.as_u8s.left) }, 0x1B => unsafe { self.state.de.as_u8s.right = self.rr(self.state.de.as_u8s.right) }, 0x1C => unsafe { self.state.hl.as_u8s.left = self.rr(self.state.hl.as_u8s.left) }, 0x1D => unsafe { self.state.hl.as_u8s.right = self.rr(self.state.hl.as_u8s.right) }, 0x1E => unsafe { let rotated = self.rr(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x1F => unsafe { self.state.af.as_u8s.left = self.rr(self.state.af.as_u8s.left) }, 0x20 => unsafe { self.state.bc.as_u8s.left = self.sla(self.state.bc.as_u8s.left) }, 0x21 => unsafe { self.state.bc.as_u8s.right = self.sla(self.state.bc.as_u8s.right) }, 0x22 => unsafe { self.state.de.as_u8s.left = self.sla(self.state.de.as_u8s.left) }, 0x23 => unsafe { self.state.de.as_u8s.right = self.sla(self.state.de.as_u8s.right) }, 0x24 => unsafe { self.state.hl.as_u8s.left = self.sla(self.state.hl.as_u8s.left) }, 0x25 => unsafe { self.state.hl.as_u8s.right = self.sla(self.state.hl.as_u8s.right) }, 0x26 => unsafe { let rotated = self.sla(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x27 => unsafe { self.state.af.as_u8s.left = self.sla(self.state.af.as_u8s.left) }, 0x28 => unsafe { self.state.bc.as_u8s.left = self.sra(self.state.bc.as_u8s.left) }, 0x29 => unsafe { self.state.bc.as_u8s.right = self.sra(self.state.bc.as_u8s.right) }, 0x2A => unsafe { self.state.de.as_u8s.left = self.sra(self.state.de.as_u8s.left) }, 0x2B => unsafe { self.state.de.as_u8s.right = self.sra(self.state.de.as_u8s.right) }, 0x2C => unsafe { self.state.hl.as_u8s.left = self.sra(self.state.hl.as_u8s.left) }, 0x2D => unsafe { self.state.hl.as_u8s.right = self.sra(self.state.hl.as_u8s.right) }, 0x2E => unsafe { let rotated = self.sra(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x2F => unsafe { self.state.af.as_u8s.left = self.sra(self.state.af.as_u8s.left) }, 0x30 => unsafe { self.state.bc.as_u8s.left = swap_nibbles(self.state.bc.as_u8s.left) }, 0x31 => unsafe { self.state.bc.as_u8s.right = swap_nibbles(self.state.bc.as_u8s.right) }, 0x32 => unsafe { self.state.de.as_u8s.left = swap_nibbles(self.state.de.as_u8s.left) }, 0x33 => unsafe { self.state.de.as_u8s.right = swap_nibbles(self.state.de.as_u8s.right) }, 0x34 => unsafe { self.state.hl.as_u8s.left = swap_nibbles(self.state.hl.as_u8s.left) }, 0x35 => unsafe { self.state.hl.as_u8s.right = swap_nibbles(self.state.hl.as_u8s.right) }, 0x36 => unsafe { let rotated = swap_nibbles(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x37 => unsafe { self.state.af.as_u8s.left = swap_nibbles(self.state.af.as_u8s.left) }, 0x38 => unsafe { self.state.bc.as_u8s.left = self.srl(self.state.bc.as_u8s.left) }, 0x39 => unsafe { self.state.bc.as_u8s.right = self.srl(self.state.bc.as_u8s.right) }, 0x3A => unsafe { self.state.de.as_u8s.left = self.srl(self.state.de.as_u8s.left) }, 0x3B => unsafe { self.state.de.as_u8s.right = self.srl(self.state.de.as_u8s.right) }, 0x3C => unsafe { self.state.hl.as_u8s.left = self.srl(self.state.hl.as_u8s.left) }, 0x3D => unsafe { self.state.hl.as_u8s.right = self.srl(self.state.hl.as_u8s.right) }, 0x3E => unsafe { let rotated = self.srl(self.memory.get(self.state.hl.as_u16)); self.memory.set(self.state.hl.as_u16, rotated) }, 0x3F => unsafe { self.state.af.as_u8s.left = self.srl(self.state.af.as_u8s.left) }, 0x40 => unsafe { self.bit(self.state.bc.as_u8s.left, 0) }, 0x41 => unsafe { self.bit(self.state.bc.as_u8s.right, 0) }, 0x42 => unsafe { self.bit(self.state.de.as_u8s.left, 0) }, 0x43 => unsafe { self.bit(self.state.de.as_u8s.right, 0) }, 0x44 => unsafe { self.bit(self.state.hl.as_u8s.left, 0) }, 0x45 => unsafe { self.bit(self.state.hl.as_u8s.right, 0) }, 0x46 => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 0); }, 0x47 => unsafe { self.bit(self.state.af.as_u8s.left, 1) }, 0x48 => unsafe { self.bit(self.state.bc.as_u8s.left, 1) }, 0x49 => unsafe { self.bit(self.state.bc.as_u8s.right, 1) }, 0x4A => unsafe { self.bit(self.state.de.as_u8s.left, 1) }, 0x4B => unsafe { self.bit(self.state.de.as_u8s.right, 1) }, 0x4C => unsafe { self.bit(self.state.hl.as_u8s.left, 1) }, 0x4D => unsafe { self.bit(self.state.hl.as_u8s.right, 1) }, 0x4E => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 1); }, 0x4F => unsafe { self.bit(self.state.af.as_u8s.left, 1) }, 0x50 => unsafe { self.bit(self.state.bc.as_u8s.left, 2) }, 0x51 => unsafe { self.bit(self.state.bc.as_u8s.right, 2) }, 0x52 => unsafe { self.bit(self.state.de.as_u8s.left, 2) }, 0x53 => unsafe { self.bit(self.state.de.as_u8s.right, 2) }, 0x54 => unsafe { self.bit(self.state.hl.as_u8s.left, 2) }, 0x55 => unsafe { self.bit(self.state.hl.as_u8s.right, 2) }, 0x56 => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 2); }, 0x57 => unsafe { self.bit(self.state.af.as_u8s.left, 3) }, 0x58 => unsafe { self.bit(self.state.bc.as_u8s.left, 3) }, 0x59 => unsafe { self.bit(self.state.bc.as_u8s.right, 3) }, 0x5A => unsafe { self.bit(self.state.de.as_u8s.left, 3) }, 0x5B => unsafe { self.bit(self.state.de.as_u8s.right, 3) }, 0x5C => unsafe { self.bit(self.state.hl.as_u8s.left, 3) }, 0x5D => unsafe { self.bit(self.state.hl.as_u8s.right, 3) }, 0x5E => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 3); }, 0x5F => unsafe { self.bit(self.state.af.as_u8s.left, 3) }, 0x60 => unsafe { self.bit(self.state.bc.as_u8s.left, 4) }, 0x61 => unsafe { self.bit(self.state.bc.as_u8s.right, 4) }, 0x62 => unsafe { self.bit(self.state.de.as_u8s.left, 4) }, 0x63 => unsafe { self.bit(self.state.de.as_u8s.right, 4) }, 0x64 => unsafe { self.bit(self.state.hl.as_u8s.left, 4) }, 0x65 => unsafe { self.bit(self.state.hl.as_u8s.right, 4) }, 0x66 => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 4); }, 0x67 => unsafe { self.bit(self.state.af.as_u8s.left, 5) }, 0x68 => unsafe { self.bit(self.state.bc.as_u8s.left, 5) }, 0x69 => unsafe { self.bit(self.state.bc.as_u8s.right, 5) }, 0x6A => unsafe { self.bit(self.state.de.as_u8s.left, 5) }, 0x6B => unsafe { self.bit(self.state.de.as_u8s.right, 5) }, 0x6C => unsafe { self.bit(self.state.hl.as_u8s.left, 5) }, 0x6D => unsafe { self.bit(self.state.hl.as_u8s.right, 5) }, 0x6E => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 5); }, 0x6F => unsafe { self.bit(self.state.af.as_u8s.left, 5) }, 0x70 => unsafe { self.bit(self.state.bc.as_u8s.left, 6) }, 0x71 => unsafe { self.bit(self.state.bc.as_u8s.right, 6) }, 0x72 => unsafe { self.bit(self.state.de.as_u8s.left, 6) }, 0x73 => unsafe { self.bit(self.state.de.as_u8s.right, 6) }, 0x74 => unsafe { self.bit(self.state.hl.as_u8s.left, 6) }, 0x75 => unsafe { self.bit(self.state.hl.as_u8s.right, 6) }, 0x76 => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 6); }, 0x77 => unsafe { self.bit(self.state.af.as_u8s.left, 7) }, 0x78 => unsafe { self.bit(self.state.bc.as_u8s.left, 7) }, 0x79 => unsafe { self.bit(self.state.bc.as_u8s.right, 7) }, 0x7A => unsafe { self.bit(self.state.de.as_u8s.left, 7) }, 0x7B => unsafe { self.bit(self.state.de.as_u8s.right, 7) }, 0x7C => unsafe { self.bit(self.state.hl.as_u8s.left, 7) }, 0x7D => unsafe { self.bit(self.state.hl.as_u8s.right, 7) }, 0x7E => unsafe { self.bit(self.memory.get(self.state.hl.as_u16), 7); }, 0x7F => unsafe { self.bit(self.state.af.as_u8s.left, 7) }, 0x80 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 0) }, 0x81 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 0) }, 0x82 => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 0) }, 0x83 => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 0) }, 0x84 => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 0) }, 0x85 => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 0) }, 0x86 => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 0); self.memory.set(self.state.hl.as_u16, rotated) }, 0x87 => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 0) }, 0x88 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 1) }, 0x89 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 1) }, 0x8A => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 1) }, 0x8B => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 1) }, 0x8C => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 1) }, 0x8D => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 1) }, 0x8E => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 1); self.memory.set(self.state.hl.as_u16, rotated) }, 0x8F => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 1) }, 0x90 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 2) }, 0x91 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 2) }, 0x92 => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 2) }, 0x93 => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 2) }, 0x94 => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 2) }, 0x95 => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 2) }, 0x96 => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 2); self.memory.set(self.state.hl.as_u16, rotated) }, 0x97 => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 2) }, 0x98 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 3) }, 0x99 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 3) }, 0x9A => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 3) }, 0x9B => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 3) }, 0x9C => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 3) }, 0x9D => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 3) }, 0x9E => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 3); self.memory.set(self.state.hl.as_u16, rotated) }, 0x9F => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 3) }, 0xA0 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 4) }, 0xA1 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 4) }, 0xA2 => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 4) }, 0xA3 => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 4) }, 0xA4 => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 4) }, 0xA5 => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 4) }, 0xA6 => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 4); self.memory.set(self.state.hl.as_u16, rotated) }, 0xA7 => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 4) }, 0xA8 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 5) }, 0xA9 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 5) }, 0xAA => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 5) }, 0xAB => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 5) }, 0xAC => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 5) }, 0xAD => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 5) }, 0xAE => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 5); self.memory.set(self.state.hl.as_u16, rotated) }, 0xAF => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 5) }, 0xB0 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 6) }, 0xB1 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 6) }, 0xB2 => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 6) }, 0xB3 => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 6) }, 0xB4 => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 6) }, 0xB5 => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 6) }, 0xB6 => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 6); self.memory.set(self.state.hl.as_u16, rotated) }, 0xB7 => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 6) }, 0xB8 => unsafe { self.state.bc.as_u8s.left = res(self.state.bc.as_u8s.left, 7) }, 0xB9 => unsafe { self.state.bc.as_u8s.right = res(self.state.bc.as_u8s.right, 7) }, 0xBA => unsafe { self.state.de.as_u8s.left = res(self.state.de.as_u8s.left, 7) }, 0xBB => unsafe { self.state.de.as_u8s.right = res(self.state.de.as_u8s.right, 7) }, 0xBC => unsafe { self.state.hl.as_u8s.left = res(self.state.hl.as_u8s.left, 7) }, 0xBD => unsafe { self.state.hl.as_u8s.right = res(self.state.hl.as_u8s.right, 7) }, 0xBE => unsafe { let rotated = res(self.memory.get(self.state.hl.as_u16), 7); self.memory.set(self.state.hl.as_u16, rotated) }, 0xBF => unsafe { self.state.af.as_u8s.left = res(self.state.af.as_u8s.left, 7) }, 0xC0 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 0) }, 0xC1 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 0) }, 0xC2 => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 0) }, 0xC3 => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 0) }, 0xC4 => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 0) }, 0xC5 => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 0) }, 0xC6 => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 0); self.memory.set(self.state.hl.as_u16, rotated) }, 0xC7 => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 0) }, 0xC8 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 1) }, 0xC9 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 1) }, 0xCA => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 1) }, 0xCB => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 1) }, 0xCC => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 1) }, 0xCD => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 1) }, 0xCE => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 1); self.memory.set(self.state.hl.as_u16, rotated) }, 0xCF => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 1) }, 0xD0 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 2) }, 0xD1 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 2) }, 0xD2 => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 2) }, 0xD3 => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 2) }, 0xD4 => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 2) }, 0xD5 => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 2) }, 0xD6 => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 2); self.memory.set(self.state.hl.as_u16, rotated) }, 0xD7 => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 2) }, 0xD8 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 3) }, 0xD9 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 3) }, 0xDA => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 3) }, 0xDB => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 3) }, 0xDC => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 3) }, 0xDD => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 3) }, 0xDE => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 3); self.memory.set(self.state.hl.as_u16, rotated) }, 0xDF => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 3) }, 0xE0 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 4) }, 0xE1 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 4) }, 0xE2 => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 4) }, 0xE3 => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 4) }, 0xE4 => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 4) }, 0xE5 => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 4) }, 0xE6 => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 4); self.memory.set(self.state.hl.as_u16, rotated) }, 0xE7 => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 4) }, 0xE8 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 5) }, 0xE9 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 5) }, 0xEA => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 5) }, 0xEB => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 5) }, 0xEC => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 5) }, 0xED => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 5) }, 0xEE => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 5); self.memory.set(self.state.hl.as_u16, rotated) }, 0xEF => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 5) }, 0xF0 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 6) }, 0xF1 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 6) }, 0xF2 => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 6) }, 0xF3 => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 6) }, 0xF4 => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 6) }, 0xF5 => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 6) }, 0xF6 => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 6); self.memory.set(self.state.hl.as_u16, rotated) }, 0xF7 => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 6) }, 0xF8 => unsafe { self.state.bc.as_u8s.left = set(self.state.bc.as_u8s.left, 7) }, 0xF9 => unsafe { self.state.bc.as_u8s.right = set(self.state.bc.as_u8s.right, 7) }, 0xFA => unsafe { self.state.de.as_u8s.left = set(self.state.de.as_u8s.left, 7) }, 0xFB => unsafe { self.state.de.as_u8s.right = set(self.state.de.as_u8s.right, 7) }, 0xFC => unsafe { self.state.hl.as_u8s.left = set(self.state.hl.as_u8s.left, 7) }, 0xFD => unsafe { self.state.hl.as_u8s.right = set(self.state.hl.as_u8s.right, 7) }, 0xFE => unsafe { let rotated = set(self.memory.get(self.state.hl.as_u16), 7); self.memory.set(self.state.hl.as_u16, rotated) }, 0xFF => unsafe { self.state.af.as_u8s.left = set(self.state.af.as_u8s.left, 7) }, } } 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 rlc(&mut self, byte: u8) -> u8 { self.rotate_c(byte, Direction::Left) } fn rrc(&mut self, byte: u8) -> u8 { self.rotate_c(byte, Direction::Right) } fn rl(&mut self, byte: u8) -> u8 { self.rotate(byte, Direction::Left) } fn rr(&mut self, byte: u8) -> u8 { self.rotate(byte, Direction::Right) } fn rotate_c(&mut self, byte: u8, direction: Direction) -> u8 { let (mut rotated, carry) = rotate(byte, &direction); if carry { rotated += get_rotation_carry(&direction); self.set_flag(FLAGS::C); } return rotated; } fn rotate(&mut self, byte: u8, direction: Direction) -> u8 { let old_carry = self.get_flag(FLAGS::C); let (mut rotated, carry) = rotate(byte, &direction); if old_carry > 0 { rotated += get_rotation_carry(&direction); } if carry { self.set_flag(FLAGS::C); } return rotated; } fn sla(&mut self, byte: u8) -> u8 { self.shift(byte, Direction::Left) } fn sra(&mut self, byte: u8) -> u8 { let b = get_bit(byte, 7); let val = self.shift(byte, Direction::Right); if b { val + 0b10000000 } else { val } } fn srl(&mut self, byte: u8) -> u8 { self.shift(byte, Direction::Right) } fn shift(&mut self, byte: u8, direction: Direction) -> u8 { let (rotated, carry) = rotate(byte, &direction); if carry { self.set_flag(FLAGS::C); } return rotated; } fn bit(&mut self, byte: u8, bit: u8) { self.set_or_clear_flag(FLAGS::Z, !get_bit(byte, bit)); } 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.wrapping_sub(1), register.as_u8s.right); self.memory .set(address.wrapping_sub(2), register.as_u8s.left); self.state.sp.as_u16 = address.wrapping_sub(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(0x2); Register { as_u8s: Inner { left: self.memory.get(address), right: self.memory.get(address.wrapping_add(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 { if get_bit(self.state.af.as_u8s.right, flag as u8) { 0x1 } else { 0x0 } } } fn set_flag(&mut self, flag: FLAGS) { if flag == FLAGS::Z { println!("setting z flag"); } unsafe { println!( "setting flag: currently {0:#b} / {0:#X}", self.state.af.as_u8s.right ); self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitor(1 << flag as u8); println!( " now {0:#b} / {0:#X}", self.state.af.as_u8s.right ); }; } 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); }; } fn set_or_clear_flag(&mut self, flag: FLAGS, state: bool) { if state { self.set_flag(flag) } else { self.clear_flag(flag) } } fn add_u8s(&mut self, first: u8, second: u8) -> u8 { let (result, carry) = first.overflowing_add(second); self.clear_flag(FLAGS::N); self.set_or_clear_flag(FLAGS::C, carry); self.set_or_clear_flag(FLAGS::Z, result == 0x0); self.set_or_clear_flag( FLAGS::H, (((first & 0xF).wrapping_add(second & 0xF)) & 0x10) == 0x10, ); return result; } fn add_u16s(&mut self, first: u16, second: u16) -> u16 { let (result, carry) = first.overflowing_add(second); self.clear_flag(FLAGS::N); self.set_or_clear_flag(FLAGS::C, carry); self.set_or_clear_flag(FLAGS::Z, result == 0x0); self.set_or_clear_flag( FLAGS::H, (((first & 0xFFF).wrapping_add(second & 0xFFF)) & 0x1000) == 0x1000, ); return result; } fn sub_u8s(&mut self, first: u8, second: u8) -> u8 { let (result, carry) = first.overflowing_sub(second); self.set_flag(FLAGS::N); self.set_or_clear_flag(FLAGS::C, carry); self.set_or_clear_flag(FLAGS::Z, result == 0x0); self.set_or_clear_flag( FLAGS::H, (((first & 0xF).wrapping_sub(second & 0xF)) & 0x10) == 0x10, ); return result; } fn sub_u16s(&mut self, first: u16, second: u16) -> u16 { let (result, carry) = first.overflowing_sub(second); self.set_flag(FLAGS::N); self.set_or_clear_flag(FLAGS::C, carry); self.set_or_clear_flag(FLAGS::Z, result == 0x0); self.set_or_clear_flag( FLAGS::H, (((first & 0xFFF).wrapping_sub(second & 0xFFF)) & 0x1000) == 0x1000, ); return result; } } fn undefined(opcode: u8) { panic!("Undefined behaviour: opcode {:#X}", opcode); } fn as_signed(unsigned: u8) -> i8 { unsafe { return transmute(unsigned); } } fn get_bit(byte: u8, flag: u8) -> bool { let mask = 1 << flag; let got = byte & mask; return got > 0x0; } fn rotate(byte: u8, direction: &Direction) -> (u8, bool) { match direction { Direction::Left => { let carry = get_bit(byte, 7); let r = byte << 1; return (r, carry); } Direction::Right => { let carry = get_bit(byte, 0); let r = byte >> 1; return (r, carry); } } } fn get_rotation_carry(direction: &Direction) -> u8 { match direction { Direction::Left => 0b1, Direction::Right => 0b10000000, } } fn swap_nibbles(byte: u8) -> u8 { (byte & 0x0F) << 4 | (byte & 0xF0) >> 4 } fn res(byte: u8, bit: u8) -> u8 { byte & !(1 << bit) } fn set(byte: u8, bit: u8) -> u8 { byte | (1 << bit) }