rustyboy/src/cpu.rs
2016-05-29 20:27:36 +02:00

1627 lines
56 KiB
Rust

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);
}
}