1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use self::super::super::{AluOperationShiftOrRotateDirection, AluOperationShiftOrRotateType, AluOperation};
enum RespectCarry {
No,
YesAdd,
YesSub,
}
impl AluOperation {
pub(in self::super::super) fn perform_impl(self, lhs: u8, rhs: u8, carry: &mut bool) -> u8 {
match self {
AluOperation::Add => add(lhs, rhs, carry, RespectCarry::No),
AluOperation::Sub => add(lhs, (!rhs).checked_add(1).unwrap_or(0), carry, RespectCarry::No),
AluOperation::AddC => add(lhs, rhs, carry, RespectCarry::YesAdd),
AluOperation::SubC => add(lhs, (!rhs).checked_add(1).unwrap_or(0), carry, RespectCarry::YesSub),
AluOperation::Not => !lhs,
AluOperation::Or => lhs | rhs,
AluOperation::Xor => lhs ^ rhs,
AluOperation::And => lhs & rhs,
AluOperation::ShiftOrRotate { d: AluOperationShiftOrRotateDirection::Left, tt } => {
let new_carry = (lhs & 0b1000_0000) != 0;
let ret = match tt {
AluOperationShiftOrRotateType::Lsf |
AluOperationShiftOrRotateType::Asf => lhs << 1,
AluOperationShiftOrRotateType::Rtc => {
let carry_mask = if *carry { 0b0000_0001 } else { 0b0000_0000 };
(lhs << 1) | carry_mask
}
AluOperationShiftOrRotateType::Rtw => lhs.rotate_left(1),
};
*carry = new_carry;
ret
}
AluOperation::ShiftOrRotate { d: AluOperationShiftOrRotateDirection::Right, tt } => {
let new_carry = (lhs & 0b0000_0001) != 0;
let ret = match tt {
AluOperationShiftOrRotateType::Lsf => lhs >> 1,
AluOperationShiftOrRotateType::Asf => {
let msb_mask = lhs & 0b1000_0000;
(lhs >> 1) | msb_mask
}
AluOperationShiftOrRotateType::Rtc => {
let carry_mask = if *carry { 0b1000_0000 } else { 0b0000_0000 };
(lhs >> 1) | carry_mask
}
AluOperationShiftOrRotateType::Rtw => lhs.rotate_right(1),
};
*carry = new_carry;
ret
}
}
}
}
fn add(lhs: u8, rhs: u8, carry: &mut bool, respect: RespectCarry) -> u8 {
let mut sum = (lhs as u16) + (rhs as u16);
match (*carry, respect) {
(false, _) |
(true, RespectCarry::No) => {}
(true, RespectCarry::YesAdd) => sum += 1,
(true, RespectCarry::YesSub) => sum -= 1,
}
*carry = (sum & 0b1_0000_0000) != 0;
(sum & 0b1111_1111) as u8
}