all opcodes implemented-ish

This commit is contained in:
Alex Janka 2023-01-17 09:09:53 +11:00
parent e40bf4f786
commit e6cbedc59b

View file

@ -1,4 +1,7 @@
use std::ops::{BitAnd, BitOr, BitXor};
use std::{
mem::transmute,
ops::{BitAnd, BitOr, BitXor},
};
use crate::{Inner, Memory, Register, State};
@ -16,9 +19,9 @@ pub struct CPU {
}
impl CPU {
pub fn exec_next(&mut self) -> u8 {
pub fn exec_next(&mut self) {
let opcode = self.next_opcode();
unsafe { println!("exec {:#4X} from {:#4X}", opcode, self.state.pc.as_u16 - 1) };
// unsafe { println!("exec {:#4X} from {:#4X}", opcode, self.state.pc.as_u16 - 1) };
match opcode {
0x0 => {
// noop
@ -76,7 +79,7 @@ impl CPU {
.state
.pc
.as_u16
.wrapping_add(self.ld_immediate_byte() as u16)
.wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16)
},
0x19 => unsafe {
self.state.hl.as_u16 = self.state.hl.as_u16.wrapping_add(self.state.de.as_u16)
@ -95,7 +98,11 @@ impl CPU {
let jump_size = self.ld_immediate_byte();
if self.get_flag(FLAGS::Z) == 0 {
unsafe {
self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16)
self.state.pc.as_u16 = self
.state
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
}
}
}
@ -118,7 +125,11 @@ impl CPU {
let jump_size = self.ld_immediate_byte();
if self.get_flag(FLAGS::Z) == 1 {
unsafe {
self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16)
self.state.pc.as_u16 = self
.state
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
}
}
}
@ -140,7 +151,11 @@ impl CPU {
let jump_size = self.ld_immediate_byte();
if self.get_flag(FLAGS::C) == 0 {
unsafe {
self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16)
self.state.pc.as_u16 = self
.state
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
}
}
}
@ -170,7 +185,11 @@ impl CPU {
let jump_size = self.ld_immediate_byte();
if self.get_flag(FLAGS::C) == 1 {
unsafe {
self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(jump_size as u16)
self.state.pc.as_u16 = self
.state
.pc
.as_u16
.wrapping_add((as_signed(jump_size) as i16) as u16)
}
}
}
@ -723,7 +742,10 @@ impl CPU {
self.state.pc = maybe_next;
}
}
0xCB => println!("Undefined behaviour: opcode CB"),
0xCB => {
let subop = self.ld_immediate_byte();
self.cb_subop(subop);
}
0xCC => {
let maybe_next = self.ld_immediate_word();
if self.get_flag(FLAGS::Z) == 1 {
@ -744,18 +766,192 @@ impl CPU {
.wrapping_add(self.ld_immediate_byte() + self.get_flag(FLAGS::C))
},
0xCF => self.rst(0x08),
0xEA => {
0xD0 => unsafe {
if self.get_flag(FLAGS::C) == 0 {
let address = self.state.sp.as_u16;
self.state.pc.as_u8s.left = self.memory.get(address);
self.state.pc.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2);
}
},
0xD1 => unsafe {
let address = self.state.sp.as_u16;
self.state.de.as_u8s.left = self.memory.get(address);
self.state.de.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2);
},
0xD2 => {
let word = self.ld_immediate_word();
if self.get_flag(FLAGS::C) == 0 {
self.state.pc = word;
}
}
0xD3 => undefined(0xD3),
0xD4 => {
let maybe_next = self.ld_immediate_word();
if self.get_flag(FLAGS::C) == 0 {
self.push(self.state.pc);
self.state.pc = maybe_next;
}
}
0xD5 => self.push(self.state.de),
0xD6 => unsafe {
self.state.af.as_u8s.left = self
.state
.af
.as_u8s
.left
.wrapping_sub(self.ld_immediate_byte())
},
0xD7 => self.rst(0x10),
0xD8 => {
if self.get_flag(FLAGS::C) == 1 {
self.state.pc = self.pop_word()
}
}
0xD9 => panic!("RETI: 0xD9"),
0xDA => {
let maybe_next = self.ld_immediate_word();
if self.get_flag(FLAGS::C) == 1 {
self.state.pc = maybe_next;
}
}
0xDB => undefined(0xDB),
0xDC => {
let maybe_next = self.ld_immediate_word();
if self.get_flag(FLAGS::C) == 1 {
self.push(self.state.pc);
self.state.pc = maybe_next;
}
}
0xDD => undefined(0xDE),
0xDE => unsafe {
self.state.af.as_u8s.left = self
.state
.af
.as_u8s
.left
.wrapping_sub(self.ld_immediate_byte() + self.get_flag(FLAGS::C))
},
0xDF => self.rst(0x18),
0xE0 => {
unsafe {
let address = self.ld_immediate_word().as_u16;
self.memory.set(address, self.state.af.as_u8s.left);
let address = Register {
as_u8s: Inner {
left: self.ld_immediate_byte(),
right: 0xFF,
},
};
self.memory.set(address.as_u16, self.state.af.as_u8s.left);
};
}
_ => {
panic!("unimplemented opcode: {:#X}", opcode);
0xE1 => unsafe {
let address = self.state.sp.as_u16;
self.state.hl.as_u8s.left = self.memory.get(address);
self.state.hl.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2);
},
0xE2 => {
unsafe {
let address = Register {
as_u8s: Inner {
left: self.state.bc.as_u8s.right,
right: 0xFF,
},
};
self.memory.set(address.as_u16, self.state.af.as_u8s.left);
};
}
0xE3 => undefined(0xE3),
0xE4 => undefined(0xE4),
0xE5 => self.push(self.state.hl),
0xE6 => unsafe {
self.state.af.as_u8s.left =
self.state.af.as_u8s.left.bitand(self.ld_immediate_byte())
},
0xE7 => self.rst(0x20),
0xE8 => unsafe {
self.state.sp.as_u16 = self
.state
.sp
.as_u16
.wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16);
},
0xE9 => self.state.pc = self.state.hl,
0xEA => unsafe {
let address = self.ld_immediate_word().as_u16;
self.memory.set(address, self.state.af.as_u8s.left);
},
0xEB => undefined(0xEB),
0xEC => undefined(0xEC),
0xED => undefined(0xED),
0xEE => unsafe {
self.state.af.as_u8s.left =
self.state.af.as_u8s.left.bitxor(self.ld_immediate_byte())
},
0xEF => self.rst(0x28),
0xF0 => {
unsafe {
let address = Register {
as_u8s: Inner {
left: self.ld_immediate_byte(),
right: 0xFF,
},
};
self.state.af.as_u8s.left = self.memory.get(address.as_u16);
};
}
0xF1 => unsafe {
let address = self.state.sp.as_u16;
self.state.af.as_u8s.left = self.memory.get(address);
self.state.af.as_u8s.right = self.memory.get(address + 1);
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(2);
},
0xF2 => {
unsafe {
let address = Register {
as_u8s: Inner {
left: self.state.bc.as_u8s.right,
right: 0xFF,
},
};
self.state.af.as_u8s.left = self.memory.get(address.as_u16);
};
}
0xF3 => panic!("DI IME instruction: 0xF3"),
0xF4 => undefined(0xF4),
0xF5 => self.push(self.state.af),
0xF6 => unsafe {
self.state.af.as_u8s.left =
self.state.af.as_u8s.left.bitor(self.ld_immediate_byte())
},
0xF7 => self.rst(0x30),
0xF8 => unsafe {
self.state.hl.as_u16 = self
.state
.sp
.as_u16
.wrapping_add((as_signed(self.ld_immediate_byte()) as i16) as u16)
},
0xF9 => self.state.sp = self.state.hl,
0xFA => unsafe {
let address = self.ld_immediate_word().as_u16;
self.state.af.as_u8s.left = self.memory.get(address);
},
0xFB => panic!("EI IME instruction: 0xFB"),
0xFC => undefined(0xFC),
0xFD => undefined(0xFD),
0xFE => unsafe {
if self.ld_immediate_byte() == self.state.af.as_u8s.left {
self.set_flag(FLAGS::Z)
}
},
0xFF => self.rst(0x38),
};
return opcode;
}
fn cb_subop(&mut self, subop: u8) {
panic!("Unimplemented sub-opcode: {:#X}", subop);
}
fn next_opcode(&mut self) -> u8 {
@ -839,3 +1035,13 @@ impl CPU {
};
}
}
fn undefined(opcode: u8) {
println!("Undefined behaviour: opcode {:#X}", opcode);
}
fn as_signed(unsigned: u8) -> i8 {
unsafe {
return transmute(unsigned);
}
}