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, } } fn read_byte(&self, addr: u16) -> u8 { self.interconnect.read_byte(addr) } 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() } 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; } 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; } } 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] } } 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]); } if val & 0x80 == 0x80 { self.set_flag(FLAG_C); 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]); } if val & 1 > 0 { self.set_flag(FLAG_C); 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; if !carry { // No carry before, now we got a carry => set it if val & 0x80 == 0x80 { self.set_flag(FLAG_C); } self.set_8bit_reg(reg_id, val << 1); } else { if val & 0x80 == 0 { self.clear_flag(FLAG_C); } 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; if !carry { // No carry before, now we got a carry => set it if val & 0x80 == 0x80 { self.set_flag(FLAG_C); } self.set_8bit_reg(reg_id, val >> 1); } else { if val & 0x80 == 0 { self.clear_flag(FLAG_C); } self.set_8bit_reg(reg_id, val >> 1 | 1 << 7); } 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 - 0x20) 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); }, 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); }, 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]); } if reg_content & (1 << 0) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } 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]); } if reg_content & (1 << 1) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } 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]); } if reg_content & (1 << 2) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } 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]); } if reg_content & (1 << 3) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } 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]); } if reg_content & (1 << 4) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } 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]); } if reg_content & (1 << 5) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } 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]); } if reg_content & (1 << 6) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } 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]); } if reg_content & (1 << 7) == 0 { self.flags |= FLAG_Z; } else { self.flags &= !FLAG_Z; } } _ => { panic!("Unsupported prefix instruction: {:x}", instruction); } } } 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 } 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)); } } fn call(&mut self, dst: u16) { let ip = self.ip; self.push(ip); //self.dump_stack(); self.ip = dst; } 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 } } 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 } } 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; } } 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 } } fn jmp_p(&mut self, addr: u16) { self.ip = addr; } 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 } } fn rst(&mut self, val: u8) -> u8 { // Make sure this is correct. if self.debug { println!("RST {:02X}", val); } self.call(val as u16); 16 } 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 } 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 } 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 } 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 } fn push(&mut self, val: u16) { self.interconnect.write_word(self.sp - 1, val); self.sp -= 2; } fn pop(&mut self) -> u16 { let v: u16 = self.interconnect.read_word(self.sp + 1); self.sp += 2; v } 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 } } 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 } } 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 } 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 } fn add_rr_rr(&mut self, r1: usize, r2: usize, r3: usize, r4: usize) -> u8 { let val1 = self.get_pair_value(r1, r2); let val2 = self.get_pair_value(r3, r4); self.set_pair_value(r1, r2, val1.wrapping_add(val2)); 8 } 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 } 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 } fn set_flag(&mut self, flag: u8) { self.flags |= flag; } fn clear_flag(&mut self, flag: u8) { self.flags &= !flag; } fn set_clear_flag(&mut self, flag: u8, dep: bool) { if dep { self.set_flag(flag); } else { self.clear_flag(flag); } } 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); } fn ret(&mut self) { let new_ip: u16 = self.pop(); //self.dump_stack(); self.ip = new_ip; } fn reti(&mut self) -> u8 { self.ret(); self.ime = true; 16 } 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(0x40, interconnect::INTERRUPT_DISPLAY_STAT); } 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 => { panic!("RLCA, not implemented"); } 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 => panic!("RRCA not implemented."), 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 => panic!("DAA not implemented!"), 0x28 => { let c = self.flags & FLAG_Z > 0; 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 mut 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 > 0; 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); // TODO: H-carry flag 8 }, 0x3A => panic!("LD A, (HL-) not implemented"), 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 old = self.regs[REG_A]; let new = old.wrapping_add(self.get_8bit_reg(reg_id)); self.regs[REG_A] = new; self.clear_flag(FLAG_N); self.set_clear_flag(FLAG_Z, new == 0); self.set_clear_flag(FLAG_C, new < old); // TODO: H 4 } // ADC 0x88 ... 0x8F => { let reg_id = (instruction - 0x88) as usize; println!("ADC {}", REG_NAMES[reg_id]); let old = self.regs[REG_A]; let mut new = old.wrapping_add(self.get_8bit_reg(reg_id)); if self.flags & FLAG_C > 0 { new = new.wrapping_add(1); } self.regs[REG_A] = new; self.clear_flag(FLAG_N); self.set_clear_flag(FLAG_Z, new == 0); self.set_clear_flag(FLAG_C, new < old); // TODO: H 4 } // SUBs 0x90 ... 0x97 => { let reg_id = (instruction - 0x90) as usize; if self.debug { println!("SUB {}", REG_NAMES[reg_id]); } let old = self.regs[REG_A]; let new = old.wrapping_sub(self.get_8bit_reg(reg_id)); 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); // TODO: H 4 } // SBC 0x98 ... 0x9F => { let reg_id = (instruction - 0x98) as usize; if self.debug { println!("SBC {}", REG_NAMES[reg_id]); } let old = self.regs[REG_A]; let mut new = old.wrapping_sub(self.get_8bit_reg(reg_id)); if self.flags & FLAG_C > 0 { new = new.wrapping_sub(1); } 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); 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); self.clear_flag(FLAG_N); 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 val = self.get_8bit_reg(reg_id); let rval = self.regs[REG_A]; self.set_flag(FLAG_N); self.set_clear_flag(FLAG_C, rval < val); self.set_clear_flag(FLAG_Z, rval == val); // TODO H 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); } let o = self.regs[REG_A]; let v = self.regs[REG_A].wrapping_add(val); self.regs[REG_A] = v; self.set_clear_flag(FLAG_Z, v == 0); self.set_clear_flag(FLAG_C, v < o); self.clear_flag(FLAG_N); // TOOD H 8 }, 0xC7 => self.rst(0x00), 0xC8 => { let c = self.flags & FLAG_Z > 0; self.ret_condition("Z".to_owned(), c) }, 0xC9 => {self.ret(); 16}, 0xCA => { let c = self.flags & FLAG_Z > 0; 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 > 0; 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); } let o = self.regs[REG_A]; let mut v = self.regs[REG_A].wrapping_add(arg); if self.flags & FLAG_C > 0 { v = v.wrapping_add(1); } self.regs[REG_A] = v; self.set_clear_flag(FLAG_Z, v == 0); self.clear_flag(FLAG_N); self.set_clear_flag(FLAG_C, v < o); // TODO: FLAG_H 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); } let rval = self.regs[REG_A]; self.set_clear_flag(FLAG_C, val > rval); self.set_clear_flag(FLAG_Z, val == rval); self.set_flag(FLAG_N); self.regs[REG_A] = rval.wrapping_sub(val); // TODO: FLAG_H 8 }, 0xD7 => self.rst(0x10), 0xD8 => { let c = self.flags & FLAG_C > 0; self.ret_condition("C".to_owned(), c) }, 0xD9 => self.reti(), 0xDA => { let c = self.flags & FLAG_C > 0; self.jmp_p_condition("C".to_owned(), c) }, 0xDB => panic!("NON-EXISTING OPCODE"), 0xDC => { let c = self.flags & FLAG_C > 0; 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); } let o = self.regs[REG_A]; let mut v = self.regs[REG_A].wrapping_sub(arg); if self.flags & FLAG_C > 0 { v = v.wrapping_sub(1); } self.regs[REG_A] = v; self.set_clear_flag(FLAG_Z, v == 0); self.set_clear_flag(FLAG_C, v > o); self.set_flag(FLAG_N); // TODO: FLAG_H 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]; if self.debug { println!("ADD SP, {:02X}", arg); } let t = self.sp.wrapping_add(arg as u16); let sp = self.sp; self.clear_flag(FLAG_N); self.clear_flag(FLAG_Z); self.set_clear_flag(FLAG_C, t < sp); // TODO FLAG_H 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 i16; if self.debug { println!("LD HL, SP+{:02X}", arg); } if arg < 0 { let v: u16 = self.sp.wrapping_sub((-arg) as u16); self.set_pair_value(REG_N_H, REG_N_L, v); } else { let v: u16 = self.sp.wrapping_add(arg as u16); self.set_pair_value(REG_N_H, REG_N_L, v); } self.clear_flag(FLAG_N); self.clear_flag(FLAG_Z); // TODO: FLAG_H FLAG_C 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); let rval = self.regs[REG_A]; if self.debug { println!("CP {:02X}", args[0]); } self.set_flag(FLAG_N); self.set_clear_flag(FLAG_C, args[0] > rval); self.set_clear_flag(FLAG_Z, args[0] == rval); // TODO H 8 }, 0xFF => self.rst(0x38), _ => panic!("Unknown instruction: {:02x}", instruction) }; } // self.dump_stack(); self.interconnect.tick(cycles); } }