-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathalu.c
177 lines (147 loc) · 2.8 KB
/
alu.c
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include <gamegirl.h>
#include <flags.h>
/*
alu.c
This file contains the source code that implements basic
arithmetic-logic-unit tasks (Register increment, decrement...)
to enhance code readability and simplify code.
*/
// Register increment (Lone-pair-register exclusive)
uint8_t increment(m_dmg_t *m_dmg, uint8_t m_register)
{
/*
Check if we need to enable half-carry bit
Mask the lower nibble of the register and
compare it with 0b00001111
*/
#ifdef PREC23
if ((m_register & 0xF) == 0xF)
#else
if ((m_register & 0b00001111) == 0b00001111)
#endif
{
// Set the Half-Carry bit
FLAG_SET(HALF);
}
else
{
// Clear the Half-Carry bit
FLAG_UNSET(HALF);
}
// Increment the register value
m_register++;
// Check if register value is not zero
if (m_register != 0)
{
// Unset the Zero (Result) flag
FLAG_UNSET(ZERO);
}
else
{
// Set the Zero (Result) flag
FLAG_SET(ZERO);
}
// Finally, clear the negative flag as we're dealing with increments
FLAG_UNSET(NGTV);
return m_register;
}
// Register decrement (Lone-pair-register exclusive)
uint8_t decrement(m_dmg_t *m_dmg, uint8_t m_register)
{
// Check if we need to enable half-carry bit
if (m_register & 0x0F)
{
// Clear the Half-Carry bit
FLAG_UNSET(HALF);
}
else
{
// Set the Half-Carry bit
FLAG_SET(HALF);
}
// Decrement the register value
m_register--;
// Check if register value is not zero
if (m_register)
{
FLAG_UNSET(ZERO);
}
else
{
FLAG_SET(ZERO);
}
// Finally, set the negative bit in flags register as we just decremented a register
FLAG_SET(NGTV);
return m_register;
}
uint8_t addition(m_dmg_t *m_dmg, uint8_t *m_register, uint8_t m_value)
{
uint32_t m_result = *m_register + m_value;
uint32_t m_bits = *m_register ^ m_value ^ m_result;
*m_register = (uint8_t) (m_result & 0x00FF);
FLAG_UNSET(ZERO);
FLAG_UNSET(NGTV);
FLAG_UNSET(CRRY);
FLAG_UNSET(HALF);
if (*m_register == 0)
{
FLAG_SET(ZERO);
}
if ((m_bits & 0x100) != 0)
{
FLAG_SET(CRRY);
}
if ((m_bits & 0x10) != 0)
{
FLAG_SET(HALF);
}
return *m_register;
}
uint16_t word_addition(m_dmg_t *m_dmg, uint16_t *m_register, uint16_t m_value)
{
uint64_t m_result = *m_register + m_value;
if (m_result & 0xffff0000)
{
FLAG_SET(CRRY);
}
else
{
FLAG_UNSET(CRRY);
}
*m_register = (uint16_t) (m_result & 0xffff);
if (((*m_register & 0x0f) + (m_value & 0x0f)) > 0x0f)
{
FLAG_SET(HALF);
}
else
{
FLAG_UNSET(HALF);
}
FLAG_UNSET(NGTV);
return *m_register;
}
uint8_t or(m_dmg_t *m_dmg, uint8_t m_register)
{
A_REG |= m_register;
if (A_REG)
{
FLAG_UNSET(ZERO);
}
else
{
FLAG_SET(ZERO);
}
#ifdef PREC23
FLAG_UNSET(CRRY | NGTV | HALF);
#else
FLAG_UNSET(CRRY);
FLAG_UNSET(NGTV);
FLAG_UNSET(HALF);
#endif
return m_register;
}
uint8_t set_bit(uint8_t m_var, uint8_t m_bit)
{
m_var |= m_bit;
return m_var;
}