1#![cfg_attr(feature = "cargo-clippy", feature(tool_lints))]
10
11use std::fmt;
12
13use machine_int::MachineInt;
14
15use self::mi::Byte;
16
17pub use crate::mi::Addr;
18pub use crate::cmos::Cmos;
19pub use crate::nmos::Nmos;
20
21mod cmos;
22mod mi;
23mod nmos;
24
25#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
26pub enum NmiLength {
27 One,
28 Two,
29 Plenty,
30}
31
32pub trait Sys {
33 fn read(&mut self, addr: u16) -> Option<u8>;
34
35 fn write(&mut self, addr: u16, val: u8) -> Option<()>;
36
37 #[inline]
38 fn set_sync(&mut self, _set: bool) {}
39
40 #[inline]
41 fn poll_nmi(&mut self) -> bool {
42 false
43 }
44
45 #[inline]
46 fn peek_nmi(&self) -> bool {
47 false
48 }
49
50 #[inline]
51 fn nmi_length(&self) -> NmiLength {
52 NmiLength::Plenty
53 }
54
55 #[inline]
56 fn irq(&self) -> bool {
57 false
58 }
59}
60
61pub trait Cpu: Clone + fmt::Debug {
62 fn is_nmos(&self) -> bool;
63 fn reset(&mut self);
64 fn pc(&self) -> u16;
65 fn set_pc(&mut self, val: u16);
66 fn sp(&self) -> u8;
67 fn set_sp(&mut self, val: u8);
68 fn a(&self) -> u8;
69 fn set_a(&mut self, val: u8);
70 fn x(&self) -> u8;
71 fn set_x(&mut self, val: u8);
72 fn y(&self) -> u8;
73 fn set_y(&mut self, val: u8);
74 fn status(&self) -> u8;
75 fn set_status(&mut self, val: u8);
76 fn flag(&self, f: Status) -> bool;
77 fn set_flag(&mut self, f: Status, set: bool);
78 fn run_instruction<S: Sys>(&mut self, sys: &mut S) -> Option<()>;
79 fn instruction_cycle(&self) -> u32;
80 fn halted(&self) -> bool;
81}
82
83#[derive(Copy, Clone)]
84pub enum Status {
85 N,
86 V,
87 D,
88 I,
89 Z,
90 C,
91}
92
93#[derive(Clone, Default)]
94struct Flags {
95 n: Byte,
96 v: Byte,
97 _r: u8,
98 _b: u8,
99 d: bool,
100 i: bool,
101 z: Byte,
102 c: Byte,
103}
104
105impl Flags {
106 #[inline]
107 fn n(&self) -> bool {
108 (self.n & 0x80) != 0
109 }
110
111 #[inline]
112 fn set_n(&mut self, set: bool) {
113 self.n = MachineInt((set as u8) << 7)
114 }
115
116 #[inline]
117 fn v(&self) -> bool {
118 self.v != 0
119 }
120
121 #[inline]
122 fn set_v(&mut self, set: bool) {
123 self.v = MachineInt(set as u8);
124 }
125
126 #[inline]
127 fn d(&self) -> bool {
128 self.d
129 }
130
131 #[inline]
132 fn set_d(&mut self, set: bool) {
133 self.d = set
134 }
135
136 #[inline]
137 fn i(&self) -> bool {
138 self.i
139 }
140
141 #[inline]
142 fn set_i(&mut self, set: bool) {
143 self.i = set
144 }
145
146 #[inline]
147 fn z(&self) -> bool {
148 self.z == 0
149 }
150
151 #[inline]
152 fn set_z(&mut self, set: bool) {
153 self.z = MachineInt(!set as u8);
154 }
155
156 #[inline]
157 pub fn c(&self) -> bool {
158 self.c != 0
159 }
160
161 #[inline]
162 pub fn set_c(&mut self, set: bool) {
163 self.c = MachineInt(set as u8);
164 }
165
166 #[inline]
167 fn nz(&mut self, val: Byte) {
168 self.n = val;
169 self.z = val;
170 }
171
172 fn to_byte(&self) -> Byte {
173 self.n & 0x80
174 | (self.v() as u8) << 6
175 | 0x30
176 | (self.d as u8) << 3
177 | (self.i as u8) << 2
178 | (self.z() as u8) << 1
179 | self.c
180 }
181
182 #[cfg_attr(
183 feature = "cargo-clippy",
184 allow(clippy::wrong_self_convention)
185 )]
186 fn from_byte(&mut self, val: Byte) {
187 self.n = val;
188 self.v = val & 0x40;
189 self.d = (val & 0x08) != 0;
190 self.i = (val & 0x04) != 0;
191 self.set_z((val & 0x02) != 0);
192 self.c = val & 1;
193 }
194}
195
196impl fmt::Debug for Flags {
197 #[cfg_attr(
198 feature = "cargo-clippy",
199 allow(clippy::many_single_char_names)
200 )]
201 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202 let n = if self.n() { "N" } else { "n" };
203 let v = match self.v.0 {
204 0 => "v",
205 _ => "V",
206 };
207 let d = if self.d { "D" } else { "d" };
208 let i = if !self.i { "i" } else { "I" };
209 let z = match self.z.0 {
210 0 => "Z",
211 _ => "z",
212 };
213 let c = match self.c.0 {
214 0 => "c",
215 _ => "C",
216 };
217 write!(f, "{}{}-B{}{}{}{}", n, v, d, i, z, c)
218 }
219}
220
221#[cfg(test)]
222mod test;