1use crate::{CpuDetails, M68000};
8use crate::addressing_modes::{EffectiveAddress, AddressingMode};
9use crate::exception::{ACCESS_ERROR, ADDRESS_ERROR};
10use crate::instruction::Size;
11use crate::utils::IsEven;
12
13type GetResult<T> = Result<T, u8>;
16type SetResult = Result<(), u8>;
19
20pub trait MemoryAccess {
32 #[must_use]
34 fn get_byte(&mut self, addr: u32) -> Option<u8>;
35
36 #[must_use]
38 fn get_word(&mut self, addr: u32) -> Option<u16>;
39
40 #[must_use]
44 fn get_long(&mut self, addr: u32) -> Option<u32> {
45 Some((self.get_word(addr)? as u32) << 16 | self.get_word(addr.wrapping_add(2))? as u32)
46 }
47
48 #[must_use]
50 fn set_byte(&mut self, addr: u32, value: u8) -> Option<()>;
51
52 #[must_use]
54 fn set_word(&mut self, addr: u32, value: u16) -> Option<()>;
55
56 #[must_use]
60 fn set_long(&mut self, addr: u32, value: u32) -> Option<()> {
61 self.set_word(addr, (value >> 16) as u16)?;
62 self.set_word(addr.wrapping_add(2), value as u16)
63 }
64
65 #[must_use]
68 fn iter_u16(&mut self, addr: u32) -> MemoryIter<Self> {
69 MemoryIter { memory: self, next_addr: addr }
70 }
71
72 fn reset_instruction(&mut self);
74}
75
76pub struct MemoryIter<'a, M: MemoryAccess + ?Sized> {
78 pub memory: &'a mut M,
80 pub next_addr: u32,
82}
83
84impl<M: MemoryAccess + ?Sized> Iterator for MemoryIter<'_, M> {
85 type Item = GetResult<u16>;
86
87 fn next(&mut self) -> Option<Self::Item> {
88 if self.next_addr.is_even() {
89 let data = self.memory.get_word(self.next_addr);
90 self.next_addr = self.next_addr.wrapping_add(2);
91 Some(data.ok_or(ACCESS_ERROR))
92 } else {
93 Some(Err(ADDRESS_ERROR))
94 }
95 }
96}
97
98impl<CPU: CpuDetails> M68000<CPU> {
99 pub(super) fn get_byte<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, ea: &mut EffectiveAddress, exec_time: &mut usize) -> GetResult<u8> {
100 match ea.mode {
101 AddressingMode::Drd(reg) => Ok(self.regs.d[reg as usize].0 as u8),
102 AddressingMode::Immediate(imm) => {
103 *exec_time += CPU::EA_IMMEDIATE;
104 Ok(imm as u8)
105 },
106 _ => memory.get_byte(self.get_effective_address(ea, exec_time)).ok_or(ACCESS_ERROR),
107 }
108 }
109
110 pub(super) fn get_word<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, ea: &mut EffectiveAddress, exec_time: &mut usize) -> GetResult<u16> {
111 match ea.mode {
112 AddressingMode::Drd(reg) => Ok(self.regs.d[reg as usize].0 as u16),
113 AddressingMode::Ard(reg) => Ok(self.regs.a(reg) as u16),
114 AddressingMode::Immediate(imm) => {
115 *exec_time += CPU::EA_IMMEDIATE;
116 Ok(imm as u16)
117 },
118 _ => {
119 let addr = self.get_effective_address(ea, exec_time).even()?;
120 memory.get_word(addr).ok_or(ACCESS_ERROR)
121 },
122 }
123 }
124
125 pub(super) fn get_long<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, ea: &mut EffectiveAddress, exec_time: &mut usize) -> GetResult<u32> {
126 match ea.mode {
127 AddressingMode::Drd(reg) => Ok(self.regs.d[reg as usize].0),
128 AddressingMode::Ard(reg) => Ok(self.regs.a(reg)),
129 AddressingMode::Immediate(imm) => {
130 *exec_time += CPU::EA_IMMEDIATE + 4;
131 Ok(imm)
132 },
133 _ => {
134 let addr = self.get_effective_address(ea, exec_time).even()?;
135 let r = memory.get_long(addr).ok_or(ACCESS_ERROR);
136 *exec_time += 4;
137 r
138 },
139 }
140 }
141
142 pub(super) fn set_byte<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, ea: &mut EffectiveAddress, exec_time: &mut usize, value: u8) -> SetResult {
143 match ea.mode {
144 AddressingMode::Drd(reg) => { self.regs.d_byte(reg, value); Ok(()) },
145 _ => memory.set_byte(self.get_effective_address(ea, exec_time), value).ok_or(ACCESS_ERROR),
146 }
147 }
148
149 pub(super) fn set_word<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, ea: &mut EffectiveAddress, exec_time: &mut usize, value: u16) -> SetResult {
150 match ea.mode {
151 AddressingMode::Drd(reg) => { self.regs.d_word(reg, value); Ok(()) },
152 AddressingMode::Ard(reg) => { self.regs.a_mut(reg).0 = value as i16 as u32; Ok(()) },
153 _ => {
154 let addr = self.get_effective_address(ea, exec_time).even()?;
155 memory.set_word(addr, value).ok_or(ACCESS_ERROR)
156 },
157 }
158 }
159
160 pub(super) fn set_long<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, ea: &mut EffectiveAddress, exec_time: &mut usize, value: u32) -> SetResult {
161 match ea.mode {
162 AddressingMode::Drd(reg) => { self.regs.d[reg as usize].0 = value; Ok(()) },
163 AddressingMode::Ard(reg) => { self.regs.a_mut(reg).0 = value; Ok(()) },
164 _ => {
165 let addr = self.get_effective_address(ea, exec_time).even()?;
166 let r = memory.set_long(addr, value).ok_or(ACCESS_ERROR);
167 *exec_time += 4;
168 r
169 },
170 }
171 }
172
173 pub fn get_next_word<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M) -> GetResult<u16> {
179 let data = memory.get_word(self.regs.pc.even()?.0).ok_or(ACCESS_ERROR);
180 self.regs.pc += 2;
181 data
182 }
183
184 pub fn get_next_long<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M) -> GetResult<u32> {
188 let data = memory.get_long(self.regs.pc.even()?.0).ok_or(ACCESS_ERROR);
189 self.regs.pc += 4;
190 data
191 }
192
193 pub fn peek_next_word<M: MemoryAccess + ?Sized>(&self, memory: &mut M) -> GetResult<u16> {
198 memory.get_word(self.regs.pc.even()?.0).ok_or(ACCESS_ERROR)
199 }
200
201 pub(super) fn pop_word<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M) -> GetResult<u16> {
203 let addr = self.ariwpo(7, Size::Word);
204 memory.get_word(addr.even()?).ok_or(ACCESS_ERROR)
205 }
206
207 pub(super) fn pop_long<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M) -> GetResult<u32> {
209 let addr = self.ariwpo(7, Size::Long);
210 memory.get_long(addr.even()?).ok_or(ACCESS_ERROR)
211 }
212
213 pub(super) fn push_word<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, value: u16) -> SetResult {
215 let addr = self.ariwpr(7, Size::Word);
216 memory.set_word(addr.even()?, value).ok_or(ACCESS_ERROR)
217 }
218
219 pub(super) fn push_long<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, value: u32) -> SetResult {
221 let addr = self.ariwpr(7, Size::Long);
222 memory.set_long(addr.even()?, value).ok_or(ACCESS_ERROR)
223 }
224
225 pub(super) fn iter_from_pc<'a, M: MemoryAccess + ?Sized>(&self, memory: &'a mut M) -> MemoryIter<'a, M> {
227 memory.iter_u16(self.regs.pc.0)
228 }
229}
230
231impl MemoryAccess for [u8] {
232 fn get_byte(&mut self, addr: u32) -> Option<u8> {
233 let addr = addr as usize;
234 if addr < self.len() {
235 Some(self[addr])
236 } else {
237 None
238 }
239 }
240
241 fn get_word(&mut self, addr: u32) -> Option<u16> {
242 let addr = addr as usize;
243 if addr < self.len() {
244 Some((self[addr] as u16) << 8 | self[addr.wrapping_add(1)] as u16)
245 } else {
246 None
247 }
248 }
249
250 fn set_byte(&mut self, addr: u32, data: u8) -> Option<()> {
251 let addr = addr as usize;
252 if addr < self.len() {
253 self[addr] = data;
254 Some(())
255 } else {
256 None
257 }
258 }
259
260 fn set_word(&mut self, addr: u32, data: u16) -> Option<()> {
261 let addr = addr as usize;
262 if addr < self.len() {
263 self[addr] = (data >> 8) as u8;
264 self[addr.wrapping_add(1)] = data as u8;
265 Some(())
266 } else {
267 None
268 }
269 }
270
271 fn reset_instruction(&mut self) {}
272}
273
274impl MemoryAccess for &[u8] {
275 fn get_byte(&mut self, addr: u32) -> Option<u8> {
276 let addr = addr as usize;
277 if addr < self.len() {
278 Some(self[addr])
279 } else {
280 None
281 }
282 }
283
284 fn get_word(&mut self, addr: u32) -> Option<u16> {
285 let addr = addr as usize;
286 if addr < self.len() {
287 Some((self[addr] as u16) << 8 | self[addr.wrapping_add(1)] as u16)
288 } else {
289 None
290 }
291 }
292
293 fn set_byte(&mut self, _: u32, _: u8) -> Option<()> {
294 panic!("Can't write in non-mutable buffer");
295 }
296
297 fn set_word(&mut self, _: u32, _: u16) -> Option<()> {
298 panic!("Can't write in non-mutable buffer");
299 }
300
301 fn reset_instruction(&mut self) {}
302}
303
304impl MemoryAccess for [u16] {
305 fn get_byte(&mut self, addr: u32) -> Option<u8> {
306 let a = addr as usize >> 1;
307 if a < self.len() {
308 if addr.is_even() {
309 Some((self[a] >> 8) as u8)
310 } else {
311 Some(self[a] as u8)
312 }
313 } else {
314 None
315 }
316 }
317
318 fn get_word(&mut self, addr: u32) -> Option<u16> {
319 let addr = addr as usize >> 1;
320 if addr < self.len() {
321 Some(self[addr])
322 } else {
323 None
324 }
325 }
326
327 fn set_byte(&mut self, addr: u32, data: u8) -> Option<()> {
328 let a = addr as usize >> 1;
329 if a < self.len() {
330 if addr.is_even() {
331 self[a] &= 0x00FF;
332 self[a] |= (data as u16) << 8;
333 } else {
334 self[a] &= 0xFF00;
335 self[a] |= data as u16;
336 }
337 Some(())
338 } else {
339 None
340 }
341 }
342
343 fn set_word(&mut self, addr: u32, data: u16) -> Option<()> {
344 let addr = addr as usize >> 1;
345 if addr < self.len() {
346 self[addr] = data;
347 Some(())
348 } else {
349 None
350 }
351 }
352
353 fn reset_instruction(&mut self) {}
354}
355
356impl MemoryAccess for &[u16] {
357 fn get_byte(&mut self, addr: u32) -> Option<u8> {
358 let a = addr as usize >> 1;
359 if a < self.len() {
360 if addr.is_even() {
361 Some((self[a] >> 8) as u8)
362 } else {
363 Some(self[a] as u8)
364 }
365 } else {
366 None
367 }
368 }
369
370 fn get_word(&mut self, addr: u32) -> Option<u16> {
371 let addr = addr as usize >> 1;
372 if addr < self.len() {
373 Some(self[addr])
374 } else {
375 None
376 }
377 }
378
379 fn set_byte(&mut self, _: u32, _: u8) -> Option<()> {
380 panic!("Can't write in non-mutable buffer");
381 }
382
383 fn set_word(&mut self, _: u32, _: u16) -> Option<()> {
384 panic!("Can't write in non-mutable buffer");
385 }
386
387 fn reset_instruction(&mut self) {}
388}