1use crate::prelude::*;
2use core::{mem, ops::{Shl, ShlAssign}};
3
4#[cfg(target_endian="little")]
7#[derive(Debug, Clone, Copy, PartialEq)]
8#[repr(u8)]
9pub enum Register {
10 A = 6,
11 B = 1,
12 C = 0,
13 D = 3,
14 E = 2,
15 H = 5,
16 L = 4,
17}
18
19#[cfg(target_endian="big")]
20#[derive(Debug, Clone, Copy, PartialEq)]
21#[repr(u8)]
22pub enum Register {
23 A = 6,
24 B = 0,
25 C = 1,
26 D = 2,
27 E = 3,
28 H = 4,
29 L = 5,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq)]
36#[repr(u8)]
37pub enum Double {
38 BC = 0,
39 DE = 1,
40 HL = 2,
41}
42
43use self::{Register as R, Double as D, Internal as I, Word as W};
44
45#[derive(Debug, Clone, Copy, PartialEq)]
47pub enum Byte {
48 Single(Register),
50 Indirect,
52 RAM(u16),
54}
55
56#[derive(Debug, Clone, Copy, PartialEq)]
59pub enum Internal {
60 Wide(Double),
61 ProgramCounter,
62 StackPointer,
63}
64#[doc(hidden)]
65#[derive(Debug, Clone, Copy, PartialEq)]
66pub enum Word {
67 OnBoard(Internal),
68 ProgramStatus,
69 RAM(u16),
70 Stack,
71}
72
73#[disclose(super)]
74impl State {
75 pub fn flags(&self) -> raw::u8 {
84 self.c as raw::u8 |
85 0b10u8 |
86 (self.p as raw::u8) << 2 |
87 (self.a as raw::u8) << 4 |
88 (self.z as raw::u8) << 6 |
89 (self.m as raw::u8) << 7
90 }
91 pub fn is_stopped(&self) -> bool { !self.active }
97 pub fn is_interrupt_ready(&self) -> bool { self.interrupts }
101 fn extract_flags(&mut self, bits: raw::u8) {
102 (self.c, self.p, self.a, self.z, self.m) = (
103 bits & 0b00000001 != 0,
104 bits & 0b00000100 != 0,
105 bits & 0b00010000 != 0,
106 bits & 0b01000000 != 0,
107 bits & 0b10000000 != 0,
108 );
109 }
110 #[must_use]
111 fn update_flags(&mut self) -> &mut bool {
112 self.update_flags_for(self[Register::A])
113 }
114 #[must_use]
115 fn update_flags_for(&mut self, value: u8) -> &mut bool {
116 let value = value.0;
117 let mut parity = value;
118 for offset in [4, 2, 1] {
119 parity ^= parity >> offset;
120 }
121 self.p = (parity & 0x01) == 0;
122 self.z = value == 0;
123 self.m = value & 0b1000_0000 != 0;
124 self.a = false;
125 &mut self.c
126 }
127 fn status(&self) -> u16 {
128 Wrapping(raw::u16::from_le_bytes([self[Register::A].0, self.flags()]))
129 }
130
131 fn push(&mut self) -> u16 {
132 self.sp -= 2;
133 self.sp
134 }
135
136 fn pop(&mut self) -> u16 {
137 let address = self.sp;
138 self.sp += 2;
139 address
140 }
141
142 fn resolve(&self, target: Byte) -> Byte {
143 match target {
144 Byte::Indirect => Byte::RAM(self[D::HL]),
145 _ => target
146 }
147 }
148}
149
150impl Index<Register> for State {
151 type Output = u8;
152 fn index(&self, index: Register) -> &Self::Output { &self.register[index as usize] }
153}
154
155impl IndexMut<Register> for State {
156 fn index_mut(&mut self, index: Register) -> &mut Self::Output { &mut self.register[index as usize] }
157}
158
159impl Index<Double> for State {
160 type Output = u16;
161 fn index(&self, index: Double) -> &Self::Output {
162 let index = 2 * index as raw::u8;
163 unsafe{ mem::transmute::<&u8, &Self::Output>(&self.register[index as usize]) }
164 }
165}
166
167impl IndexMut<Double> for State {
168 fn index_mut(&mut self, index: Double) -> &mut Self::Output {
169 let index = 2 * index as raw::u8;
170 unsafe{ mem::transmute::<&mut u8, &mut Self::Output>(&mut self.register[index as usize]) }
171 }
172}
173
174impl Index<Internal> for State {
175 type Output = u16;
176 fn index(&self, index: Internal) -> &Self::Output {
177 match index {
178 I::Wide(pair) => &self[pair],
179 I::ProgramCounter => &self.pc,
180 I::StackPointer => &self.sp,
181 }
182 }
183}
184
185impl IndexMut<Internal> for State {
186 fn index_mut(&mut self, index: Internal) -> &mut Self::Output {
187 match index {
188 I::Wide(pair) => &mut self[pair],
189 I::ProgramCounter => &mut self.pc,
190 I::StackPointer => &mut self.sp,
191 }
192 }
193}
194
195impl<H: Harness + ?Sized, C: BorrowMut<H>> Shl<&Machine<H, C>> for u16 {
196 type Output = u16;
197 fn shl(self, host: &Machine<H, C>) -> Self::Output {
198 host.read_word(self)
199 }
200}
201
202impl<H: Harness + ?Sized, C: BorrowMut<H>> Shl<&Machine<H, C>> for Word {
203 type Output = u16;
204 fn shl(self, host: &Machine<H, C>) -> Self::Output {
205 match self {
206 Self::OnBoard(internal) => host.chip[internal],
207 Self::ProgramStatus => {
208 Wrapping(raw::u16::from_le_bytes([host.chip.register[6].0, host.chip.flags()]))
209 }
210 Self::RAM(i) => host.read_word(i),
211 Self::Stack => panic!("Can't pop from stack without mutate access"),
212 }
213 }
214}
215
216impl<H: Harness + ?Sized, C: BorrowMut<H>> Shl<&mut Machine<H, C>> for Word {
217 type Output = u16;
218 fn shl(self, host: &mut Machine<H, C>) -> Self::Output {
219 match self {
220 Word::Stack => {
221 let addr = host.chip.sp;
222 host.chip.sp += 2;
223 host.read_word(addr)
224 }
225 _ => self << &*host,
226 }
227 }
228}
229
230impl<H: Harness + ?Sized, C: BorrowMut<H>> ShlAssign<(u16, u16)> for Machine<H, C> {
231 fn shl_assign(&mut self, (index, value): (u16, u16)) {
232 self.write_word(index, value);
233 }
234}
235
236impl<H: Harness + ?Sized, C: BorrowMut<H>> ShlAssign<(Word, u16)> for Machine<H, C> {
237 fn shl_assign(&mut self, (index, value): (Word, u16)) {
238 match index {
239 W::OnBoard(internal) => self.chip[internal] = value,
240 W::RAM(address) => self.write_word(address, value),
241 W::ProgramStatus => {
242 let [a, f] = value.0.to_le_bytes();
243 self.chip[R::A] = Wrapping(a);
244 self.chip.extract_flags(f);
245 }
246 W::Stack => {
247 self.chip.sp -= 2;
248 let sp = self.chip.sp;
249 self.write_word(sp, value);
250 }
251 }
252 }
253}