fix adds and flags

This commit is contained in:
Alex Janka 2023-01-18 12:45:56 +11:00
parent 3cf0df204d
commit 9533768bd9

View file

@ -16,12 +16,16 @@ enum FLAGS {
pub struct CPU { pub struct CPU {
pub memory: Memory, pub memory: Memory,
pub state: State, pub state: State,
pub last_instruction: u8,
pub last_instruction_addr: u16,
} }
impl CPU { impl CPU {
pub fn exec_next(&mut self) { pub fn exec_next(&mut self) {
unsafe { self.last_instruction_addr = self.state.pc.as_u16 };
let opcode = self.next_opcode(); let opcode = self.next_opcode();
// unsafe { println!("exec {:#4X} from {:#4X}", opcode, self.state.pc.as_u16 - 1) }; self.last_instruction = opcode;
match opcode { match opcode {
0x0 => { 0x0 => {
// noop // noop
@ -31,12 +35,12 @@ impl CPU {
let address = self.state.bc.as_u16; let address = self.state.bc.as_u16;
self.memory.set(address, self.state.af.as_u8s.left); self.memory.set(address, self.state.af.as_u8s.left);
}, },
0x03 => unsafe { self.state.bc.as_u16 = self.state.bc.as_u16.wrapping_add(1) }, 0x03 => unsafe { self.state.bc.as_u16 = self.add_u16s(self.state.bc.as_u16, 1) },
0x04 => unsafe { 0x04 => unsafe {
self.state.bc.as_u8s.left = self.state.bc.as_u8s.left.wrapping_add(1) self.state.bc.as_u8s.left = self.add_u8s(self.state.bc.as_u8s.left, 1)
}, },
0x05 => unsafe { 0x05 => unsafe {
self.state.bc.as_u8s.left = self.state.bc.as_u8s.left.wrapping_sub(1) self.state.bc.as_u8s.left = self.sub_u8s(self.state.bc.as_u8s.left, 1)
}, },
0x06 => self.state.bc.as_u8s.left = self.ld_immediate_byte(), 0x06 => self.state.bc.as_u8s.left = self.ld_immediate_byte(),
0x07 => panic!("RCLA rotate instruction: 0x07"), 0x07 => panic!("RCLA rotate instruction: 0x07"),
@ -46,15 +50,15 @@ impl CPU {
self.store_word(address, word); self.store_word(address, word);
}, },
0x09 => unsafe { 0x09 => unsafe {
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.bc.as_u16) self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, self.state.bc.as_u16)
}, },
0x0A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.bc.as_u16) }, 0x0A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.bc.as_u16) },
0x0B => unsafe { self.state.bc.as_u16 = self.state.bc.as_u16.wrapping_sub(0x1) }, 0x0B => unsafe { self.state.bc.as_u16 = self.sub_u16s(self.state.bc.as_u16, 0x1) },
0x0C => unsafe { 0x0C => unsafe {
self.state.bc.as_u8s.right = self.state.bc.as_u8s.right.wrapping_add(0x1) self.state.bc.as_u8s.right = self.add_u8s(self.state.bc.as_u8s.right, 0x1)
}, },
0x0D => unsafe { 0x0D => unsafe {
self.state.bc.as_u8s.right = self.state.bc.as_u8s.right.wrapping_sub(0x1) self.state.bc.as_u8s.right = self.sub_u8s(self.state.bc.as_u8s.right, 0x1)
}, },
0x0E => self.state.bc.as_u8s.right = self.ld_immediate_byte(), 0x0E => self.state.bc.as_u8s.right = self.ld_immediate_byte(),
0x0F => panic!("RRCA rotate instruction: 0x0F"), 0x0F => panic!("RRCA rotate instruction: 0x0F"),
@ -65,32 +69,32 @@ impl CPU {
let data = self.state.af.as_u8s.left; let data = self.state.af.as_u8s.left;
self.memory.set(address, data); self.memory.set(address, data);
}, },
0x13 => unsafe { self.state.de.as_u16 = self.state.de.as_u16.wrapping_sub(0x1) }, 0x13 => unsafe { self.state.de.as_u16 = self.sub_u16s(self.state.de.as_u16, 0x1) },
0x14 => unsafe { 0x14 => unsafe {
self.state.de.as_u8s.left = self.state.de.as_u8s.left.wrapping_add(0x1) self.state.de.as_u8s.left = self.add_u8s(self.state.de.as_u8s.left, 0x1)
}, },
0x15 => unsafe { 0x15 => unsafe {
self.state.de.as_u8s.left = self.state.de.as_u8s.left.wrapping_sub(0x1) self.state.de.as_u8s.left = self.sub_u8s(self.state.de.as_u8s.left, 0x1)
}, },
0x16 => self.state.de.as_u8s.left = self.ld_immediate_byte(), 0x16 => self.state.de.as_u8s.left = self.ld_immediate_byte(),
0x17 => panic!("RLA rotate instruction: 0x17"), 0x17 => panic!("RLA rotate instruction: 0x17"),
0x18 => unsafe { 0x18 => unsafe {
self.state.pc.as_u16 = self let t = (as_signed(self.ld_immediate_byte()) as i16) as u16;
.state self.state.pc.as_u16 = self.add_u16s(self.state.pc.as_u16, t)
.pc
.as_u16
.wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16)
}, },
0x19 => unsafe { 0x19 => unsafe {
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.de.as_u16) self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, self.state.de.as_u16)
}, },
0x1A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.de.as_u16) }, 0x1A => unsafe {
0x1B => unsafe { self.state.de.as_u16 = self.state.de.as_u16.wrapping_sub(1) }, // println!("loading from {:#X}", self.state.de.as_u16);
self.state.af.as_u8s.left = self.memory.get(self.state.de.as_u16);
},
0x1B => unsafe { self.state.de.as_u16 = self.sub_u16s(self.state.de.as_u16, 1) },
0x1C => unsafe { 0x1C => unsafe {
self.state.de.as_u8s.right = self.state.de.as_u8s.right.wrapping_add(1) self.state.de.as_u8s.right = self.add_u8s(self.state.de.as_u8s.right, 1)
}, },
0x1D => unsafe { 0x1D => unsafe {
self.state.de.as_u8s.right = self.state.de.as_u8s.right.wrapping_sub(1) self.state.de.as_u8s.right = self.sub_u8s(self.state.de.as_u8s.right, 1)
}, },
0x1E => self.state.de.as_u8s.right = self.ld_immediate_byte(), 0x1E => self.state.de.as_u8s.right = self.ld_immediate_byte(),
0x1F => panic!("RRA rotate instruction: 0x1F"), 0x1F => panic!("RRA rotate instruction: 0x1F"),
@ -99,10 +103,7 @@ impl CPU {
if self.get_flag(FLAGS::Z) == 0 { if self.get_flag(FLAGS::Z) == 0 {
unsafe { unsafe {
self.state.pc.as_u16 = self self.state.pc.as_u16 = self
.state .add_u16s(self.state.pc.as_u16, (as_signed(jump_size) as i16) as u16)
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
} }
} }
} }
@ -110,14 +111,14 @@ impl CPU {
0x22 => unsafe { 0x22 => unsafe {
self.memory self.memory
.set(self.state.hl.as_u16, self.state.af.as_u8s.left); .set(self.state.hl.as_u16, self.state.af.as_u8s.left);
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(1); self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, 1);
}, },
0x23 => unsafe { self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(1) }, 0x23 => unsafe { self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, 1) },
0x24 => unsafe { 0x24 => unsafe {
self.state.hl.as_u8s.left = self.state.hl.as_u8s.left.wrapping_add(1) self.state.hl.as_u8s.left = self.add_u8s(self.state.hl.as_u8s.left, 1)
}, },
0x25 => unsafe { 0x25 => unsafe {
self.state.hl.as_u8s.left = self.state.hl.as_u8s.left.wrapping_sub(1) self.state.hl.as_u8s.left = self.sub_u8s(self.state.hl.as_u8s.left, 1)
}, },
0x26 => self.state.hl.as_u8s.left = self.ld_immediate_byte(), 0x26 => self.state.hl.as_u8s.left = self.ld_immediate_byte(),
0x27 => unsafe { 0x27 => unsafe {
@ -137,30 +138,31 @@ impl CPU {
self.state.af.as_u8s.left -= 0x6; self.state.af.as_u8s.left -= 0x6;
} }
} }
println!(
" ...this set register a to {:#X}...",
self.state.af.as_u8s.left
);
}, },
0x28 => { 0x28 => {
let jump_size = self.ld_immediate_byte(); let jump_size = self.ld_immediate_byte();
if self.get_flag(FLAGS::Z) == 1 { if self.get_flag(FLAGS::Z) == 1 {
unsafe { unsafe {
self.state.pc.as_u16 = self self.state.pc.as_u16 = self
.state .add_u16s(self.state.pc.as_u16, (as_signed(jump_size) as i16) as u16)
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
} }
} }
} }
0x29 => unsafe { self.state.hl.as_u16 *= 2 }, 0x29 => unsafe { self.state.hl.as_u16 *= 2 },
0x2A => unsafe { 0x2A => unsafe {
self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16); self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16);
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(1); self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, 1);
}, },
0x2B => unsafe { self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_sub(1) }, 0x2B => unsafe { self.state.hl.as_u16 = self.sub_u16s(self.state.hl.as_u16, 1) },
0x2C => unsafe { 0x2C => unsafe {
self.state.hl.as_u8s.right = self.state.hl.as_u8s.right.wrapping_add(1) self.state.hl.as_u8s.right = self.add_u8s(self.state.hl.as_u8s.right, 1)
}, },
0x2D => unsafe { 0x2D => unsafe {
self.state.hl.as_u8s.right = self.state.hl.as_u8s.right.wrapping_sub(1) self.state.hl.as_u8s.right = self.sub_u8s(self.state.hl.as_u8s.right, 1)
}, },
0x2E => self.state.hl.as_u8s.right = self.ld_immediate_byte(), 0x2E => self.state.hl.as_u8s.right = self.ld_immediate_byte(),
0x2F => unsafe { self.state.af.as_u8s.left = !self.state.af.as_u8s.left }, 0x2F => unsafe { self.state.af.as_u8s.left = !self.state.af.as_u8s.left },
@ -169,10 +171,7 @@ impl CPU {
if self.get_flag(FLAGS::C) == 0 { if self.get_flag(FLAGS::C) == 0 {
unsafe { unsafe {
self.state.pc.as_u16 = self self.state.pc.as_u16 = self
.state .add_u16s(self.state.pc.as_u16, (as_signed(jump_size) as i16) as u16)
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
} }
} }
} }
@ -180,9 +179,9 @@ impl CPU {
0x32 => unsafe { 0x32 => unsafe {
self.memory self.memory
.set(self.state.hl.as_u16, self.state.af.as_u8s.left); .set(self.state.hl.as_u16, self.state.af.as_u8s.left);
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_sub(1); self.state.hl.as_u16 = self.sub_u16s(self.state.hl.as_u16, 1);
}, },
0x33 => unsafe { self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(1) }, 0x33 => unsafe { self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 1) },
0x34 => unsafe { 0x34 => unsafe {
let address = self.state.hl.as_u16; let address = self.state.hl.as_u16;
let data = self.memory.get(address) + 1; let data = self.memory.get(address) + 1;
@ -203,26 +202,23 @@ impl CPU {
if self.get_flag(FLAGS::C) == 1 { if self.get_flag(FLAGS::C) == 1 {
unsafe { unsafe {
self.state.pc.as_u16 = self self.state.pc.as_u16 = self
.state .add_u16s(self.state.pc.as_u16, (as_signed(jump_size) as i16) as u16)
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
} }
} }
} }
0x39 => unsafe { 0x39 => unsafe {
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.sp.as_u16) self.state.hl.as_u16 = self.add_u16s(self.state.hl.as_u16, self.state.sp.as_u16)
}, },
0x3A => unsafe { 0x3A => unsafe {
self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16); self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16);
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_sub(1); self.state.hl.as_u16 = self.sub_u16s(self.state.hl.as_u16, 1);
}, },
0x3B => unsafe { self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_sub(1) }, 0x3B => unsafe { self.state.sp.as_u16 = self.sub_u16s(self.state.sp.as_u16, 1) },
0x3C => unsafe { 0x3C => unsafe {
self.state.af.as_u8s.left = self.state.af.as_u8s.left.wrapping_add(1) self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, 1)
}, },
0x3D => unsafe { 0x3D => unsafe {
self.state.af.as_u8s.left = self.state.af.as_u8s.left.wrapping_sub(1) self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, 1)
}, },
0x3E => self.state.af.as_u8s.left = self.ld_immediate_byte(), 0x3E => self.state.af.as_u8s.left = self.ld_immediate_byte(),
0x3F => self.toggle_flag(FLAGS::C), 0x3F => self.toggle_flag(FLAGS::C),
@ -312,256 +308,156 @@ impl CPU {
0x7E => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16) }, 0x7E => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.hl.as_u16) },
0x7F => {} 0x7F => {}
0x80 => unsafe { 0x80 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.add_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left)
.af
.as_u8s
.left
.wrapping_add(self.state.bc.as_u8s.left)
}, },
0x81 => unsafe { 0x81 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.add_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.right)
.af
.as_u8s
.left
.wrapping_add(self.state.bc.as_u8s.right)
}, },
0x82 => unsafe { 0x82 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left)
.af
.as_u8s
.left
.wrapping_add(self.state.de.as_u8s.left)
}, },
0x83 => unsafe { 0x83 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right)
.af
.as_u8s
.left
.wrapping_add(self.state.de.as_u8s.right)
}, },
0x84 => unsafe { 0x84 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left)
.af
.as_u8s
.left
.wrapping_add(self.state.hl.as_u8s.left)
}, },
0x85 => unsafe { 0x85 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right)
.af
.as_u8s
.left
.wrapping_add(self.state.hl.as_u8s.right)
}, },
0x86 => unsafe { 0x86 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left = self.add_u8s(
.state self.state.af.as_u8s.left,
.af self.memory.get(self.state.hl.as_u16),
.as_u8s )
.left
.wrapping_add(self.memory.get(self.state.hl.as_u16))
}, },
0x87 => unsafe { 0x87 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.add_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left)
.af
.as_u8s
.left
.wrapping_add(self.state.af.as_u8s.left)
}, },
0x88 => unsafe { 0x88 => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.add_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left + f)
.as_u8s
.left
.wrapping_add(self.state.bc.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0x89 => unsafe { 0x89 => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.add_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.right + f)
.as_u8s
.left
.wrapping_add(self.state.bc.as_u8s.right + self.get_flag(FLAGS::C))
}, },
0x8A => unsafe { 0x8A => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left + f)
.as_u8s
.left
.wrapping_add(self.state.de.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0x8B => unsafe { 0x8B => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.add_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right + f)
.as_u8s
.left
.wrapping_add(self.state.de.as_u8s.right + self.get_flag(FLAGS::C))
}, },
0x8C => unsafe { 0x8C => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left + f)
.as_u8s
.left
.wrapping_add(self.state.hl.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0x8D => unsafe { 0x8D => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.add_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right + f)
.as_u8s
.left
.wrapping_add(self.state.hl.as_u8s.right + self.get_flag(FLAGS::C))
}, },
0x8E => unsafe { 0x8E => unsafe {
self.state.af.as_u8s.left = let f = self.get_flag(FLAGS::C);
self.state.af.as_u8s.left.wrapping_add( self.state.af.as_u8s.left = self.add_u8s(
self.memory.get(self.state.hl.as_u16) + self.get_flag(FLAGS::C), self.state.af.as_u8s.left,
) self.memory.get(self.state.hl.as_u16) + f,
)
}, },
0x8F => unsafe { 0x8F => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.add_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left + f)
.as_u8s
.left
.wrapping_add(self.state.af.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0x90 => unsafe { 0x90 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left)
.af
.as_u8s
.left
.wrapping_sub(self.state.bc.as_u8s.left)
}, },
0x91 => unsafe { 0x91 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.right)
.af
.as_u8s
.left
.wrapping_sub(self.state.bc.as_u8s.right)
}, },
0x92 => unsafe { 0x92 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left)
.af
.as_u8s
.left
.wrapping_sub(self.state.de.as_u8s.left)
}, },
0x93 => unsafe { 0x93 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right)
.af
.as_u8s
.left
.wrapping_sub(self.state.de.as_u8s.right)
}, },
0x94 => unsafe { 0x94 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left)
.af
.as_u8s
.left
.wrapping_sub(self.state.hl.as_u8s.left)
}, },
0x95 => unsafe { 0x95 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right)
.af
.as_u8s
.left
.wrapping_sub(self.state.hl.as_u8s.right)
}, },
0x96 => unsafe { 0x96 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left = self.sub_u8s(
.state self.state.af.as_u8s.left,
.af self.memory.get(self.state.hl.as_u16),
.as_u8s )
.left
.wrapping_sub(self.memory.get(self.state.hl.as_u16))
}, },
0x97 => unsafe { 0x97 => unsafe {
self.state.af.as_u8s.left = self self.state.af.as_u8s.left =
.state self.sub_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left)
.af
.as_u8s
.left
.wrapping_sub(self.state.af.as_u8s.left)
}, },
0x98 => unsafe { 0x98 => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.left + f)
.as_u8s
.left
.wrapping_sub(self.state.bc.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0x99 => unsafe { 0x99 => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.sub_u8s(self.state.af.as_u8s.left, self.state.bc.as_u8s.right + f)
.as_u8s
.left
.wrapping_sub(self.state.bc.as_u8s.right + self.get_flag(FLAGS::C))
}, },
0x9A => unsafe { 0x9A => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.left + f)
.as_u8s
.left
.wrapping_sub(self.state.de.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0x9B => unsafe { 0x9B => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.sub_u8s(self.state.af.as_u8s.left, self.state.de.as_u8s.right + f)
.as_u8s
.left
.wrapping_sub(self.state.de.as_u8s.right + self.get_flag(FLAGS::C))
}, },
0x9C => unsafe { 0x9C => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.left + f)
.as_u8s
.left
.wrapping_sub(self.state.hl.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0x9D => unsafe { 0x9D => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.sub_u8s(self.state.af.as_u8s.left, self.state.hl.as_u8s.right + f)
.as_u8s
.left
.wrapping_sub(self.state.hl.as_u8s.right + self.get_flag(FLAGS::C))
}, },
0x9E => unsafe { 0x9E => unsafe {
self.state.af.as_u8s.left = let f = self.get_flag(FLAGS::C);
self.state.af.as_u8s.left.wrapping_sub( self.state.af.as_u8s.left = self.sub_u8s(
self.memory.get(self.state.hl.as_u16) + self.get_flag(FLAGS::C), self.state.af.as_u8s.left,
) self.memory.get(self.state.hl.as_u16) + f,
)
}, },
0x9F => unsafe { 0x9F => unsafe {
self.state.af.as_u8s.left = self let f = self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left =
.af self.sub_u8s(self.state.af.as_u8s.left, self.state.af.as_u8s.left + f)
.as_u8s
.left
.wrapping_sub(self.state.af.as_u8s.left + self.get_flag(FLAGS::C))
}, },
0xA0 => unsafe { 0xA0 => unsafe {
self.state.af.as_u8s.left = self.state.af.as_u8s.left =
@ -712,14 +608,14 @@ impl CPU {
let address = self.state.sp.as_u16; let address = self.state.sp.as_u16;
self.state.pc.as_u8s.left = self.memory.get(address); self.state.pc.as_u8s.left = self.memory.get(address);
self.state.pc.as_u8s.right = self.memory.get(address + 1); self.state.pc.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 2);
} }
}, },
0xC1 => unsafe { 0xC1 => unsafe {
let address = self.state.sp.as_u16; let address = self.state.sp.as_u16;
self.state.bc.as_u8s.left = self.memory.get(address); self.state.bc.as_u8s.left = self.memory.get(address);
self.state.bc.as_u8s.right = self.memory.get(address + 1); self.state.bc.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 2);
}, },
0xC2 => { 0xC2 => {
let word = self.ld_immediate_word(); let word = self.ld_immediate_word();
@ -739,12 +635,8 @@ impl CPU {
} }
0xC5 => self.push(self.state.bc), 0xC5 => self.push(self.state.bc),
0xC6 => unsafe { 0xC6 => unsafe {
self.state.af.as_u8s.left = self let t = self.ld_immediate_byte();
.state self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, t)
.af
.as_u8s
.left
.wrapping_add(self.ld_immediate_byte())
}, },
0xC7 => self.rst(0x00), 0xC7 => self.rst(0x00),
0xC8 => { 0xC8 => {
@ -775,12 +667,8 @@ impl CPU {
self.state.pc = self.ld_immediate_word(); self.state.pc = self.ld_immediate_word();
} }
0xCE => unsafe { 0xCE => unsafe {
self.state.af.as_u8s.left = self let t = self.ld_immediate_byte() + self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left = self.add_u8s(self.state.af.as_u8s.left, t)
.af
.as_u8s
.left
.wrapping_add(self.ld_immediate_byte() + self.get_flag(FLAGS::C))
}, },
0xCF => self.rst(0x08), 0xCF => self.rst(0x08),
0xD0 => unsafe { 0xD0 => unsafe {
@ -788,14 +676,14 @@ impl CPU {
let address = self.state.sp.as_u16; let address = self.state.sp.as_u16;
self.state.pc.as_u8s.left = self.memory.get(address); self.state.pc.as_u8s.left = self.memory.get(address);
self.state.pc.as_u8s.right = self.memory.get(address + 1); self.state.pc.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 2);
} }
}, },
0xD1 => unsafe { 0xD1 => unsafe {
let address = self.state.sp.as_u16; let address = self.state.sp.as_u16;
self.state.de.as_u8s.left = self.memory.get(address); self.state.de.as_u8s.left = self.memory.get(address);
self.state.de.as_u8s.right = self.memory.get(address + 1); self.state.de.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 2);
}, },
0xD2 => { 0xD2 => {
let word = self.ld_immediate_word(); let word = self.ld_immediate_word();
@ -813,12 +701,8 @@ impl CPU {
} }
0xD5 => self.push(self.state.de), 0xD5 => self.push(self.state.de),
0xD6 => unsafe { 0xD6 => unsafe {
self.state.af.as_u8s.left = self let t = self.ld_immediate_byte();
.state self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, t)
.af
.as_u8s
.left
.wrapping_sub(self.ld_immediate_byte())
}, },
0xD7 => self.rst(0x10), 0xD7 => self.rst(0x10),
0xD8 => { 0xD8 => {
@ -846,12 +730,8 @@ impl CPU {
} }
0xDD => undefined(0xDE), 0xDD => undefined(0xDE),
0xDE => unsafe { 0xDE => unsafe {
self.state.af.as_u8s.left = self let t = self.ld_immediate_byte() + self.get_flag(FLAGS::C);
.state self.state.af.as_u8s.left = self.sub_u8s(self.state.af.as_u8s.left, t)
.af
.as_u8s
.left
.wrapping_sub(self.ld_immediate_byte() + self.get_flag(FLAGS::C))
}, },
0xDF => self.rst(0x18), 0xDF => self.rst(0x18),
0xE0 => { 0xE0 => {
@ -869,7 +749,7 @@ impl CPU {
let address = self.state.sp.as_u16; let address = self.state.sp.as_u16;
self.state.hl.as_u8s.left = self.memory.get(address); self.state.hl.as_u8s.left = self.memory.get(address);
self.state.hl.as_u8s.right = self.memory.get(address + 1); self.state.hl.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 2);
}, },
0xE2 => { 0xE2 => {
unsafe { unsafe {
@ -891,11 +771,8 @@ impl CPU {
}, },
0xE7 => self.rst(0x20), 0xE7 => self.rst(0x20),
0xE8 => unsafe { 0xE8 => unsafe {
self.state.sp.as_u16 = self let t = (as_signed(self.ld_immediate_byte()) as i16) as u16;
.state self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, t);
.sp
.as_u16
.wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16);
}, },
0xE9 => self.state.pc = self.state.hl, 0xE9 => self.state.pc = self.state.hl,
0xEA => unsafe { 0xEA => unsafe {
@ -925,7 +802,7 @@ impl CPU {
let address = self.state.sp.as_u16; let address = self.state.sp.as_u16;
self.state.af.as_u8s.left = self.memory.get(address); self.state.af.as_u8s.left = self.memory.get(address);
self.state.af.as_u8s.right = self.memory.get(address + 1); self.state.af.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); self.state.sp.as_u16 = self.add_u16s(self.state.sp.as_u16, 2);
}, },
0xF2 => { 0xF2 => {
unsafe { unsafe {
@ -947,11 +824,8 @@ impl CPU {
}, },
0xF7 => self.rst(0x30), 0xF7 => self.rst(0x30),
0xF8 => unsafe { 0xF8 => unsafe {
self.state.hl.as_u16 = self let t = (as_signed(self.ld_immediate_byte()) as i16) as u16;
.state self.state.hl.as_u16 = self.add_u16s(self.state.sp.as_u16, t)
.sp
.as_u16
.wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16)
}, },
0xF9 => self.state.sp = self.state.hl, 0xF9 => self.state.sp = self.state.hl,
0xFA => unsafe { 0xFA => unsafe {
@ -971,13 +845,18 @@ impl CPU {
} }
fn cb_subop(&mut self, subop: u8) { fn cb_subop(&mut self, subop: u8) {
panic!("Unimplemented sub-opcode: {:#X}", subop); match subop {
0x7C => unsafe {
self.set_or_clear_flag(FLAGS::Z, !get_bit(self.state.hl.as_u8s.left, 7))
},
_ => panic!("Unimplemented sub-opcode: {:#X}", subop),
}
} }
fn next_opcode(&mut self) -> u8 { fn next_opcode(&mut self) -> u8 {
unsafe { unsafe {
let opcode = self.memory.get(self.state.pc.as_u16); let opcode = self.memory.get(self.state.pc.as_u16);
self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(0x1); self.state.pc.as_u16 += 0x1;
return opcode; return opcode;
}; };
} }
@ -1000,7 +879,7 @@ impl CPU {
fn pop_word(&mut self) -> Register { fn pop_word(&mut self) -> Register {
unsafe { unsafe {
let address = self.state.sp.as_u16; let address = self.state.sp.as_u16;
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2); self.state.sp.as_u16 += 0x2;
Register { Register {
as_u8s: Inner { as_u8s: Inner {
left: self.memory.get(address), left: self.memory.get(address),
@ -1032,7 +911,11 @@ impl CPU {
fn get_flag(&mut self, flag: FLAGS) -> u8 { fn get_flag(&mut self, flag: FLAGS) -> u8 {
unsafe { unsafe {
return self.state.af.as_u8s.right & (1 << flag as u8); if get_bit(self.state.af.as_u8s.right, flag as u8) {
0x1
} else {
0x0
}
} }
} }
@ -1042,7 +925,6 @@ impl CPU {
}; };
} }
#[allow(dead_code)]
fn clear_flag(&mut self, flag: FLAGS) { fn clear_flag(&mut self, flag: FLAGS) {
unsafe { unsafe {
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitand(!(1 << flag as u8)); self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitand(!(1 << flag as u8));
@ -1054,6 +936,56 @@ impl CPU {
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitxor(1 << flag as u8); self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitxor(1 << flag as u8);
}; };
} }
fn set_or_clear_flag(&mut self, flag: FLAGS, state: bool) {
if state {
self.set_flag(flag)
} else {
self.clear_flag(flag)
}
}
fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
self.set_or_clear_flag(FLAGS::Z, !carry && result == 0x0);
self.set_or_clear_flag(FLAGS::H, (first & 0xF) + (second & 0xF) > 0xF);
return result;
}
fn add_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
self.set_or_clear_flag(FLAGS::Z, !carry && result == 0x0);
self.set_or_clear_flag(FLAGS::H, (first & 0xF) + (second & 0xF) > 0xF);
return result;
}
fn sub_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
self.set_or_clear_flag(FLAGS::Z, !carry && result == 0x0);
self.set_or_clear_flag(
FLAGS::H,
((first & 0xF) as i32 - (second & 0xF) as i32) < 0xF,
);
return result;
}
fn sub_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
self.set_or_clear_flag(FLAGS::Z, !carry && result == 0x0);
self.set_or_clear_flag(
FLAGS::H,
((first & 0xF) as i32 - (second & 0xF) as i32) < 0xF,
);
return result;
}
} }
fn undefined(opcode: u8) { fn undefined(opcode: u8) {
@ -1065,3 +997,9 @@ fn as_signed(unsigned: u8) -> i8 {
return transmute(unsigned); return transmute(unsigned);
} }
} }
fn get_bit(byte: u8, flag: u8) -> bool {
let mask = 1 << flag;
let got = byte & mask;
return got > 0x0;
}