use crate::alu;
use crate::bus::Memory;
use crate::cpu::Cpu;
#[rustfmt::skip]
const PAGE1_CYCLES: [u8; 256] = {
let mut t = [0u8; 256];
t[0x20] = 5; t[0x21] = 5; t[0x22] = 5; t[0x23] = 5;
t[0x24] = 5; t[0x25] = 5; t[0x26] = 5; t[0x27] = 5;
t[0x28] = 5; t[0x29] = 5; t[0x2A] = 5; t[0x2B] = 5;
t[0x2C] = 5; t[0x2D] = 5; t[0x2E] = 5; t[0x2F] = 5;
t[0x3E] = 20; t[0x3F] = 20; t[0x83] = 5; t[0x8C] = 5; t[0x8E] = 4; t[0x93] = 7; t[0x9C] = 7; t[0x9E] = 6; t[0x9F] = 6; t[0xA3] = 7; t[0xAC] = 7; t[0xAE] = 6; t[0xAF] = 6; t[0xB3] = 8; t[0xBC] = 8; t[0xBE] = 7; t[0xBF] = 7; t[0xC3] = 5; t[0xCE] = 4; t[0xD3] = 7; t[0xDE] = 6; t[0xDF] = 6; t[0xE3] = 7; t[0xEE] = 6; t[0xEF] = 6; t[0xF3] = 8; t[0xFE] = 7; t[0xFF] = 7; t
};
pub(super) fn cycles(sub: u8) -> u8 {
PAGE1_CYCLES[sub as usize]
}
pub fn execute(cpu: &mut Cpu, mem: &mut impl Memory, opcode: u8) {
cpu.cycles += PAGE1_CYCLES[opcode as usize] as u64;
match opcode {
0x20 => {
let addr = cpu.addr_relative16(mem);
cpu.reg.pc = addr;
}
0x21 => {
let _addr = cpu.addr_relative16(mem);
}
0x22 => {
let addr = cpu.addr_relative16(mem);
if !cpu.reg.cc.carry() && !cpu.reg.cc.zero() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x23 => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.carry() || cpu.reg.cc.zero() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x24 => {
let addr = cpu.addr_relative16(mem);
if !cpu.reg.cc.carry() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x25 => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.carry() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x26 => {
let addr = cpu.addr_relative16(mem);
if !cpu.reg.cc.zero() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x27 => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.zero() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x28 => {
let addr = cpu.addr_relative16(mem);
if !cpu.reg.cc.overflow() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x29 => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.overflow() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x2A => {
let addr = cpu.addr_relative16(mem);
if !cpu.reg.cc.negative() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x2B => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.negative() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x2C => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.negative() == cpu.reg.cc.overflow() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x2D => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.negative() != cpu.reg.cc.overflow() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x2E => {
let addr = cpu.addr_relative16(mem);
if !cpu.reg.cc.zero() && cpu.reg.cc.negative() == cpu.reg.cc.overflow() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x2F => {
let addr = cpu.addr_relative16(mem);
if cpu.reg.cc.zero() || cpu.reg.cc.negative() != cpu.reg.cc.overflow() {
cpu.reg.pc = addr;
cpu.cycles += 1;
}
}
0x3E => {
cpu.push_entire_state(mem);
cpu.reg.pc = mem.read_word(crate::cpu::VEC_SWI2);
}
0x3F => {
cpu.reg.cc.set_entire(true);
cpu.push_entire_state(mem);
cpu.reg.pc = mem.read_word(crate::cpu::VEC_SWI2);
}
0x83 => {
let v = cpu.fetch_word(mem);
let d = cpu.reg.d;
alu::sub16(d, v, &mut cpu.reg.cc);
}
0x93 => {
let addr = cpu.addr_direct(mem);
let v = mem.read_word(addr);
let d = cpu.reg.d;
alu::sub16(d, v, &mut cpu.reg.cc);
}
0xA3 => {
let (addr, ex) = cpu.addr_indexed(mem);
cpu.cycles += ex as u64;
let v = mem.read_word(addr);
let d = cpu.reg.d;
alu::sub16(d, v, &mut cpu.reg.cc);
}
0xB3 => {
let addr = cpu.addr_extended(mem);
let v = mem.read_word(addr);
let d = cpu.reg.d;
alu::sub16(d, v, &mut cpu.reg.cc);
}
0x8C => {
let v = cpu.fetch_word(mem);
let y = cpu.reg.y;
alu::sub16(y, v, &mut cpu.reg.cc);
}
0x9C => {
let addr = cpu.addr_direct(mem);
let v = mem.read_word(addr);
let y = cpu.reg.y;
alu::sub16(y, v, &mut cpu.reg.cc);
}
0xAC => {
let (addr, ex) = cpu.addr_indexed(mem);
cpu.cycles += ex as u64;
let v = mem.read_word(addr);
let y = cpu.reg.y;
alu::sub16(y, v, &mut cpu.reg.cc);
}
0xBC => {
let addr = cpu.addr_extended(mem);
let v = mem.read_word(addr);
let y = cpu.reg.y;
alu::sub16(y, v, &mut cpu.reg.cc);
}
0x8E => {
let v = cpu.fetch_word(mem);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.y = v;
}
0x9E => {
let addr = cpu.addr_direct(mem);
let v = mem.read_word(addr);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.y = v;
}
0x9F => {
let addr = cpu.addr_direct(mem);
let v = cpu.reg.y;
alu::ld16_flags(v, &mut cpu.reg.cc);
mem.write_word(addr, v);
}
0xAE => {
let (addr, ex) = cpu.addr_indexed(mem);
cpu.cycles += ex as u64;
let v = mem.read_word(addr);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.y = v;
}
0xAF => {
let (addr, ex) = cpu.addr_indexed(mem);
cpu.cycles += ex as u64;
let v = cpu.reg.y;
alu::ld16_flags(v, &mut cpu.reg.cc);
mem.write_word(addr, v);
}
0xBE => {
let addr = cpu.addr_extended(mem);
let v = mem.read_word(addr);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.y = v;
}
0xBF => {
let addr = cpu.addr_extended(mem);
let v = cpu.reg.y;
alu::ld16_flags(v, &mut cpu.reg.cc);
mem.write_word(addr, v);
}
0xC3 => {
let v = cpu.fetch_word(mem);
let d = cpu.reg.d;
let _r = alu::add16(d, v, &mut cpu.reg.cc);
}
0xCE => {
let v = cpu.fetch_word(mem);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.s = v;
cpu.arm_nmi();
}
0xD3 => {
let addr = cpu.addr_direct(mem);
let v = mem.read_word(addr);
let d = cpu.reg.d;
let _r = alu::add16(d, v, &mut cpu.reg.cc);
}
0xDE => {
let addr = cpu.addr_direct(mem);
let v = mem.read_word(addr);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.s = v;
cpu.arm_nmi();
}
0xDF => {
let addr = cpu.addr_direct(mem);
let v = cpu.reg.s;
alu::ld16_flags(v, &mut cpu.reg.cc);
mem.write_word(addr, v);
}
0xE3 => {
let (addr, ex) = cpu.addr_indexed(mem);
cpu.cycles += ex as u64;
let v = mem.read_word(addr);
let d = cpu.reg.d;
let _r = alu::add16(d, v, &mut cpu.reg.cc);
}
0xEE => {
let (addr, ex) = cpu.addr_indexed(mem);
cpu.cycles += ex as u64;
let v = mem.read_word(addr);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.s = v;
cpu.arm_nmi();
}
0xEF => {
let (addr, ex) = cpu.addr_indexed(mem);
cpu.cycles += ex as u64;
let v = cpu.reg.s;
alu::ld16_flags(v, &mut cpu.reg.cc);
mem.write_word(addr, v);
}
0xF3 => {
let addr = cpu.addr_extended(mem);
let v = mem.read_word(addr);
let d = cpu.reg.d;
let _r = alu::add16(d, v, &mut cpu.reg.cc);
}
0xFE => {
let addr = cpu.addr_extended(mem);
let v = mem.read_word(addr);
alu::ld16_flags(v, &mut cpu.reg.cc);
cpu.reg.s = v;
cpu.arm_nmi();
}
0xFF => {
let addr = cpu.addr_extended(mem);
let v = cpu.reg.s;
alu::ld16_flags(v, &mut cpu.reg.cc);
mem.write_word(addr, v);
}
_ => {
cpu.illegal = true;
}
}
}