Skip to main content

monistode_emulator/
arithmetic.rs

1use super::flag_register::{FlagRegister, ProcessorFlags};
2use super::num_type_conversions::ToSigned;
3use num_traits::{
4    ops::overflowing::{OverflowingAdd, OverflowingMul, OverflowingSub},
5    Zero,
6};
7use std::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
8
9pub trait ArithmeticOperand:
10    Zero
11    + PartialEq
12    + ToSigned
13    + OverflowingAdd
14    + OverflowingSub
15    + OverflowingMul
16    + BitAnd<Self, Output = Self>
17    + BitOr<Self, Output = Self>
18    + BitXor<Self, Output = Self>
19    + Not<Output = Self>
20    + Shl<Self, Output = Self>
21    + Shr<Self, Output = Self>
22{
23}
24impl<
25        T: Zero
26            + PartialEq
27            + ToSigned
28            + OverflowingAdd
29            + OverflowingSub
30            + OverflowingMul
31            + BitAnd<T, Output = T>
32            + BitOr<T, Output = T>
33            + BitXor<T, Output = T>
34            + Not<Output = T>
35            + Shl<T, Output = T>
36            + Shr<T, Output = T>,
37    > ArithmeticOperand for T
38{
39}
40
41trait FlagRegisterExt: FlagRegister {
42    fn set_zf_if_zero<T: Zero>(&mut self, value: &T)
43    where
44        Self: Sized;
45
46    fn set_sf_if_negative<T: ArithmeticOperand>(&mut self, value: &T)
47    where
48        Self: Sized;
49}
50
51impl<T: FlagRegister> FlagRegisterExt for T {
52    #[inline]
53    fn set_zf_if_zero<U: Zero>(&mut self, value: &U) {
54        self.set_if(value.is_zero(), ProcessorFlags::ZF);
55    }
56
57    #[inline]
58    fn set_sf_if_negative<U: ArithmeticOperand>(&mut self, value: &U) {
59        self.set_if(
60            value.as_signed() < U::SignedVariant::zero(),
61            ProcessorFlags::SF,
62        );
63    }
64}
65
66#[inline]
67pub fn add<T, U>(flags: &mut U, a: T, b: T) -> T
68where
69    T: ArithmeticOperand,
70    U: FlagRegister,
71{
72    let result = a.overflowing_add(&b);
73    flags.reset();
74    flags.set_if(result.1, ProcessorFlags::CF);
75    flags.set_if(
76        a.as_signed().overflowing_add(&b.as_signed()).1,
77        ProcessorFlags::OF,
78    );
79    flags.set_zf_if_zero(&result.0);
80    flags.set_sf_if_negative(&result.0);
81
82    result.0
83}
84
85#[inline]
86pub fn addc<T, U>(flags: &mut U, a: T, b: T) -> T
87where
88    T: ArithmeticOperand,
89    U: FlagRegister,
90{
91    let raw_sum = a.overflowing_add(&b);
92    let result = raw_sum
93        .0
94        .overflowing_add(&if flags.get(ProcessorFlags::CF) {
95            T::one()
96        } else {
97            T::zero()
98        });
99    flags.reset();
100    flags.set_if(result.1 || raw_sum.1, ProcessorFlags::CF);
101    flags.set_if(
102        a.as_signed().overflowing_add(&b.as_signed()).1
103            || a.as_signed()
104                .overflowing_add(&b.as_signed())
105                .0
106                .overflowing_add(&if flags.get(ProcessorFlags::CF) {
107                    T::one().as_signed()
108                } else {
109                    T::zero().as_signed()
110                })
111                .1,
112        ProcessorFlags::OF,
113    );
114    flags.set_zf_if_zero(&result.0);
115    flags.set_sf_if_negative(&result.0);
116
117    result.0
118}
119
120#[inline]
121pub fn inc<T, U>(flags: &mut U, a: T) -> T
122where
123    T: ArithmeticOperand,
124    U: FlagRegister,
125{
126    let result = a.overflowing_add(&T::one());
127    flags.reset();
128    flags.set_if(result.1, ProcessorFlags::CF);
129    flags.set_if(
130        a.as_signed().overflowing_add(&T::one().as_signed()).1,
131        ProcessorFlags::OF,
132    );
133    flags.set_zf_if_zero(&result.0);
134    flags.set_sf_if_negative(&result.0);
135
136    result.0
137}
138
139#[inline]
140pub fn test<T, U>(flags: &mut U, a: T, b: T) -> T
141where
142    T: ArithmeticOperand,
143    U: FlagRegister,
144{
145    let result = a.overflowing_add(&b);
146    flags.reset();
147    flags.set_if(result.1, ProcessorFlags::CF);
148    flags.clear(ProcessorFlags::OF);
149    flags.set_zf_if_zero(&result.0);
150    flags.set_sf_if_negative(&result.0);
151
152    a
153}
154
155#[inline]
156pub fn dec<T, U>(flags: &mut U, a: T) -> T
157where
158    T: ArithmeticOperand,
159    U: FlagRegister,
160{
161    let result = a.overflowing_sub(&T::one());
162    flags.reset();
163    flags.set_if(!result.1, ProcessorFlags::CF);
164    flags.set_if(
165        a.as_signed().overflowing_sub(&T::one().as_signed()).1,
166        ProcessorFlags::OF,
167    );
168    flags.set_zf_if_zero(&result.0);
169    flags.set_sf_if_negative(&result.0);
170
171    result.0
172}
173
174#[inline]
175pub fn sub<T, U>(flags: &mut U, a: T, b: T) -> T
176where
177    T: ArithmeticOperand,
178    U: FlagRegister,
179{
180    let result = a.overflowing_sub(&b);
181    flags.reset();
182    flags.set_if(!result.1, ProcessorFlags::CF);
183    flags.set_if(
184        a.as_signed().overflowing_sub(&b.as_signed()).1,
185        ProcessorFlags::OF,
186    );
187    flags.set_zf_if_zero(&result.0);
188    flags.set_sf_if_negative(&result.0);
189
190    result.0
191}
192
193#[inline]
194pub fn cmp<T, U>(flags: &mut U, a: T, b: T) -> T
195where
196    T: ArithmeticOperand,
197    U: FlagRegister,
198{
199    let result = a.overflowing_sub(&b);
200    flags.reset();
201    flags.set_if(!result.1, ProcessorFlags::CF);
202    flags.set_if(
203        a.as_signed().overflowing_sub(&b.as_signed()).1,
204        ProcessorFlags::OF,
205    );
206    flags.set_zf_if_zero(&result.0);
207    flags.set_sf_if_negative(&result.0);
208
209    a
210}
211
212#[inline]
213pub fn mul<T, U>(flags: &mut U, a: T, b: T) -> T
214where
215    T: ArithmeticOperand,
216    U: FlagRegister,
217{
218    let result = a.overflowing_mul(&b);
219    flags.reset();
220    flags.set_if(result.1, ProcessorFlags::CF);
221    flags.set_if(
222        a.as_signed().overflowing_mul(&b.as_signed()).1,
223        ProcessorFlags::OF,
224    );
225    flags.set_zf_if_zero(&result.0);
226    flags.set_sf_if_negative(&result.0);
227
228    result.0
229}
230
231#[inline]
232pub fn div<T, U>(flags: &mut U, a: T, b: T) -> T
233where
234    T: ArithmeticOperand,
235    U: FlagRegister,
236{
237    flags.reset();
238    if b.is_zero() {
239        flags.set(ProcessorFlags::CF);
240        flags.set(ProcessorFlags::OF);
241        return T::zero();
242    }
243    flags.set_zf_if_zero(&a);
244
245    a / b
246}
247
248#[inline]
249pub fn and<T, U>(flags: &mut U, a: T, b: T) -> T
250where
251    T: ArithmeticOperand,
252    U: FlagRegister,
253{
254    let result = a & b;
255    flags.reset();
256    flags.set_zf_if_zero(&result);
257    flags.set_sf_if_negative(&result);
258
259    result
260}
261
262#[inline]
263pub fn or<T, U>(flags: &mut U, a: T, b: T) -> T
264where
265    T: ArithmeticOperand,
266    U: FlagRegister,
267{
268    let result = a | b;
269    flags.reset();
270    flags.set_zf_if_zero(&result);
271    flags.set_sf_if_negative(&result);
272
273    result
274}
275
276#[inline]
277pub fn xor<T, U>(flags: &mut U, a: T, b: T) -> T
278where
279    T: ArithmeticOperand,
280    U: FlagRegister,
281{
282    let result = a ^ b;
283    flags.reset();
284    flags.set_zf_if_zero(&result);
285    flags.set_sf_if_negative(&result);
286
287    result
288}
289
290#[inline]
291pub fn not<T, U>(flags: &mut U, a: T) -> T
292where
293    T: ArithmeticOperand,
294    U: FlagRegister,
295{
296    let result = !a;
297    flags.reset();
298    flags.set_zf_if_zero(&result);
299    flags.set_if(!flags.get(ProcessorFlags::SF), ProcessorFlags::SF);
300
301    result
302}
303
304#[inline]
305pub fn shl<T, U>(flags: &mut U, a: T, b: T) -> T
306where
307    T: ArithmeticOperand,
308    U: FlagRegister,
309{
310    let result = a << b;
311    flags.reset();
312    // TODO
313
314    result
315}
316
317#[inline]
318pub fn shr<T, U>(flags: &mut U, a: T, b: T) -> T
319where
320    T: ArithmeticOperand,
321    U: FlagRegister,
322{
323    let result = a >> b;
324    flags.reset();
325    // TODO
326
327    result
328}