Skip to content
Snippets Groups Projects
inst.rs 49.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • fn rst_30h(cpu: &mut Cpu) {
        rst(cpu, 0x0030);
    }
    
    
    fn ld_hl_spi8(cpu: &mut Cpu) {
        let sp = cpu.sp as i32;
        let byte = cpu.read_u8() as i8;
        let byte_i32 = byte as i32;
    
        let result = sp.wrapping_add(byte_i32);
    
        cpu.set_sub(false);
        cpu.set_zero(false);
        cpu.set_half_carry((sp ^ byte_i32 ^ result) & 0x10 == 0x10);
        cpu.set_carry((sp ^ byte_i32 ^ result) & 0x100 == 0x100);
    
        cpu.set_hl(result as u16);
    }
    
    
    fn ld_sp_hl(cpu: &mut Cpu) {
        cpu.sp = cpu.hl();
    }
    
    
    fn ld_a_mu16(cpu: &mut Cpu) {
        let word = cpu.read_u16();
        let byte = cpu.mmu.read(word);
        cpu.a = byte;
    }
    
    
    fn ei(cpu: &mut Cpu) {
        cpu.enable_int();
    }
    
    fn cp_a_u8(cpu: &mut Cpu) {
        let byte = cpu.read_u8();
        sub_set_flags(cpu, cpu.a, byte);
    }
    
    fn rst_38h(cpu: &mut Cpu) {
        rst(cpu, 0x0038);
    }
    
    
    fn rlc_b(cpu: &mut Cpu) {
        cpu.b = rlc(cpu, cpu.b);
    }
    
    fn rlc_c(cpu: &mut Cpu) {
        cpu.c = rlc(cpu, cpu.c);
    }
    
    fn rlc_d(cpu: &mut Cpu) {
        cpu.d = rlc(cpu, cpu.d);
    }
    
    fn rlc_e(cpu: &mut Cpu) {
        cpu.e = rlc(cpu, cpu.e);
    }
    
    fn rlc_h(cpu: &mut Cpu) {
        cpu.h = rlc(cpu, cpu.h);
    }
    
    fn rlc_l(cpu: &mut Cpu) {
        cpu.l = rlc(cpu, cpu.l);
    }
    
    
    fn rlc_mhl(cpu: &mut Cpu) {
        let hl = cpu.hl();
        let byte = cpu.mmu.read(hl);
        let result = rlc(cpu, byte);
        cpu.mmu.write(hl, result);
    }
    
    
    fn rlc_a(cpu: &mut Cpu) {
        cpu.a = rlc(cpu, cpu.a);
    }
    
    
    fn rrc_b(cpu: &mut Cpu) {
        cpu.b = rrc(cpu, cpu.b);
    }
    
    fn rrc_c(cpu: &mut Cpu) {
        cpu.c = rrc(cpu, cpu.c);
    }
    
    fn rrc_d(cpu: &mut Cpu) {
        cpu.d = rrc(cpu, cpu.d);
    }
    
    fn rrc_e(cpu: &mut Cpu) {
        cpu.e = rrc(cpu, cpu.e);
    }
    
    fn rrc_h(cpu: &mut Cpu) {
        cpu.h = rrc(cpu, cpu.h);
    }
    
    fn rrc_l(cpu: &mut Cpu) {
        cpu.l = rrc(cpu, cpu.l);
    }
    
    
    fn rrc_mhl(cpu: &mut Cpu) {
        let hl = cpu.hl();
        let byte = cpu.mmu.read(hl);
        let result = rrc(cpu, byte);
        cpu.mmu.write(hl, result);
    }
    
    
    fn rrc_a(cpu: &mut Cpu) {
        cpu.l = rrc(cpu, cpu.a);
    }
    
    
    fn rl_b(cpu: &mut Cpu) {
        cpu.b = rl(cpu, cpu.b);
    }
    
    
    fn rl_c(cpu: &mut Cpu) {
        cpu.c = rl(cpu, cpu.c);
    }
    
    
    fn rl_d(cpu: &mut Cpu) {
        cpu.d = rl(cpu, cpu.d);
    }
    
    fn rl_e(cpu: &mut Cpu) {
        cpu.e = rl(cpu, cpu.e);
    }
    
    fn rl_h(cpu: &mut Cpu) {
        cpu.h = rl(cpu, cpu.h);
    }
    
    fn rl_l(cpu: &mut Cpu) {
        cpu.l = rl(cpu, cpu.l);
    }
    
    fn rl_mhl(cpu: &mut Cpu) {
        let hl = cpu.hl();
        let byte = cpu.mmu.read(hl);
        let result = rl(cpu, byte);
        cpu.mmu.write(hl, result);
    }
    
    fn rl_a(cpu: &mut Cpu) {
        cpu.a = rl(cpu, cpu.a);
    }
    
    fn rr_b(cpu: &mut Cpu) {
        cpu.b = rr(cpu, cpu.b);
    }
    
    
    fn rr_c(cpu: &mut Cpu) {
        cpu.c = rr(cpu, cpu.c);
    }
    
    fn rr_d(cpu: &mut Cpu) {
        cpu.d = rr(cpu, cpu.d);
    }
    
    
    fn rr_e(cpu: &mut Cpu) {
        cpu.e = rr(cpu, cpu.e);
    }
    
    
    fn rr_h(cpu: &mut Cpu) {
        cpu.h = rr(cpu, cpu.h);
    }
    
    fn rr_l(cpu: &mut Cpu) {
        cpu.l = rr(cpu, cpu.l);
    }
    
    fn rr_mhl(cpu: &mut Cpu) {
        let hl = cpu.hl();
        let byte = cpu.mmu.read(hl);
        let result = rr(cpu, byte);
        cpu.mmu.write(hl, result);
    }
    
    fn rr_a(cpu: &mut Cpu) {
        cpu.l = rr(cpu, cpu.a);
    }
    
    
    fn sla_b(cpu: &mut Cpu) {
        cpu.b = sla(cpu, cpu.b);
    }
    
    
    fn sla_c(cpu: &mut Cpu) {
        cpu.c = sla(cpu, cpu.c);
    }
    
    fn sla_d(cpu: &mut Cpu) {
        cpu.d = sla(cpu, cpu.d);
    }
    
    fn sla_e(cpu: &mut Cpu) {
        cpu.e = sla(cpu, cpu.e);
    }
    
    fn sla_h(cpu: &mut Cpu) {
        cpu.h = sla(cpu, cpu.h);
    }
    
    fn sla_l(cpu: &mut Cpu) {
        cpu.l = sla(cpu, cpu.l);
    }
    
    fn sla_mhl(cpu: &mut Cpu) {
        let hl = cpu.hl();
        let byte = cpu.mmu.read(hl);
        let result = sla(cpu, byte);
        cpu.mmu.write(hl, result);
    }
    
    
    fn sla_a(cpu: &mut Cpu) {
        cpu.a = sla(cpu, cpu.a);
    }
    
    
    fn swap_a(cpu: &mut Cpu) {
        cpu.a = swap(cpu, cpu.a)
    }
    
    
    fn srl_b(cpu: &mut Cpu) {
        cpu.b = srl(cpu, cpu.b);
    }
    
    
    fn bit_0_d(cpu: &mut Cpu) {
        bit_d(cpu, 0);
    }
    
    
    fn bit_7_h(cpu: &mut Cpu) {
        bit_h(cpu, 7);
    }
    
    
    fn bit_7_l(cpu: &mut Cpu) {
        bit_l(cpu, 7);
    }
    
    fn bit_7_a(cpu: &mut Cpu) {
        bit_a(cpu, 7);
    }
    
    
    fn res_0_a(cpu: &mut Cpu) {
        cpu.a = res(cpu.a, 0);
    }
    
    
    fn res_7_mhl(cpu: &mut Cpu) {
        let hl = cpu.hl();
        let byte = cpu.mmu.read(hl);
        let value = res(byte, 7);
        cpu.mmu.write(hl, value);
    }
    
    
    fn set_3_mhl(cpu: &mut Cpu) {
        let hl = cpu.hl();
        let byte = cpu.mmu.read(hl);
        let value = set(byte, 3);
        cpu.mmu.write(hl, value);
    }
    
    
    fn set_4_a(cpu: &mut Cpu) {
        cpu.a = set(cpu.a, 4);
    }
    
    /// Helper function to set one bit in a u8.
    fn set(value: u8, bit: u8) -> u8 {
        value | (1u8 << (bit as usize))
    }
    
    
    /// Helper function to clear one bit in a u8
    fn res(value: u8, bit: u8) -> u8 {
        value & !(1u8 << (bit as usize))
    }
    
    
    /// Helper function that rotates (shifts) left the given
    
    /// byte (probably from a register) and updates the
    /// proper flag registers.
    
    fn rl(cpu: &mut Cpu, value: u8) -> u8 {
    
        let carry = cpu.get_carry();
    
    
        cpu.set_carry(value & 0x80 == 0x80);
    
        let result = (value << 1) | carry as u8;
    
        cpu.set_sub(false);
        cpu.set_zero(result == 0);
        cpu.set_half_carry(false);
    
        result
    }
    
    
    fn rlc(cpu: &mut Cpu, value: u8) -> u8 {
        cpu.set_carry(value & 0x80 == 0x80);
    
        let result = (value << 1) | (value >> 7);
    
        cpu.set_sub(false);
        cpu.set_zero(result == 0);
        cpu.set_half_carry(false);
    
        result
    }
    
    
    /// Helper function that rotates (shifts) right the given
    /// byte (probably from a register) and updates the
    /// proper flag registers.
    fn rr(cpu: &mut Cpu, value: u8) -> u8 {
        let carry = cpu.get_carry();
    
        cpu.set_carry(value & 0x01 == 0x01);
    
        let result = (value >> 1) | ((carry as u8) << 7);
    
    
        cpu.set_sub(false);
        cpu.set_zero(result == 0);
        cpu.set_half_carry(false);
    
        result
    }
    
    
    fn rrc(cpu: &mut Cpu, value: u8) -> u8 {
        cpu.set_carry(value & 0x01 == 0x01);
    
        let result = (value >> 1) | (value << 7);
    
        cpu.set_sub(false);
        cpu.set_zero(result == 0);
        cpu.set_half_carry(false);
    
        result
    }
    
    
    /// Helper function to test one bit in a u8.
    /// Returns true if bit is 0.
    fn bit_zero(val: u8, bit: u8) -> bool {
        (val & (1u8 << (bit as usize))) == 0
    }
    
    
    fn bit_d(cpu: &mut Cpu, bit: u8) {
        cpu.set_sub(false);
        cpu.set_zero(bit_zero(cpu.d, bit));
        cpu.set_half_carry(true);
    }
    
    
    fn bit_h(cpu: &mut Cpu, bit: u8) {
        cpu.set_sub(false);
        cpu.set_zero(bit_zero(cpu.h, bit));
        cpu.set_half_carry(true);
    }
    
    
    fn bit_l(cpu: &mut Cpu, bit: u8) {
        cpu.set_sub(false);
        cpu.set_zero(bit_zero(cpu.l, bit));
        cpu.set_half_carry(true);
    }
    
    fn bit_a(cpu: &mut Cpu, bit: u8) {
        cpu.set_sub(false);
        cpu.set_zero(bit_zero(cpu.a, bit));
        cpu.set_half_carry(true);
    }
    
    
    fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
        let first = first as u32;
        let second = second as u32;
    
    
        let result = first.wrapping_add(second);
        let result_b = result as u8;
    
    
        cpu.set_sub(false);
    
        cpu.set_zero(result_b == 0);
        cpu.set_half_carry((first ^ second ^ result) & 0x10 == 0x10);
        cpu.set_carry(result & 0x100 == 0x100);
    
        result_b
    
    fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
        let first = first as u32;
        let second = second as u32;
        let carry = cpu.get_carry() as u32;
    
        let result = first.wrapping_add(second).wrapping_add(carry);
        let result_b = result as u8;
    
        cpu.set_sub(false);
        cpu.set_zero(result_b == 0);
        cpu.set_half_carry((first ^ second ^ result) & 0x10 == 0x10);
        cpu.set_carry(result & 0x100 == 0x100);
    
        result_b
    }
    
    
    fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
        let first = first as u32;
        let second = second as u32;
    
    
        let result = first.wrapping_sub(second);
        let result_b = result as u8;
    
    
        cpu.set_sub(true);
    
        cpu.set_zero(result_b == 0);
        cpu.set_half_carry((first ^ second ^ result) & 0x10 == 0x10);
        cpu.set_carry(result & 0x100 == 0x100);
    
        result_b
    
    fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
        let first = first as u32;
        let second = second as u32;
        let carry = cpu.get_carry() as u32;
    
        let result = first.wrapping_sub(second).wrapping_sub(carry);
        let result_b = result as u8;
    
        cpu.set_sub(true);
        cpu.set_zero(result_b == 0);
        cpu.set_half_carry((first ^ second ^ result) & 0x10 == 0x10);
        cpu.set_carry(result & 0x100 == 0x100);
    
        result_b
    }
    
    
    fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 {
        let first = first as u32;
        let second = second as u32;
    
        let result = first.wrapping_add(second);
    
    
        cpu.set_sub(false);
    
        cpu.set_half_carry((first ^ second ^ result) & 0x1000 == 0x1000);
        cpu.set_carry(result & 0x10000 == 0x10000);
    
        result as u16
    
    }
    
    fn swap(cpu: &mut Cpu, value: u8) -> u8 {
        cpu.set_sub(false);
        cpu.set_zero(value == 0);
        cpu.set_half_carry(false);
        cpu.set_carry(false);
    
        (value << 4) | (value >> 4)
    }
    
    
    /// Helper function to shift an `u8` to the left and update CPU
    /// flags.
    
    fn sla(cpu: &mut Cpu, value: u8) -> u8 {
    
        let result = value << 1;
    
        cpu.set_sub(false);
        cpu.set_zero(result == 0);
        cpu.set_half_carry(false);
        cpu.set_carry(value & 0x80 != 0);
    
        result
    }
    
    
    fn srl(cpu: &mut Cpu, value: u8) -> u8 {
        let result = value >> 1;
    
        cpu.set_sub(false);
        cpu.set_zero(result == 0);
        cpu.set_half_carry(false);
        cpu.set_carry(value & 0x01 == 0x01);
    
        result
    }
    
    
    /// Helper function for RST instructions, pushes the
    /// current PC to the stack and jumps to the provided
    /// address.
    fn rst(cpu: &mut Cpu, addr: u16) {
        cpu.push_word(cpu.pc);
        cpu.pc = addr;
    }