use super::interconnect; //const REG_B: usize = 0; //const REG_C: usize = 1; //const REG_D: usize = 2; //const REG_E: usize = 3; //const REG_H: usize = 4; //const REG_L: usize = 5; const REG_A: usize = 6; const REG_N_B: usize = 0; const REG_N_C: usize = 1; const REG_N_D: usize = 2; const REG_N_E: usize = 3; const REG_N_H: usize = 4; const REG_N_L: usize = 5; const REG_N_HL: usize = 6; const REG_N_A: usize = 7; const REG_N_F: usize = 8; const REG_NAMES: [&'static str; 9] = ["B", "C", "D", "E", "H", "L", "(HL)", "A", "F"]; const FLAG_Z: u8 = 1 << 7; const FLAG_N: u8 = 1 << 6; const FLAG_H: u8 = 1 << 5; const FLAG_C: u8 = 1 << 4; pub struct CPU { // Registers: B, C, D, E, H, L, A regs: [u8; 7], flags: u8, ip: u16, sp: u16, interconnect: interconnect::Interconnect, ime: bool, debug: bool, halted: bool, } fn to_u16(bytes: Box<[u8]>) -> u16 { (bytes[1] as u16) << 8 | (bytes[0] as u16) } impl CPU { pub fn new(interconnect: interconnect::Interconnect) -> CPU { CPU { flags: 0, regs: [0, 0, 0, 0, 0, 0, 0], ip: 0, sp: 0xFFFE, interconnect: interconnect, ime: false, // Is this correct? debug: false, halted: false, } } #[inline] fn read_byte(&self, addr: u16) -> u8 { self.interconnect.read_byte(addr) } #[inline] fn load_args(&mut self, num_args: u8) -> Box<[u8]> { let mut args = Vec::new(); for i in 0..num_args { args.push(self.read_byte(self.ip + i as u16)); } self.ip += num_args as u16; args.into_boxed_slice() } #[inline] fn set_8bit_reg(&mut self, reg_id: usize, value: u8) { // Make sure that we skip the (HL) part. if reg_id == REG_N_A { self.regs[REG_A] = value; } else if reg_id == REG_N_F { self.flags = value & 0xF0; } else if reg_id == REG_N_HL { let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, value); } else { self.regs[reg_id] = value; } } #[inline] fn get_8bit_reg(&self, reg_id: usize) -> u8 { // Make sure that we skip the (HL) part. if reg_id == REG_N_A { self.regs[REG_A] } else if reg_id == REG_N_F { self.flags } else if reg_id == REG_N_HL { let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.read_byte(addr) } else { self.regs[reg_id] } } #[inline] fn adc_r(&mut self, val: u8) { // Passes the test let old: u8 = self.regs[REG_A]; let mut new: u8 = old; let c: u8; if self.flags & FLAG_C == FLAG_C { c = 1; } else { c = 0; } new = new.wrapping_add(val); new = new.wrapping_add(c); self.regs[REG_A] = new; self.clear_flag(FLAG_N); self.set_clear_flag(FLAG_Z, new == 0); self.set_clear_flag(FLAG_C, ((val + c) > 0 && new < old) || (c == 1 && new == old)); self.set_clear_flag(FLAG_H, ((old & 0x0F) + (val & 0x0F) + c) > 0x0F); } #[inline] fn add_r(&mut self, val: u8) { // Passes the test let old: u8 = self.regs[REG_A]; let new: u8 = old.wrapping_add(val); let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16); self.regs[REG_A] = new; self.clear_flag(FLAG_N); self.set_clear_flag(FLAG_Z, new == 0); self.set_clear_flag(FLAG_C, val > 0 && new < old); self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10); } #[inline] fn sbc_r(&mut self, val: u8) { // Passes the test let old: u8 = self.regs[REG_A]; let mut new: u8 = old as u8; let c: u8; if self.flags & FLAG_C == FLAG_C { c = 1; } else { c = 0; } new = new.wrapping_sub(val); new = new.wrapping_sub(c); self.regs[REG_A] = new; self.set_flag(FLAG_N); self.set_clear_flag(FLAG_Z, new == 0); self.set_clear_flag(FLAG_C, new > old || (new == old && c == 1)); self.set_clear_flag(FLAG_H, ((old & 0x0F) - (val & 0x0F) - c) > 0x0F); } #[inline] fn sub_r(&mut self, val: u8) { // Passes the test let old: u8 = self.regs[REG_A]; let new: u8 = old.wrapping_sub(val); let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16); self.regs[REG_A] = new; self.set_flag(FLAG_N); self.set_clear_flag(FLAG_Z, new == 0); self.set_clear_flag(FLAG_C, new > old); self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10); } #[inline] fn cp_r(&mut self, val: u8) { // Passes the test let old: u8 = self.regs[REG_A]; let new: u8 = old.wrapping_sub(val); let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16); self.set_flag(FLAG_N); self.set_clear_flag(FLAG_Z, new == 0); self.set_clear_flag(FLAG_C, new > old); self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10); } #[inline] fn run_prefix_instruction(&mut self) { let instruction = self.read_byte(self.ip); self.ip += 1; match instruction { 0x00 ... 0x07 => { let reg_id = (instruction - 0x00) as usize; let val = self.get_8bit_reg(reg_id); if self.debug { println!("RLC {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_C, val & 0x80 == 80); if val & 0x80 == 0x80 { self.set_8bit_reg(reg_id, val << 1 | 1); } else { self.set_8bit_reg(reg_id, val << 1); } self.set_clear_flag(FLAG_Z, val == 0); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); }, 0x08 ... 0x0F => { let reg_id = (instruction - 0x08) as usize; let val = self.get_8bit_reg(reg_id); if self.debug { println!("RRC {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_C, val & 1 == 1); if val & 1 > 0 { self.set_8bit_reg(reg_id, val >> 1 | 0x80); } else { self.set_8bit_reg(reg_id, val >> 1); } self.set_clear_flag(FLAG_Z, val == 0); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); }, 0x10 ... 0x17 => { let reg_id = (instruction - 0x10) as usize; let val = self.get_8bit_reg(reg_id); if self.debug { println!("RL {}", REG_NAMES[reg_id]); } let carry = self.flags & FLAG_C > 0; self.set_clear_flag(FLAG_C, val & 0x80 == 0x80); if !carry { self.set_8bit_reg(reg_id, val << 1); } else { self.set_8bit_reg(reg_id, val << 1 | 1); } self.clear_flag(FLAG_Z); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); }, 0x18 ... 0x1F => { // RR let reg_id = (instruction - 0x18) as usize; let val = self.get_8bit_reg(reg_id); if self.debug { println!("RR {}", REG_NAMES[reg_id]); } let carry = self.flags & FLAG_C > 0; self.set_clear_flag(FLAG_C, val & 1 == 1); if !carry { self.set_8bit_reg(reg_id, val >> 1); } else { self.set_8bit_reg(reg_id, val >> 1 | 0x80); } self.clear_flag(FLAG_Z); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); }, 0x20 ... 0x27 => { let reg_id = (instruction - 0x20) as usize; if self.debug { println!("SLA {}", REG_NAMES[reg_id]); } let v: u8 = self.get_8bit_reg(reg_id); self.set_clear_flag(FLAG_C, v & 0x80 > 0); self.set_8bit_reg(reg_id, v << 1); }, 0x28 ... 0x2F => { let reg_id = (instruction - 0x28) as usize; if self.debug { println!("SRA {}", REG_NAMES[reg_id]); } let v: u8 = self.get_8bit_reg(reg_id); self.set_clear_flag(FLAG_C, v & 1 > 0); self.set_8bit_reg(reg_id, v >> 1 | v & 0x80); }, 0x30 ... 0x37 => { let reg_id = (instruction - 0x30) as usize; if self.debug { println!("SWAP {}", REG_NAMES[reg_id]); } let v: u8 = self.get_8bit_reg(reg_id); self.set_8bit_reg(reg_id, v << 4 | v >> 4); }, 0x38 ... 0x3F => { let reg_id = (instruction - 0x38) as usize; if self.debug { println!("SRL {}", REG_NAMES[reg_id]); } let v: u8 = self.get_8bit_reg(reg_id); self.set_8bit_reg(reg_id, v >> 1); self.set_clear_flag(FLAG_C, v & 1 == 1); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); self.set_clear_flag(FLAG_Z, (v & 0xFE) == 0); }, // Bits 0x40 ... 0x47 => { // Test 0th bit let reg_id = (instruction - 0x40) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 0, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 0) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } 0x48 ... 0x4F => { // Test 1th bit let reg_id = (instruction - 0x48) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 1, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 1) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } 0x50 ... 0x57 => { // Test 2th bit let reg_id = (instruction - 0x50) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 2, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 2) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } 0x58 ... 0x5F => { // Test 3th bit let reg_id = (instruction - 0x58) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 3, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 3) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } 0x60 ... 0x67 => { // Test 4th bit let reg_id = (instruction - 0x60) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 4, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 4) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } 0x68 ... 0x6F => { // Test 5th bit let reg_id = (instruction - 0x68) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 5, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 5) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } 0x70 ... 0x77 => { // Test 6th bit let reg_id = (instruction - 0x70) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 6, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 6) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } 0x78 ... 0x7F => { // Test 7th bit let reg_id = (instruction - 0x78) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("BIT 7, {}", REG_NAMES[reg_id]); } self.set_clear_flag(FLAG_Z, reg_content & (1 << 7) == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); } // Reset bits 0x80 ... 0x87 => { // Reset 0th bit let reg_id = (instruction - 0x80) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 0, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 0)); } 0x88 ... 0x8F => { // Reset 1th bit let reg_id = (instruction - 0x88) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 1, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 1)); } 0x90 ... 0x97 => { // Reset 2nd bit let reg_id = (instruction - 0x90) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 2, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 2)); } 0x98 ... 0x9F => { // Reset 3th bit let reg_id = (instruction - 0x98) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 3, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 3)); } 0xA0 ... 0xA7 => { // Reset 4th bit let reg_id = (instruction - 0xA0) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 4, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 4)); } 0xA8 ... 0xAF => { // Reset 5th bit let reg_id = (instruction - 0xA8) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 5, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 5)); } 0xB0 ... 0xB7 => { // Reset 6th bit let reg_id = (instruction - 0xB0) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 6, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 6)); } 0xB8 ... 0xBF => { // Reset 7th bit let reg_id = (instruction - 0xB8) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("RES 7, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content & !(1 << 7)); } // Set bits 0xC0 ... 0xC7 => { // Set 0th bit let reg_id = (instruction - 0xC0) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 0, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 0)); } 0xC8 ... 0xCF => { // Set 1th bit let reg_id = (instruction - 0xC8) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 1, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 1)); } 0xD0 ... 0xD7 => { // Set 2nd bit let reg_id = (instruction - 0xD0) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 2, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 2)); } 0xD8 ... 0xDF => { // Set 3th bit let reg_id = (instruction - 0xD8) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 3, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 3)); } 0xE0 ... 0xE7 => { // Set 4th bit let reg_id = (instruction - 0xE0) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 4, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 4)); } 0xE8 ... 0xEF => { // Set 5th bit let reg_id = (instruction - 0xE8) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 5, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 5)); } 0xF0 ... 0xF7 => { // Set 6th bit let reg_id = (instruction - 0xF0) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 6, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 6)); } 0xF8 ... 0xFF => { // Set 7th bit let reg_id = (instruction - 0xF8) as usize; let reg_content = self.get_8bit_reg(reg_id); if self.debug { println!("SET 7, {}", REG_NAMES[reg_id]); } self.set_8bit_reg(reg_id, reg_content | (1 << 7)); } _ => { panic!("Unsupported prefix instruction: {:x}", instruction); } } } #[inline] fn get_pair_value(&self, a: usize, b: usize) -> u16 { (self.get_8bit_reg(a) as u16) << 8 | self.get_8bit_reg(b) as u16 } #[inline] fn set_pair_value(&mut self, a: usize, b: usize, value: u16) { self.set_8bit_reg(a, (value >> 8) as u8); self.set_8bit_reg(b, value as u8); } fn dump_stack(&self) { for i in self.sp .. 0xFFFE { println!("[{:#04X}]: {:#02X}", i, self.interconnect.read_byte(i)); } } #[inline] fn call(&mut self, dst: u16) { let ip = self.ip; self.push(ip); //self.dump_stack(); self.ip = dst; } #[inline] fn call_condition(&mut self, cond_str: String, cond: bool) -> u8 { let dst = to_u16(self.load_args(2)); if self.debug { println!("CALL {} {:04X}", cond_str, dst); } if cond { self.call(dst); 24 } else { 12 } } #[inline] fn ret_condition(&mut self, cond_str: String, cond: bool) -> u8 { if self.debug { println!("RET {}", cond_str); } if cond { self.ret(); 20 } else { 8 } } #[inline] fn jmp_r(&mut self, addr: u8) { let off: i8 = addr as i8; if off < 0 { self.ip -= (-off) as u16; } else { self.ip += off as u16; } } #[inline] fn jmp_r_condition(&mut self, cond_str: String, cond: bool) -> u8 { let t = self.load_args(1)[0]; if self.debug { println!("JR {} {:02X}", cond_str, t); } if cond { self.jmp_r(t); 12 } else { 8 } } #[inline] fn jmp_p(&mut self, addr: u16) { self.ip = addr; } #[inline] fn jmp_p_condition(&mut self, cond_str: String, cond: bool) -> u8 { let t = to_u16(self.load_args(2)); if self.debug { println!("JP {} {:04X}", cond_str, t); } if cond { self.jmp_p(t); 12 } else { 8 } } #[inline] fn rst(&mut self, val: u8) -> u8 { // Make sure this is correct. if self.debug || true { println!("RST {:02X}", val); } self.call(val as u16); 16 } #[inline] fn pop_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("POP {}{}", REG_NAMES[r1], REG_NAMES[r2]); } let val: u16 = self.pop(); self.set_pair_value(r1, r2, val); 12 } #[inline] fn push_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("PUSH {}{}", REG_NAMES[r1], REG_NAMES[r2]); } let val: u16 = self.get_pair_value(r1, r2); self.push(val); 16 } #[inline] fn dec_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("DEC {}{}", REG_NAMES[r1], REG_NAMES[r2]); } let v = self.get_pair_value(r1, r2); let v = v.wrapping_sub(1); self.set_pair_value(r1, r2, v); 8 } #[inline] fn inc_rr(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("INC {}{}", REG_NAMES[r1], REG_NAMES[r2]); } let v = self.get_pair_value(r1, r2); let v = v.wrapping_add(1); self.set_pair_value(r1, r2, v); 8 } #[inline] fn push(&mut self, val: u16) { self.interconnect.write_word(self.sp - 1, val); self.sp -= 2; } #[inline] fn pop(&mut self) -> u16 { let v: u16 = self.interconnect.read_word(self.sp + 1); self.sp += 2; v } #[inline] fn ld_r_r(&mut self, reg_dst: usize, reg_src: usize) -> u8 { if self.debug { println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src]) } let sv = self.get_8bit_reg(reg_src); self.set_8bit_reg(reg_dst, sv); if reg_dst == REG_N_HL || reg_src == REG_N_HL { 8 } else { 4 } } #[inline] fn ld_r_v(&mut self, r: usize) -> u8 { let val: u8 = self.load_args(1)[0]; if self.debug { println!("LD {}, {:02X}", REG_NAMES[r], val); } self.set_8bit_reg(r, val); if r == REG_N_HL { 12 } else { 8 } } #[inline] fn ld_rr_vv(&mut self, r1: usize, r2: usize) -> u8 { let val: u16 = to_u16(self.load_args(2)); if self.debug { println!("LD {}{}, {:04X}", REG_NAMES[r1], REG_NAMES[r2], val); } self.set_pair_value(r1, r2, val); 12 } #[inline] fn reg_inc(&mut self, reg_id: usize) -> u8 { if self.debug { println!("INC {}", REG_NAMES[reg_id]); } let val = self.get_8bit_reg(reg_id).wrapping_add(1); self.set_8bit_reg(reg_id, val); self.set_clear_flag(FLAG_Z, val == 0); // self.set_clear_flag(FLAG_C, val == 0); self.clear_flag(FLAG_N); 4 } #[inline] fn add_rr_rr(&mut self, r1: usize, r2: usize, r3: usize, r4: usize) -> u8 { if self.debug { println!("ADD {}{}, {}{}", REG_NAMES[r1], REG_NAMES[r2], REG_NAMES[r3], REG_NAMES[r4]); } let val1 = self.get_pair_value(r1, r2); let val2 = self.get_pair_value(r3, r4); let res = val1.wrapping_add(val2); self.set_pair_value(r1, r2, res); // We need to update the flags self.clear_flag(FLAG_N); // Some magic formula self.set_clear_flag(FLAG_C, val1 as usize + val2 as usize & 0x10000 == 0x10000); self.set_clear_flag(FLAG_H, (val1 ^ val2 ^ res) & 0x1000 == 0x1000); 8 } #[inline] fn reg_dec(&mut self, reg_id: usize) -> u8 { if self.debug { println!("DEC {}", REG_NAMES[reg_id]); } let val = self.get_8bit_reg(reg_id).wrapping_sub(1); self.set_8bit_reg(reg_id, val); self.set_clear_flag(FLAG_Z, val == 0); // self.set_clear_flag(FLAG_C, val == 255); self.set_flag(FLAG_N); 4 } #[inline] fn ld_dref_rr_a(&mut self, r1: usize, r2: usize) -> u8 { if self.debug { println!("LD ({}{}), A", REG_NAMES[r1], REG_NAMES[r2]); } let dst: u16 = self.get_pair_value(r1, r2); let val: u8 = self.get_8bit_reg(REG_N_A); self.interconnect.write_byte(dst, val); 8 } #[inline] fn set_flag(&mut self, flag: u8) { self.flags |= flag; } #[inline] fn clear_flag(&mut self, flag: u8) { self.flags &= !flag; } #[inline] fn set_clear_flag(&mut self, flag: u8, dep: bool) { if dep { self.set_flag(flag); } else { self.clear_flag(flag); } } #[inline] fn int_(&mut self, val: u8){ if self.debug { println!("INT {:02X}", val); } // TODO: Clear interrupt register self.ime = false; self.call(val as u16); } #[inline] fn ret(&mut self) { let new_ip: u16 = self.pop(); //self.dump_stack(); self.ip = new_ip; } #[inline] fn reti(&mut self) -> u8 { self.ret(); self.ime = true; 16 } #[inline] fn handle_interrupt(&mut self, offset: u8, flag: u8) { // Remove interrupt requested flag let new_flag = self.interconnect.read_byte(0xFF0F) & !flag; self.interconnect.write_byte(0xFF0F, new_flag); // Run interrupt handler self.int_(offset); self.halted = false; } pub fn run_instruction(&mut self) { // self.debug = !self.interconnect.is_boot_rom(); // Check for interrupts. // TODO: Make this right if self.ime { // read pending interrupts let pending = self.interconnect.read_byte(0xFF0F); let enabled = self.interconnect.read_byte(0xFFFF); let e_pending = pending & enabled; if e_pending & interconnect::INTERRUPT_DISPLAY_VBLANK > 0 { // println!("Handling vblank interrupt"); self.handle_interrupt(0x40, interconnect::INTERRUPT_DISPLAY_VBLANK); } else if e_pending & interconnect::INTERRUPT_DISPLAY_STAT > 0 { println!("Handling display stat interrupt"); self.handle_interrupt(0x48, interconnect::INTERRUPT_DISPLAY_STAT); } else if e_pending & interconnect::INTERRUPT_TIMER_OVERFLOW > 0{ println!("Handling timer interrupt"); self.handle_interrupt(0x50, interconnect::INTERRUPT_TIMER_OVERFLOW); } else if e_pending > 0 { panic!("Unknown pending interrupt: {:02X}", e_pending); } } let mut cycles: u8 = 1; if !self.halted { // We need to double-check the flags let instruction = self.read_byte(self.ip); if self.debug { print!("{:#04x}: [SP: {:#04X}] i={:02X}. ", &self.ip, &self.sp, &instruction); for i in 0 .. 6 { print!("{}: {:02X} ", REG_NAMES[i], self.get_8bit_reg(i)); } print!("A: {:02X} ", self.regs[REG_A]); print!("I: {:02X} ", self.interconnect.read_byte(0xFFFF)); // Flags print!("Z={} ", self.flags & FLAG_Z != 0); print!("N={} ", self.flags & FLAG_N != 0); print!("H={} ", self.flags & FLAG_H != 0); print!("C={} ", self.flags & FLAG_C != 0); } self.ip = self.ip.wrapping_add(1); cycles = match instruction { 0x00 => { if self.debug { println!("NOP"); } 4 }, 0x01 => self.ld_rr_vv(REG_N_B, REG_N_C), 0x02 => self.ld_dref_rr_a(REG_N_B, REG_N_C), 0x03 => self.inc_rr(REG_N_B, REG_N_C), 0x04 => self.reg_inc(REG_N_B), 0x05 => self.reg_dec(REG_N_B), 0x06 => self.ld_r_v(REG_N_B), 0x07 => { if self.debug { println!("RLCA"); } let val = self.regs[REG_A]; let carry = val & 0x80 == 0x80; self.set_clear_flag(FLAG_C, carry); if !carry { self.regs[REG_A] = self.regs[REG_A] << 1; } else { self.regs[REG_A] = self.regs[REG_A] << 1 | 1; } self.clear_flag(FLAG_Z); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 4 } 0x08 => { let a: u16 = to_u16(self.load_args(2)); if self.debug{ println!("LD ({:04X}), sp", a); } self.interconnect.write_word(a, self.sp); 20 } 0x09 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_B, REG_N_C), 0x0A => { if self.debug { println!("LD A, (BC)"); } self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_N_B, REG_N_C)); 8 }, 0x0B => self.dec_rr(REG_N_B, REG_N_C), 0x0C => self.reg_inc(REG_N_C), 0x0D => self.reg_dec(REG_N_C), 0x0E => self.ld_r_v(REG_N_C), 0x0F => { if self.debug { println!("RRCA"); } let val = self.regs[REG_A]; self.set_clear_flag(FLAG_C, val & 1 == 1); if val & 1 == 0 { self.regs[REG_A] = self.regs[REG_A] >> 1; } else { self.regs[REG_A] = self.regs[REG_A] >> 1 | 0x80; } self.clear_flag(FLAG_Z); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 4 } 0x10 => panic!("STOP 0 {:02X} not implemented.", self.load_args(1)[0]), 0x11 => self.ld_rr_vv(REG_N_D, REG_N_E), 0x12 => self.ld_dref_rr_a(REG_N_D, REG_N_E), 0x13 => self.inc_rr(REG_N_D, REG_N_E), 0x14 => self.reg_inc(REG_N_D), 0x15 => self.reg_dec(REG_N_D), 0x16 => self.ld_r_v(REG_N_D), 0x17 => { if self.debug { println!("RLA"); } let carry = self.flags & FLAG_C > 0; let val = self.regs[REG_A]; self.set_clear_flag(FLAG_C, val & 0x80 == 0x80); if !carry { self.regs[REG_A] = self.regs[REG_A] << 1; } else { self.regs[REG_A] = self.regs[REG_A] << 1 | 1; } self.clear_flag(FLAG_Z); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 4 }, 0x18 => { let dst = self.load_args(1)[0]; self.jmp_r(dst); 12 }, 0x19 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_D, REG_N_E), 0x1A => { if self.debug { println!("LD A, (DE)"); } self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_N_D, REG_N_E)); 8 }, 0x1B => self.dec_rr(REG_N_D, REG_N_E), 0x1C => self.reg_inc(REG_N_E), 0x1D => self.reg_dec(REG_N_E), 0x1E => self.ld_r_v(REG_N_E), 0x1F => { if self.debug { println!("RRA"); } let carry = self.flags & FLAG_C > 0; let val = self.regs[REG_A]; self.set_clear_flag(FLAG_C, val & 1 == 1); if !carry { self.regs[REG_A] = self.regs[REG_A] >> 1; } else { self.regs[REG_A] = self.regs[REG_A] >> 1 | 0x80; } self.clear_flag(FLAG_Z); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 4 }, 0x20 => { let c = self.flags & FLAG_Z == 0; self.jmp_r_condition("NZ".to_owned(), c) } 0x21 => self.ld_rr_vv(REG_N_H, REG_N_L), 0x22 => { if self.debug { println!("LD (HL+), A"); } let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, self.regs[REG_A]); self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_add(1)); 8 }, 0x23 => self.inc_rr(REG_N_H, REG_N_L), 0x24 => self.reg_inc(REG_N_H), 0x25 => self.reg_dec(REG_N_H), 0x26 => self.ld_r_v(REG_N_H), 0x27 => { // Logic copied from some other emulator let mut v = self.regs[REG_A] as u16; if self.debug { println!("DAA"); } if self.flags & FLAG_N == 0 { // Lower nibble if self.flags & FLAG_H == FLAG_H || (v & 0xF) > 9 { v += 0x06; } // Higher nibble if self.flags & FLAG_C == FLAG_C || v > 0x9F { v += 0x60; } } else { // Lower nibble if self.flags & FLAG_H == FLAG_H { v = v.wrapping_sub(6) & 0xFF; } // Higher nibble if self.flags & FLAG_C == FLAG_C { v = v.wrapping_sub(0x60); } } self.clear_flag(FLAG_H); self.set_clear_flag(FLAG_C, (v & 0x100) == 0x100); self.set_clear_flag(FLAG_Z, v as u8 == 0); self.regs[REG_A] = v as u8; 4 }, 0x28 => { let c = self.flags & FLAG_Z == FLAG_Z; self.jmp_r_condition("Z".to_owned(), c) }, 0x29 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_H, REG_N_L), 0x2A => { if self.debug { println!("LD A, (HL+)"); } let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.regs[REG_A] = self.interconnect.read_byte(addr); self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_add(1)); 8 }, 0x2B => self.dec_rr(REG_N_H, REG_N_L), 0x2C => self.reg_inc(REG_N_L), 0x2D => self.reg_dec(REG_N_L), 0x2E => self.ld_r_v(REG_N_L), 0x2F => { if self.debug { println!("CPL"); } self.regs[REG_A] = !self.regs[REG_A]; self.set_flag(FLAG_N); self.set_flag(FLAG_H); 4 }, 0x30 => { let c = self.flags & FLAG_C == 0; self.jmp_r_condition("NC".to_owned(), c) }, 0x31 => { let args = self.load_args(2); self.sp = to_u16(args); if self.debug { println!("LD SP, {:04x}", self.sp); } 12 }, 0x32 => { if self.debug { println!("LD (HL-), A"); } let addr = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, self.regs[REG_A]); self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_sub(1)); 8 }, 0x33 => { if self.debug { println!("INC SP"); } let sp = self.sp.wrapping_add(1); self.sp = sp; 8 } 0x34 => self.reg_inc(REG_N_HL), 0x35 => self.reg_dec(REG_N_HL), 0x36 => self.ld_r_v(REG_N_HL), 0x37 => { if self.debug { println!("SCF"); } self.set_flag(FLAG_C); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 4 }, 0x38 => { let c = self.flags & FLAG_C == FLAG_C; self.jmp_r_condition("C".to_owned(), c) }, 0x39 => { if self.debug { println!("ADD HL, SP"); } let sp = self.sp; let old = self.get_pair_value(REG_N_H, REG_N_L); let v = old.wrapping_add(sp); self.set_pair_value(REG_N_H, REG_N_L, v); self.clear_flag(FLAG_N); self.set_clear_flag(FLAG_C, old > v && sp > 0); self.set_clear_flag(FLAG_H, ((old & 0xFFF) + (sp & 0xFFF)) > 0xFFF); 8 }, 0x3A => { if self.debug { println!("LD A, (HL-)"); } let mut addr = self.get_pair_value(REG_N_H, REG_N_L); self.regs[REG_A] = self.interconnect.read_byte(addr); self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_sub(1)); 8 } 0x3B => { if self.debug { println!("DEC SP"); } let sp = self.sp.wrapping_sub(1); self.sp = sp; 8 } 0x3C => self.reg_inc(REG_N_A), 0x3D => self.reg_dec(REG_N_A), 0x3E => self.ld_r_v(REG_N_A), 0x3F => { if self.debug { println!("CCF"); } self.flags ^= FLAG_C; self.clear_flag(FLAG_N); 4 } // LDs 0x40 ... 0x47 => self.ld_r_r(REG_N_B, (instruction - 0x40) as usize), 0x48 ... 0x4F => self.ld_r_r(REG_N_C, (instruction - 0x48) as usize), 0x50 ... 0x57 => self.ld_r_r(REG_N_D, (instruction - 0x50) as usize), 0x58 ... 0x5F => self.ld_r_r(REG_N_E, (instruction - 0x58) as usize), 0x60 ... 0x67 => self.ld_r_r(REG_N_H, (instruction - 0x60) as usize), 0x68 ... 0x6F => self.ld_r_r(REG_N_L, (instruction - 0x68) as usize), 0x70 ... 0x75 | 0x77 => self.ld_r_r(REG_N_HL, (instruction - 0x70) as usize), 0x78 ... 0x7F => self.ld_r_r(REG_N_A, (instruction - 0x78) as usize), // HALT 0x76 => { if self.debug { println!("HALT"); } self.halted = true; 4 }, // ADD 0x80 ... 0x87 => { let reg_id = (instruction - 0x80) as usize; if self.debug { println!("ADD {}", REG_NAMES[reg_id]); } let v = self.get_8bit_reg(reg_id); self.add_r(v); 4 } // ADC 0x88 ... 0x8F => { let reg_id = (instruction - 0x88) as usize; if self.debug { println!("ADC {}", REG_NAMES[reg_id]); } let v = self.get_8bit_reg(reg_id); self.adc_r(v); 4 } // SUBs 0x90 ... 0x97 => { let reg_id = (instruction - 0x90) as usize; if self.debug { println!("SUB {}", REG_NAMES[reg_id]); } let r = self.get_8bit_reg(reg_id); self.sub_r(r); 4 } // SBC 0x98 ... 0x9F => { let reg_id = (instruction - 0x98) as usize; if self.debug { println!("SBC {}", REG_NAMES[reg_id]); } let r = self.get_8bit_reg(reg_id); self.sbc_r(r); 4 } // AND 0xA0 ... 0xA7 => { let reg_id = (instruction - 0xA0) as usize; if self.debug { println!("AND {}", REG_NAMES[reg_id]); } self.regs[REG_A] &= self.get_8bit_reg(reg_id); let v = self.regs[REG_A]; self.set_clear_flag(FLAG_Z, v == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); self.clear_flag(FLAG_C); 4 } // XOR 0xA8 ... 0xAF => { let reg_id = (instruction - 0xA8) as usize; if self.debug { println!("XOR {}", REG_NAMES[reg_id]); } self.regs[REG_A] ^= self.get_8bit_reg(reg_id); let v = self.regs[REG_A]; self.set_clear_flag(FLAG_Z, v == 0); self.clear_flag(FLAG_C); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 4 }, // OR 0xB0 ... 0xB7 => { let reg_id = (instruction - 0xB0) as usize; if self.debug { println!("OR {}", REG_NAMES[reg_id]); } self.regs[REG_A] |= self.get_8bit_reg(reg_id); let v = self.regs[REG_A]; self.set_clear_flag(FLAG_Z, v == 0); self.clear_flag(FLAG_C); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 4 } // CP 0xB8 ... 0xBF => { let reg_id = (instruction - 0xB8) as usize; if self.debug { println!("CP {}", REG_NAMES[reg_id]); } let v = self.get_8bit_reg(reg_id); self.cp_r(v); 4 }, 0xC0 => { let c = self.flags & FLAG_Z == 0; self.ret_condition("NZ".to_owned(), c) }, 0xC1 => self.pop_rr(REG_N_B, REG_N_C), 0xC2 => { let c = self.flags & FLAG_Z == 0; self.jmp_p_condition("NZ".to_owned(), c) }, 0xC3 => { let dst = to_u16(self.load_args(2)); self.jmp_p(dst); 16 }, 0xC4 => { let c = self.flags & FLAG_Z == 0; self.call_condition("NZ".to_owned(), c) } 0xC5 => self.push_rr(REG_N_B, REG_N_C), 0xC6 => { let val = self.load_args(1)[0]; if self.debug { println!("ADD A, {:02X}", val); } self.add_r(val); 8 }, 0xC7 => self.rst(0x00), 0xC8 => { let c = self.flags & FLAG_Z == FLAG_Z; self.ret_condition("Z".to_owned(), c) }, 0xC9 => {self.ret(); 16}, 0xCA => { let c = self.flags & FLAG_Z == FLAG_Z; self.jmp_p_condition("Z".to_owned(), c) } 0xCB => { // Prefix CB. This is annoying. self.run_prefix_instruction(); 12 // TODO: Verify that this is the case for all prefix instructions. }, 0xCC => { let c = self.flags & FLAG_Z == FLAG_Z; self.call_condition("Z".to_owned(), c) }, 0xCD => self.call_condition("".to_owned(), true), 0xCE => { let arg = self.load_args(1)[0]; if self.debug { println!("ADC A, {:02X}", arg); } self.adc_r(arg); 8 }, 0xCF => self.rst(0x08), 0xD0 => { let c = self.flags & FLAG_C == 0; self.ret_condition("NC".to_owned(), c) }, 0xD1 => self.pop_rr(REG_N_D, REG_N_E), 0xD2 => { let c = self.flags & FLAG_C == 0; self.jmp_p_condition("NC".to_owned(), c) } 0xD3 => panic!("NON-EXISTING OPCODE"), 0xD4 => { let c = self.flags & FLAG_C == 0; self.call_condition("NC".to_owned(), c) } 0xD5 => self.push_rr(REG_N_D, REG_N_E), 0xD6 => { let val = self.load_args(1)[0]; if self.debug { println!("SUB {:02X}", val); } self.sub_r(val); 8 }, 0xD7 => self.rst(0x10), 0xD8 => { let c = self.flags & FLAG_C == FLAG_C; self.ret_condition("C".to_owned(), c) }, 0xD9 => self.reti(), 0xDA => { let c = self.flags & FLAG_C == FLAG_C; self.jmp_p_condition("C".to_owned(), c) }, 0xDB => panic!("NON-EXISTING OPCODE"), 0xDC => { let c = self.flags & FLAG_C == FLAG_C; self.call_condition("C".to_owned(), c) } 0xDD => panic!("NON-EXISTING OPCODE"), 0xDE => { let arg = self.load_args(1)[0]; if self.debug { println!("SBC {:02X}", arg); } self.sbc_r(arg); 8 }, 0xDF => self.rst(0x18), 0xE0 => { let args = self.load_args(1); if self.debug { println!("LDH {:02X}, A", args[0]); } self.interconnect.write_byte(0xFF00 + args[0] as u16, self.regs[REG_A]); 12 }, 0xE1 => self.pop_rr(REG_N_H, REG_N_L), 0xE2 => { if self.debug { println!("LD (C), A"); } let addr: u16 = 0xFF00 + self.get_8bit_reg(REG_N_C) as u16; self.interconnect.write_byte(addr, self.regs[REG_A]); 8 }, 0xE3 | 0xE4 => panic!("NON-EXISTING OPCODE"), 0xE5 => self.push_rr(REG_N_H, REG_N_L), 0xE6 => { let val = self.load_args(1)[0]; if self.debug { println!("AND {:02X}", val); } let v = self.regs[REG_A] & val; self.regs[REG_A] = v; self.set_clear_flag(FLAG_Z, v == 0); self.clear_flag(FLAG_N); self.set_flag(FLAG_H); self.clear_flag(FLAG_C); 8 }, 0xE7 => self.rst(0x20), 0xE8 => { let arg = self.load_args(1)[0] as i8; if self.debug { println!("ADD SP, {:02X}", arg); } let t: u16; if arg > 0 { t = self.sp.wrapping_add(arg as u16); } else { t = self.sp.wrapping_sub((-arg) as u16); } let sp = self.sp; self.clear_flag(FLAG_N); self.clear_flag(FLAG_Z); self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ t) & 0x100 == 0x100); self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ t) & 0x10 == 0x10); self.sp = t; 16 } 0xE9 => { if self.debug { println!("JP (HL)"); } self.ip = self.get_pair_value(REG_N_H, REG_N_L); 4 }, 0xEA => { let addr = to_u16(self.load_args(2)); if self.debug{ println!("LD ({:04X}), A", addr); } self.interconnect.write_byte(addr, self.regs[REG_A]); 16 }, 0xEB ... 0xED => panic!("NON-EXISTING OPCODE"), 0xEE => { let arg = self.load_args(1)[0]; if self.debug { println!("XOR {:02X}", arg); } let v = self.regs[REG_A] ^ arg; self.regs[REG_A] = v; self.set_clear_flag(FLAG_Z, v == 0); self.clear_flag(FLAG_H); self.clear_flag(FLAG_C); self.clear_flag(FLAG_N); 8 }, 0xEF => self.rst(0x28), 0xF0 => { let args = self.load_args(1); if self.debug { println!("LDH A, {:02X}", args[0]); } self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + args[0] as u16); 12 }, 0xF1 => self.pop_rr(REG_N_A, REG_N_F), 0xF2 => { if self.debug{ println!("LD A, (C)"); } let addr = 0xFF00 + self.get_8bit_reg(REG_N_C) as u16; self.regs[REG_A] = self.interconnect.read_byte(addr); 8 }, 0xF3 => { if self.debug { println!("DI"); } self.ime = false; 4 }, 0xF4 => panic!("NON-EXISTING OPCODE"), 0xF5 => self.push_rr(REG_N_A, REG_N_F), 0xF6 => { let val = self.load_args(1)[0]; if self.debug { println!("OR {:02X}", val); } let v = self.regs[REG_A] | val; self.regs[REG_A] = v; self.set_clear_flag(FLAG_Z, v == 0); self.clear_flag(FLAG_C); self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); 8 }, 0xF7 => self.rst(0x30), 0xF8 => { let arg = self.load_args(1)[0] as i8; if self.debug { println!("LD HL, SP+{:02X}", arg); } self.clear_flag(FLAG_N); self.clear_flag(FLAG_Z); let sp = self.sp; if arg < 0 { let v: u16 = self.sp.wrapping_sub((-arg) as u16); self.set_pair_value(REG_N_H, REG_N_L, v); self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ v) & 0x100 == 0x100); self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ v) & 0x10 == 0x10); } else { let v: u16 = self.sp.wrapping_add(arg as u16); self.set_pair_value(REG_N_H, REG_N_L, v); self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ v) & 0x100 == 0x100); self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ v) & 0x10 == 0x10); } 12 }, 0xF9 => { if self.debug { println!("LD SP, HL"); } self.sp = self.get_pair_value(REG_N_H, REG_N_L); 8 }, 0xFA => { let addr = to_u16(self.load_args(2)); if self.debug { println!("LD A, ({:04X})", addr); } self.regs[REG_A] = self.interconnect.read_byte(addr); 16 }, 0xFB => { // Enable interrupts - TODO if self.debug { println!("EI"); } self.ime = true; // interrupt master enable 4 }, 0xFC | 0xFD => panic!("NON-EXISTING OPCODE"), 0xFE => { let args = self.load_args(1); if self.debug { println!("CP {:02X}", args[0]); } self.cp_r(args[0]); 8 }, 0xFF => self.rst(0x38), _ => panic!("Unknown instruction: {:02x}", instruction) }; } // self.dump_stack(); self.interconnect.tick(cycles); } }