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 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 result
328}