rustzx_z80/opcode/
internal_block.rs1use crate::{
2 opcode::BlockDir,
3 tables::{lookup8_r12, HALF_CARRY_SUB_TABLE, PARITY_TABLE, SZF3F5_TABLE},
4 RegName16, RegName8, Z80Bus, FLAG_CARRY, FLAG_F3, FLAG_F5, FLAG_HALF_CARRY, FLAG_PV, FLAG_SIGN,
5 FLAG_SUB, FLAG_ZERO, Z80,
6};
7
8pub fn execute_ldi_ldd(cpu: &mut Z80, bus: &mut impl Z80Bus, dir: BlockDir) {
10 let src = bus.read(cpu.regs.get_hl(), 3);
11 let bc = cpu.regs.dec_reg_16(RegName16::BC);
12 bus.write(cpu.regs.get_de(), src, 3);
13 bus.wait_loop(cpu.regs.get_de(), 2);
14 match dir {
15 BlockDir::Inc => {
16 cpu.regs.inc_reg_16(RegName16::HL);
17 cpu.regs.inc_reg_16(RegName16::DE);
18 }
19 BlockDir::Dec => {
20 cpu.regs.dec_reg_16(RegName16::HL);
21 cpu.regs.dec_reg_16(RegName16::DE);
22 }
23 }
24 let mut flags = cpu.regs.get_flags();
25 flags &= !(FLAG_SUB | FLAG_HALF_CARRY | FLAG_PV | FLAG_F3 | FLAG_F5);
26 flags |= (bc != 0) as u8 * FLAG_PV;
27 let src_plus_a = src.wrapping_add(cpu.regs.get_acc());
28 flags |= (src_plus_a & 0x08 != 0) as u8 * FLAG_F3;
29 flags |= (src_plus_a & 0x02 != 0) as u8 * FLAG_F5;
30 cpu.regs.set_flags(flags);
31 }
33
34pub fn execute_cpi_cpd(cpu: &mut Z80, bus: &mut impl Z80Bus, dir: BlockDir) -> bool {
36 let src = bus.read(cpu.regs.get_hl(), 3);
37 bus.wait_loop(cpu.regs.get_hl(), 5);
38 match dir {
39 BlockDir::Inc => {
40 cpu.regs.inc_reg_16(RegName16::HL);
41 cpu.regs.set_mem_ptr(cpu.regs.get_mem_ptr().wrapping_add(1));
42 }
43 BlockDir::Dec => {
44 cpu.regs.dec_reg_16(RegName16::HL);
45 cpu.regs.set_mem_ptr(cpu.regs.get_mem_ptr().wrapping_sub(1));
46 }
47 };
48 let bc = cpu.regs.dec_reg_16(RegName16::BC);
49 let acc = cpu.regs.get_acc();
50 let tmp = acc.wrapping_sub(src);
51 let mut flags = cpu.regs.get_flags() & FLAG_CARRY;
52 flags |= FLAG_SUB;
53 flags |= (bc != 0) as u8 * FLAG_PV;
54 flags |= (tmp == 0) as u8 * FLAG_ZERO;
55 flags |= tmp & FLAG_SIGN;
56 let lookup = lookup8_r12(acc, src, tmp);
57 let half_borrow = HALF_CARRY_SUB_TABLE[(lookup & 0x07) as usize];
58 flags |= half_borrow;
59 let tmp2 = if half_borrow != 0 {
60 tmp.wrapping_sub(1)
61 } else {
62 tmp
63 };
64 flags |= ((tmp2 & 0x08) != 0) as u8 * FLAG_F3;
65 flags |= ((tmp2 & 0x02) != 0) as u8 * FLAG_F5;
66 cpu.regs.set_flags(flags);
67 tmp == 0
69}
70
71pub fn execute_ini_ind(cpu: &mut Z80, bus: &mut impl Z80Bus, dir: BlockDir) -> u8 {
75 bus.wait_no_mreq(cpu.regs.get_ir(), 1);
76 let src = bus.read_io(cpu.regs.get_bc());
77 bus.write(cpu.regs.get_hl(), src, 3);
78 match dir {
79 BlockDir::Inc => {
80 cpu.regs.inc_reg_16(RegName16::HL);
81 cpu.regs.set_mem_ptr(cpu.regs.get_bc().wrapping_add(1));
82 }
83 BlockDir::Dec => {
84 cpu.regs.dec_reg_16(RegName16::HL);
85 cpu.regs.set_mem_ptr(cpu.regs.get_bc().wrapping_sub(1));
86 }
87 };
88 let b = cpu.regs.dec_reg_8(RegName8::B);
89 let mut flags = 0u8;
90 flags |= SZF3F5_TABLE[b as usize];
91 flags |= ((src & 0x80) != 0) as u8 * FLAG_SUB;
92 let c = match dir {
93 BlockDir::Inc => cpu.regs.get_reg_8(RegName8::C).wrapping_add(1),
94 BlockDir::Dec => cpu.regs.get_reg_8(RegName8::C).wrapping_sub(1),
95 };
96 let (k, k_carry) = c.overflowing_add(src);
98 flags |= k_carry as u8 * (FLAG_CARRY | FLAG_HALF_CARRY);
99 flags |= PARITY_TABLE[((k & 0x07) ^ b) as usize];
101 cpu.regs.set_flags(flags);
102
103 src
104}
105
106pub fn execute_outi_outd(cpu: &mut Z80, bus: &mut impl Z80Bus, dir: BlockDir) -> u8 {
109 bus.wait_no_mreq(cpu.regs.get_ir(), 1);
110 let src = bus.read(cpu.regs.get_hl(), 3);
111 let b = cpu.regs.dec_reg_8(RegName8::B);
112
113 match dir {
114 BlockDir::Inc => {
115 cpu.regs.inc_reg_16(RegName16::HL);
116 cpu.regs.set_mem_ptr(cpu.regs.get_bc().wrapping_add(1));
117 }
118 BlockDir::Dec => {
119 cpu.regs.dec_reg_16(RegName16::HL);
120 cpu.regs.set_mem_ptr(cpu.regs.get_bc().wrapping_sub(1));
121 }
122 };
123
124 bus.write_io(cpu.regs.get_bc(), src);
125
126 let l = cpu.regs.get_l();
127 let mut flags = 0u8;
128 flags |= SZF3F5_TABLE[b as usize];
129 flags |= ((src & 0x80) != 0) as u8 * FLAG_SUB;
130 let (k, k_carry) = l.overflowing_add(src);
132 flags |= k_carry as u8 * (FLAG_CARRY | FLAG_HALF_CARRY);
133 flags |= PARITY_TABLE[((k & 0x07) ^ b) as usize];
135 cpu.regs.set_flags(flags);
136
137 src
138}