iz80/
operators.rs

1use super::environment::Environment;
2use super::registers::Flag;
3
4pub type Operator = fn(&mut Environment, u8, u8) -> u8;
5
6pub fn operator_add(env: &mut Environment, a: u8, b: u8) -> u8 {
7    env.state.reg.clear_flag(Flag::C);
8    operator_adc(env, a, b)
9}
10
11pub fn operator_adc(env: &mut Environment, a: u8, b: u8) -> u8 {
12    let aa = a as u16;
13    let bb = b as u16;
14    let mut vv = aa + bb;
15    if env.state.reg.get_flag(Flag::C) {
16        vv += 1;
17    }
18    env.state.reg.update_arithmetic_flags(aa, bb, vv, false, true);
19    vv as u8
20}
21
22pub fn operator_add16(env: &mut Environment, aa: u16, bb: u16) -> u16 {
23    let aaaa = aa as u32;
24    let bbbb = bb as u32;
25    let vvvv = aaaa + bbbb;
26
27    env.state.reg.update_add16_flags(aaaa, bbbb, vvvv);
28    vvvv as u16
29}
30
31pub fn operator_adc16(env: &mut Environment, aa: u16, bb: u16) -> u16 {
32    let aaaa = aa as u32;
33    let bbbb = bb as u32;
34    let mut vvvv = aaaa.wrapping_add(bbbb);
35    if env.state.reg.get_flag(Flag::C) {
36        vvvv = vvvv.wrapping_add(1);
37    }
38    let vv = vvvv as u16;
39
40    // TUZD-8.6
41    env.state.reg.update_arithmetic_flags_16(aaaa, bbbb, vvvv, false);
42    env.state.reg.put_flag(Flag::Z, vv == 0);
43    vv
44}
45
46pub fn operator_sbc16(env: &mut Environment, aa: u16, bb: u16) -> u16 {
47    let aaaa = aa as u32;
48    let bbbb = bb as u32;
49    let mut vvvv = aaaa.wrapping_sub(bbbb);
50    if env.state.reg.get_flag(Flag::C) {
51        vvvv = vvvv.wrapping_sub(1);
52    }
53    let vv = vvvv as u16;
54
55    // TUZD-8.6
56    env.state.reg.update_arithmetic_flags_16(aaaa, bbbb, vvvv, true);
57    env.state.reg.put_flag(Flag::Z, vv == 0);
58    vv
59}
60
61pub fn operator_inc(env: &mut Environment, a: u8) -> u8 {
62    let aa = a as u16;
63    let vv = aa + 1;
64    env.state.reg.update_arithmetic_flags(aa, 0, vv, false, false);
65    vv as u8
66}
67
68pub fn operator_sub(env: &mut Environment, a: u8, b: u8) -> u8 {
69    env.state.reg.clear_flag(Flag::C);
70    operator_sbc(env, a, b)
71}
72
73pub fn operator_sbc(env: &mut Environment, a: u8, b: u8) -> u8 {
74    let aa = a as u16;
75    let bb = b as u16;
76    let mut vv = aa.wrapping_sub(bb);
77    if env.state.reg.get_flag(Flag::C) {
78        vv = vv.wrapping_sub(1);
79    }
80    env.state.reg.update_arithmetic_flags(aa, bb, vv, true, true);
81    vv as u8
82}
83
84pub fn operator_dec(env: &mut Environment, a: u8) -> u8 {
85    let aa = a as u16;
86    let vv = aa.wrapping_sub(1);
87    env.state.reg.update_arithmetic_flags(aa, 0, vv, true, false);
88    vv as u8
89}
90
91pub fn operator_and(env: &mut Environment, a: u8, b: u8) -> u8 {
92    let v = a & b;
93    env.state.reg.update_logic_flags(a, b, v, true);
94    v
95}
96
97pub fn operator_xor(env: &mut Environment, a: u8, b: u8) -> u8 {
98    let v = a ^ b;
99    env.state.reg.update_logic_flags(a, b, v, false);
100    v
101}
102
103pub fn operator_or(env: &mut Environment, a: u8, b: u8) -> u8 {
104    let v = a | b;
105    env.state.reg.update_logic_flags(a, b, v, false);
106    v
107}
108
109pub fn operator_cp(env: &mut Environment, a: u8, b: u8) -> u8 {
110    env.state.reg.clear_flag(Flag::C);
111    operator_sub(env, a, b);
112
113    // Note: flags 3 and 5 are taken from b. TUZD-8.4
114    env.state.reg.update_undocumented_flags(b);
115    a // Do not update the accumulator
116}