core.rsannotatedcore.rssource1231 lines · 41.7 KB · raw
1pub(crate) mod instructions;
2
3use crate::core::instructions::Instruction;
4use crate::traits::BusInterface;
5use jgenesis_common::num::GetBit;
6use jgenesis_proc_macros::EnumAll;
7use std::fmt::{Display, Formatter};
8
9use crate::debug::{BusDebugExt, M68000Debugger};
10pub use instructions::cycles_if_move_btst_cmp;
11
12#[derive(Debug, Clone, Copy)]
13#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
14struct ConditionCodes {
15    carry: bool,
16    overflow: bool,
17    zero: bool,
18    negative: bool,
19    extend: bool,
20}
21
22impl From<u8> for ConditionCodes {
23    fn from(value: u8) -> Self {
24        Self {
25            carry: value.bit(0),
26            overflow: value.bit(1),
27            zero: value.bit(2),
28            negative: value.bit(3),
29            extend: value.bit(4),
30        }
31    }
32}
33
34impl From<ConditionCodes> for u8 {
35    fn from(value: ConditionCodes) -> Self {
36        (u8::from(value.extend) << 4)
37            | (u8::from(value.negative) << 3)
38            | (u8::from(value.zero) << 2)
39            | (u8::from(value.overflow) << 1)
40            | u8::from(value.carry)
41    }
42}
43
44#[derive(Debug, Clone)]
45#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
46struct Registers {
47    data: [u32; 8],
48    address: [u32; 7],
49    usp: u32,
50    ssp: u32,
51    pc: u32,
52    prefetch: u16,
53    ccr: ConditionCodes,
54    interrupt_priority_mask: u8,
55    pending_interrupt_level: Option<u8>,
56    supervisor_mode: bool,
57    trace_enabled: bool,
58    address_error: bool,
59    last_instruction_was_muldiv: bool,
60    stopped: bool,
61    frozen: bool,
62}
63
64const DEFAULT_INTERRUPT_MASK: u8 = 7;
65
66impl Registers {
67    pub fn new() -> Self {
68        Self {
69            data: [0; 8],
70            address: [0; 7],
71            usp: 0,
72            ssp: 0,
73            pc: 0,
74            prefetch: 0,
75            ccr: 0.into(),
76            interrupt_priority_mask: DEFAULT_INTERRUPT_MASK,
77            pending_interrupt_level: None,
78            supervisor_mode: true,
79            trace_enabled: false,
80            address_error: false,
81            last_instruction_was_muldiv: false,
82            stopped: false,
83            frozen: false,
84        }
85    }
86
87    fn status_register(&self) -> u16 {
88        let lsb: u8 = self.ccr.into();
89        let msb = self.interrupt_priority_mask
90            | (u8::from(self.supervisor_mode) << 5)
91            | (u8::from(self.trace_enabled) << 7);
92
93        u16::from_be_bytes([msb, lsb])
94    }
95
96    fn set_status_register(&mut self, value: u16) {
97        let [msb, lsb] = value.to_be_bytes();
98
99        self.interrupt_priority_mask = msb & 0x07;
100        self.supervisor_mode = msb.bit(5);
101        self.trace_enabled = msb.bit(7);
102
103        self.ccr = lsb.into();
104    }
105
106    fn sp(&self) -> u32 {
107        if self.supervisor_mode { self.ssp } else { self.usp }
108    }
109
110    fn set_sp(&mut self, sp: u32) {
111        if self.supervisor_mode {
112            self.ssp = sp;
113        } else {
114            self.usp = sp;
115        }
116    }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120pub struct DataRegister(pub(crate) u8);
121
122impl DataRegister {
123    const ALL: [Self; 8] = [Self(0), Self(1), Self(2), Self(3), Self(4), Self(5), Self(6), Self(7)];
124
125    fn read_from(self, registers: &Registers) -> u32 {
126        registers.data[self.0 as usize]
127    }
128
129    fn write_byte_to(self, registers: &mut Registers, value: u8) {
130        let existing_value = registers.data[self.0 as usize];
131        registers.data[self.0 as usize] = (existing_value & 0xFFFF_FF00) | u32::from(value);
132    }
133
134    fn write_word_to(self, registers: &mut Registers, value: u16) {
135        let existing_value = registers.data[self.0 as usize];
136        registers.data[self.0 as usize] = (existing_value & 0xFFFF_0000) | u32::from(value);
137    }
138
139    fn write_long_word_to(self, registers: &mut Registers, value: u32) {
140        registers.data[self.0 as usize] = value;
141    }
142}
143
144impl From<u8> for DataRegister {
145    fn from(value: u8) -> Self {
146        Self(value)
147    }
148}
149
150#[derive(Debug, Clone, Copy, PartialEq, Eq)]
151pub struct AddressRegister(pub(crate) u8);
152
153impl AddressRegister {
154    const ALL: [Self; 8] = [Self(0), Self(1), Self(2), Self(3), Self(4), Self(5), Self(6), Self(7)];
155
156    fn is_stack_pointer(self) -> bool {
157        self.0 == 7
158    }
159
160    fn read_from(self, registers: &Registers) -> u32 {
161        match (self.0, registers.supervisor_mode) {
162            (7, false) => registers.usp,
163            (7, true) => registers.ssp,
164            (register, _) => registers.address[register as usize],
165        }
166    }
167
168    #[allow(clippy::unused_self)]
169    fn write_byte_to(self, _registers: &mut Registers, _value: u8) {
170        panic!("Writing a byte to an address register is not supported");
171    }
172
173    fn write_word_to(self, registers: &mut Registers, value: u16) {
174        // Address register writes are always sign extended to 32 bits
175        self.write_long_word_to(registers, value as i16 as u32);
176    }
177
178    fn write_long_word_to(self, registers: &mut Registers, value: u32) {
179        match (self.0, registers.supervisor_mode) {
180            (7, false) => {
181                registers.usp = value;
182            }
183            (7, true) => {
184                registers.ssp = value;
185            }
186            (register, _) => {
187                registers.address[register as usize] = value;
188            }
189        }
190    }
191}
192
193impl From<u8> for AddressRegister {
194    fn from(value: u8) -> Self {
195        Self(value)
196    }
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumAll)]
200pub enum OpSize {
201    Byte,
202    Word,
203    LongWord,
204}
205
206impl OpSize {
207    fn increment_step_for(self, register: AddressRegister) -> u32 {
208        match self {
209            Self::Byte => {
210                if register.is_stack_pointer() {
211                    2
212                } else {
213                    1
214                }
215            }
216            Self::Word => 2,
217            Self::LongWord => 4,
218        }
219    }
220}
221
222impl Display for OpSize {
223    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
224        match self {
225            Self::Byte => write!(f, "b"),
226            Self::Word => write!(f, "w"),
227            Self::LongWord => write!(f, "l"),
228        }
229    }
230}
231
232#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum IndexRegister {
234    Data(DataRegister),
235    Address(AddressRegister),
236}
237
238impl IndexRegister {
239    fn read_from(self, registers: &Registers, size: IndexSize) -> u32 {
240        let raw_value = match self {
241            Self::Data(register) => register.read_from(registers),
242            Self::Address(register) => register.read_from(registers),
243        };
244
245        match size {
246            IndexSize::SignExtendedWord => raw_value as i16 as u32,
247            IndexSize::LongWord => raw_value,
248        }
249    }
250}
251
252pub(crate) fn parse_index(extension: u16) -> (IndexRegister, IndexSize) {
253    let register_number = ((extension >> 12) & 0x07) as u8;
254    let register = if extension.bit(15) {
255        IndexRegister::Address(register_number.into())
256    } else {
257        IndexRegister::Data(register_number.into())
258    };
259
260    let size = if extension.bit(11) { IndexSize::LongWord } else { IndexSize::SignExtendedWord };
261
262    (register, size)
263}
264
265#[derive(Debug, Clone, Copy, PartialEq, Eq)]
266pub enum IndexSize {
267    SignExtendedWord,
268    LongWord,
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq)]
272enum BusOpType {
273    Read,
274    Write,
275    Jump,
276}
277
278#[derive(Debug, Clone, Copy, PartialEq, Eq)]
279enum Exception {
280    AddressError(u32, BusOpType),
281    PrivilegeViolation,
282    IllegalInstruction(u16),
283    DivisionByZero { cycles: u32 },
284    Trap(u32),
285    CheckRegister { cycles: u32 },
286}
287
288type ExecuteResult<T> = Result<T, Exception>;
289
290#[derive(Debug, Clone, Copy, PartialEq, Eq)]
291pub enum AddressingMode {
292    DataDirect(DataRegister),
293    AddressDirect(AddressRegister),
294    AddressIndirect(AddressRegister),
295    AddressIndirectPostincrement(AddressRegister),
296    AddressIndirectPredecrement(AddressRegister),
297    AddressIndirectDisplacement(AddressRegister),
298    AddressIndirectIndexed(AddressRegister),
299    PcRelativeDisplacement,
300    PcRelativeIndexed,
301    AbsoluteShort,
302    AbsoluteLong,
303    Immediate,
304    Quick(u8),
305}
306
307impl AddressingMode {
308    fn is_data_direct(self) -> bool {
309        matches!(self, Self::DataDirect(..))
310    }
311
312    fn is_address_direct(self) -> bool {
313        matches!(self, Self::AddressDirect(..))
314    }
315
316    fn is_memory(self) -> bool {
317        matches!(
318            self,
319            Self::AddressIndirect(..)
320                | Self::AddressIndirectPostincrement(..)
321                | Self::AddressIndirectPredecrement(..)
322                | Self::AddressIndirectDisplacement(..)
323                | Self::AddressIndirectIndexed(..)
324                | Self::PcRelativeDisplacement
325                | Self::PcRelativeIndexed
326                | Self::AbsoluteShort
327                | Self::AbsoluteLong
328        )
329    }
330
331    fn address_calculation_cycles(self, size: OpSize) -> u32 {
332        use AddressingMode::{
333            AbsoluteLong, AbsoluteShort, AddressDirect, AddressIndirect,
334            AddressIndirectDisplacement, AddressIndirectIndexed, AddressIndirectPostincrement,
335            AddressIndirectPredecrement, DataDirect, Immediate, PcRelativeDisplacement,
336            PcRelativeIndexed, Quick,
337        };
338        use OpSize::{Byte, LongWord, Word};
339
340        match (self, size) {
341            (DataDirect(..) | AddressDirect(..) | Quick(..), _) => 0,
342            (AddressIndirect(..) | AddressIndirectPostincrement(..) | Immediate, Byte | Word) => 4,
343            (AddressIndirectPredecrement(..), Byte | Word) => 6,
344            (
345                AddressIndirectDisplacement(..) | PcRelativeDisplacement | AbsoluteShort,
346                Byte | Word,
347            )
348            | (AddressIndirect(..) | AddressIndirectPostincrement(..) | Immediate, LongWord) => 8,
349            (AddressIndirectIndexed(..) | PcRelativeIndexed, Byte | Word)
350            | (AddressIndirectPredecrement(..), LongWord) => 10,
351            (AbsoluteLong, Byte | Word)
352            | (
353                AddressIndirectDisplacement(..) | PcRelativeDisplacement | AbsoluteShort,
354                LongWord,
355            ) => 12,
356            (AddressIndirectIndexed(..) | PcRelativeIndexed, LongWord) => 14,
357            (AbsoluteLong, LongWord) => 16,
358        }
359    }
360}
361
362impl Display for AddressingMode {
363    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
364        match self {
365            Self::DataDirect(register) => write!(f, "D{}", register.0),
366            Self::AddressDirect(register) => write!(f, "A{}", register.0),
367            Self::AddressIndirect(register) => write!(f, "(A{})", register.0),
368            Self::AddressIndirectPostincrement(register) => write!(f, "(A{})+", register.0),
369            Self::AddressIndirectPredecrement(register) => write!(f, "-(A{})", register.0),
370            Self::AddressIndirectDisplacement(register) => write!(f, "(d, A{})", register.0),
371            Self::AddressIndirectIndexed(register) => write!(f, "(d, A{}, X)", register.0),
372            Self::PcRelativeDisplacement => write!(f, "(d, PC)"),
373            Self::PcRelativeIndexed => write!(f, "(d, PC, X)"),
374            Self::AbsoluteShort => write!(f, "(xxx).w"),
375            Self::AbsoluteLong => write!(f, "(xxx).l"),
376            Self::Immediate => write!(f, "#<d>"),
377            Self::Quick(n) => write!(f, "#<{n}>"),
378        }
379    }
380}
381
382#[derive(Debug, Clone, Copy, PartialEq, Eq)]
383enum ResolvedAddress {
384    DataRegister(DataRegister),
385    AddressRegister(AddressRegister),
386    Memory(u32),
387    MemoryPostincrement { address: u32, register: AddressRegister, increment: u32 },
388    Immediate(u32),
389}
390
391impl ResolvedAddress {
392    fn apply_post(self, registers: &mut Registers) {
393        if let ResolvedAddress::MemoryPostincrement { address, register, increment } = self {
394            register.write_long_word_to(registers, address.wrapping_add(increment));
395        }
396    }
397}
398
399impl Display for ResolvedAddress {
400    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
401        match self {
402            Self::DataRegister(register) => write!(f, "D{}", register.0),
403            Self::AddressRegister(register) => write!(f, "A{}", register.0),
404            Self::Memory(address) | Self::MemoryPostincrement { address, .. } => {
405                write!(f, "(${address:06X})")
406            }
407            Self::Immediate(value) => write!(f, "#<${value:08X}>"),
408        }
409    }
410}
411
412#[derive(Debug)]
413struct InstructionExecutor<'cpu, 'bus, B> {
414    cpu: &'cpu mut M68000,
415    bus: &'bus mut B,
416    opcode: u16,
417    instruction: Option<Instruction>,
418}
419
420const ADDRESS_ERROR_VECTOR: u32 = 3;
421const ILLEGAL_OPCODE_VECTOR: u32 = 4;
422const DIVIDE_BY_ZERO_VECTOR: u32 = 5;
423const CHECK_REGISTER_VECTOR: u32 = 6;
424const PRIVILEGE_VIOLATION_VECTOR: u32 = 8;
425const LINE_1010_VECTOR: u32 = 10;
426const LINE_1111_VECTOR: u32 = 11;
427const AUTO_VECTORED_INTERRUPT_BASE_ADDRESS: u32 = 0x60;
428
429impl<'cpu, 'bus, B: BusInterface> InstructionExecutor<'cpu, 'bus, B> {
430    fn new(cpu: &'cpu mut M68000, bus: &'bus mut B) -> Self {
431        Self { cpu, bus, opcode: 0, instruction: None }
432    }
433
434    // Read a word from the bus; returns an address error if address is odd
435    fn read_bus_word(&mut self, address: u32) -> ExecuteResult<u16> {
436        if address & 1 != 0 {
437            return Err(Exception::AddressError(address, BusOpType::Read));
438        }
439
440        Ok(self.bus.read_word_debug(address, self.cpu))
441    }
442
443    // Write a word to the bus; returns an address error if address is odd
444    fn write_bus_word(&mut self, address: u32, value: u16) -> ExecuteResult<()> {
445        if address & 1 != 0 {
446            return Err(Exception::AddressError(address, BusOpType::Write));
447        }
448
449        self.bus.write_word_debug(address, value, self.cpu);
450
451        Ok(())
452    }
453
454    // Read a long word from the bus; returns an address error if address is odd
455    fn read_bus_long_word(&mut self, address: u32) -> ExecuteResult<u32> {
456        if address & 1 != 0 {
457            return Err(Exception::AddressError(address, BusOpType::Read));
458        }
459
460        Ok(self.bus.read_longword_debug(address, self.cpu))
461    }
462
463    // Write a long word to the bus; returns an address error if address is odd
464    fn write_bus_long_word(&mut self, address: u32, value: u32) -> ExecuteResult<()> {
465        if address & 1 != 0 {
466            return Err(Exception::AddressError(address, BusOpType::Write));
467        }
468
469        self.bus.write_longword_debug(address, value, self.cpu);
470
471        Ok(())
472    }
473
474    // Fetch a word from the current PC and increment PC; returns an address error if PC is odd
475    fn fetch_operand(&mut self) -> ExecuteResult<u16> {
476        let prefetch_addr = self.cpu.registers.pc.wrapping_add(2);
477        if self.cpu.registers.pc & 1 != 0 {
478            return Err(Exception::AddressError(prefetch_addr, BusOpType::Read));
479        }
480
481        let operand = self.cpu.registers.prefetch;
482        self.cpu.registers.prefetch = self.bus.read_word(prefetch_addr);
483        self.cpu.registers.pc = prefetch_addr;
484
485        Ok(operand)
486    }
487
488    // Resolve the given addressing mode to a concrete register, memory location, or immediate value,
489    // which may require fetching extension words
490    fn resolve_address(
491        &mut self,
492        addressing_mode: AddressingMode,
493        size: OpSize,
494    ) -> ExecuteResult<ResolvedAddress> {
495        let resolved_address = match addressing_mode {
496            AddressingMode::DataDirect(register) => ResolvedAddress::DataRegister(register),
497            AddressingMode::AddressDirect(register) => ResolvedAddress::AddressRegister(register),
498            AddressingMode::AddressIndirect(register) => {
499                ResolvedAddress::Memory(register.read_from(&self.cpu.registers))
500            }
501            AddressingMode::AddressIndirectPredecrement(register) => {
502                let increment = size.increment_step_for(register);
503                let address = register.read_from(&self.cpu.registers).wrapping_sub(increment);
504                register.write_long_word_to(&mut self.cpu.registers, address);
505                ResolvedAddress::Memory(address)
506            }
507            AddressingMode::AddressIndirectPostincrement(register) => {
508                let increment = size.increment_step_for(register);
509                let address = register.read_from(&self.cpu.registers);
510                ResolvedAddress::MemoryPostincrement { address, register, increment }
511            }
512            AddressingMode::AddressIndirectDisplacement(register) => {
513                let extension = self.fetch_operand()?;
514                let displacement = extension as i16;
515                let address =
516                    register.read_from(&self.cpu.registers).wrapping_add(displacement as u32);
517                ResolvedAddress::Memory(address)
518            }
519            AddressingMode::AddressIndirectIndexed(register) => {
520                let extension = self.fetch_operand()?;
521                let (index_register, index_size) = parse_index(extension);
522                let index = index_register.read_from(&self.cpu.registers, index_size);
523                let displacement = extension as i8;
524
525                let address = register
526                    .read_from(&self.cpu.registers)
527                    .wrapping_add(index)
528                    .wrapping_add(displacement as u32);
529                ResolvedAddress::Memory(address)
530            }
531            AddressingMode::PcRelativeDisplacement => {
532                let pc = self.cpu.registers.pc;
533                let extension = self.fetch_operand()?;
534                let displacement = extension as i16;
535                let address = pc.wrapping_add(displacement as u32);
536                ResolvedAddress::Memory(address)
537            }
538            AddressingMode::PcRelativeIndexed => {
539                let pc = self.cpu.registers.pc;
540                let extension = self.fetch_operand()?;
541                let (index_register, index_size) = parse_index(extension);
542                let index = index_register.read_from(&self.cpu.registers, index_size);
543                let displacement = extension as i8;
544
545                let address = pc.wrapping_add(index).wrapping_add(displacement as u32);
546                ResolvedAddress::Memory(address)
547            }
548            AddressingMode::AbsoluteShort => {
549                let extension = self.fetch_operand()?;
550                let address = extension as i16 as u32;
551                ResolvedAddress::Memory(address)
552            }
553            AddressingMode::AbsoluteLong => {
554                let extension_0 = self.fetch_operand()?;
555                let extension_1 = self.fetch_operand()?;
556                let address = (u32::from(extension_0) << 16) | u32::from(extension_1);
557                ResolvedAddress::Memory(address)
558            }
559            AddressingMode::Immediate => {
560                let extension_0 = self.fetch_operand()?;
561                match size {
562                    OpSize::Byte => ResolvedAddress::Immediate((extension_0 as u8).into()),
563                    OpSize::Word => ResolvedAddress::Immediate(extension_0.into()),
564                    OpSize::LongWord => {
565                        let extension_1 = self.fetch_operand()?;
566                        let value = (u32::from(extension_0) << 16) | u32::from(extension_1);
567                        ResolvedAddress::Immediate(value)
568                    }
569                }
570            }
571            AddressingMode::Quick(value) => ResolvedAddress::Immediate(value.into()),
572        };
573
574        log::trace!("[{}] {addressing_mode} resolved to {resolved_address}", self.cpu.name);
575
576        Ok(resolved_address)
577    }
578
579    // Resolve the given address and, if it is a postincrement address, apply the increment
580    fn resolve_address_with_post(
581        &mut self,
582        addressing_mode: AddressingMode,
583        size: OpSize,
584    ) -> ExecuteResult<ResolvedAddress> {
585        let resolved = self.resolve_address(addressing_mode, size)?;
586        resolved.apply_post(&mut self.cpu.registers);
587        Ok(resolved)
588    }
589
590    fn read_byte_resolved(&mut self, resolved_address: ResolvedAddress) -> u8 {
591        match resolved_address {
592            ResolvedAddress::DataRegister(register) => {
593                register.read_from(&self.cpu.registers) as u8
594            }
595            ResolvedAddress::AddressRegister(register) => {
596                register.read_from(&self.cpu.registers) as u8
597            }
598            ResolvedAddress::Memory(address)
599            | ResolvedAddress::MemoryPostincrement { address, .. } => {
600                self.bus.read_byte_debug(address, self.cpu)
601            }
602            ResolvedAddress::Immediate(value) => value as u8,
603        }
604    }
605
606    // Exists for ease of use in macros
607    #[allow(clippy::unnecessary_wraps)]
608    #[inline]
609    fn read_byte_resolved_as_result(
610        &mut self,
611        resolved_address: ResolvedAddress,
612    ) -> ExecuteResult<u8> {
613        Ok(self.read_byte_resolved(resolved_address))
614    }
615
616    // Read a word from the given location; will return an address error if the location is an odd memory address
617    fn read_word_resolved(&mut self, resolved_address: ResolvedAddress) -> ExecuteResult<u16> {
618        match resolved_address {
619            ResolvedAddress::DataRegister(register) => {
620                Ok(register.read_from(&self.cpu.registers) as u16)
621            }
622            ResolvedAddress::AddressRegister(register) => {
623                Ok(register.read_from(&self.cpu.registers) as u16)
624            }
625            ResolvedAddress::Memory(address)
626            | ResolvedAddress::MemoryPostincrement { address, .. } => self.read_bus_word(address),
627            ResolvedAddress::Immediate(value) => Ok(value as u16),
628        }
629    }
630
631    // Read a long word from the given location; will return an address error if the location is an odd memory address
632    fn read_long_word_resolved(&mut self, resolved_address: ResolvedAddress) -> ExecuteResult<u32> {
633        match resolved_address {
634            ResolvedAddress::DataRegister(register) => Ok(register.read_from(&self.cpu.registers)),
635            ResolvedAddress::AddressRegister(register) => {
636                Ok(register.read_from(&self.cpu.registers))
637            }
638            ResolvedAddress::Memory(address)
639            | ResolvedAddress::MemoryPostincrement { address, .. } => {
640                self.read_bus_long_word(address)
641            }
642            ResolvedAddress::Immediate(value) => Ok(value),
643        }
644    }
645
646    fn read_byte(&mut self, source: AddressingMode) -> ExecuteResult<u8> {
647        let resolved_address = self.resolve_address_with_post(source, OpSize::Byte)?;
648        let value = self.read_byte_resolved(resolved_address);
649        Ok(value)
650    }
651
652    fn read_word(&mut self, source: AddressingMode) -> ExecuteResult<u16> {
653        let resolved_address = self.resolve_address_with_post(source, OpSize::Word)?;
654        let value = self.read_word_resolved(resolved_address)?;
655        Ok(value)
656    }
657
658    fn read_long_word(&mut self, source: AddressingMode) -> ExecuteResult<u32> {
659        let resolved_address = self.resolve_address_with_post(source, OpSize::LongWord)?;
660        let value = self.read_long_word_resolved(resolved_address)?;
661        Ok(value)
662    }
663
664    fn write_byte_resolved(&mut self, resolved_address: ResolvedAddress, value: u8) {
665        match resolved_address {
666            ResolvedAddress::DataRegister(register) => {
667                register.write_byte_to(&mut self.cpu.registers, value);
668            }
669            ResolvedAddress::AddressRegister(register) => {
670                register.write_byte_to(&mut self.cpu.registers, value);
671            }
672            ResolvedAddress::Memory(address)
673            | ResolvedAddress::MemoryPostincrement { address, .. } => {
674                self.bus.write_byte_debug(address, value, self.cpu);
675            }
676            ResolvedAddress::Immediate(..) => panic!("cannot write to immediate addressing mode"),
677        }
678    }
679
680    // Exists for ease of use in macros
681    #[allow(clippy::unnecessary_wraps)]
682    #[inline]
683    fn write_byte_resolved_as_result(
684        &mut self,
685        resolved_address: ResolvedAddress,
686        value: u8,
687    ) -> ExecuteResult<()> {
688        self.write_byte_resolved(resolved_address, value);
689        Ok(())
690    }
691
692    fn write_word_resolved(
693        &mut self,
694        resolved_address: ResolvedAddress,
695        value: u16,
696    ) -> ExecuteResult<()> {
697        match resolved_address {
698            ResolvedAddress::DataRegister(register) => {
699                register.write_word_to(&mut self.cpu.registers, value);
700            }
701            ResolvedAddress::AddressRegister(register) => {
702                register.write_word_to(&mut self.cpu.registers, value);
703            }
704            ResolvedAddress::Memory(address)
705            | ResolvedAddress::MemoryPostincrement { address, .. } => {
706                self.write_bus_word(address, value)?;
707            }
708            ResolvedAddress::Immediate(..) => panic!("cannot write to immediate addressing mode"),
709        }
710
711        Ok(())
712    }
713
714    fn write_long_word_resolved(
715        &mut self,
716        resolved_address: ResolvedAddress,
717        value: u32,
718    ) -> ExecuteResult<()> {
719        match resolved_address {
720            ResolvedAddress::DataRegister(register) => {
721                register.write_long_word_to(&mut self.cpu.registers, value);
722            }
723            ResolvedAddress::AddressRegister(register) => {
724                register.write_long_word_to(&mut self.cpu.registers, value);
725            }
726            ResolvedAddress::Memory(address)
727            | ResolvedAddress::MemoryPostincrement { address, .. } => {
728                self.write_bus_long_word(address, value)?;
729            }
730            ResolvedAddress::Immediate(..) => panic!("cannot write to immediate addressing mode"),
731        }
732
733        Ok(())
734    }
735
736    fn write_byte(&mut self, dest: AddressingMode, value: u8) -> ExecuteResult<()> {
737        let resolved_address = self.resolve_address(dest, OpSize::Byte)?;
738        self.write_byte_resolved(resolved_address, value);
739        resolved_address.apply_post(&mut self.cpu.registers);
740
741        Ok(())
742    }
743
744    fn write_word(&mut self, dest: AddressingMode, value: u16) -> ExecuteResult<()> {
745        let resolved_address = self.resolve_address(dest, OpSize::Word)?;
746        self.write_word_resolved(resolved_address, value)?;
747        resolved_address.apply_post(&mut self.cpu.registers);
748
749        Ok(())
750    }
751
752    fn write_long_word(&mut self, dest: AddressingMode, value: u32) -> ExecuteResult<()> {
753        let resolved_address = self.resolve_address(dest, OpSize::LongWord)?;
754        self.write_long_word_resolved(resolved_address, value)?;
755        resolved_address.apply_post(&mut self.cpu.registers);
756
757        Ok(())
758    }
759
760    fn push_stack_u16(&mut self, value: u16) -> ExecuteResult<()> {
761        let sp = self.cpu.registers.sp().wrapping_sub(2);
762        self.cpu.registers.set_sp(sp);
763
764        self.write_bus_word(sp, value)?;
765
766        Ok(())
767    }
768
769    fn push_stack_u32(&mut self, value: u32) -> ExecuteResult<()> {
770        let high_word = (value >> 16) as u16;
771        let low_word = value as u16;
772
773        let sp = self.cpu.registers.sp().wrapping_sub(4);
774        self.cpu.registers.set_sp(sp);
775
776        self.write_bus_word(sp, high_word)?;
777        self.write_bus_word(sp.wrapping_add(2), low_word)?;
778
779        Ok(())
780    }
781
782    fn pop_stack_u16(&mut self) -> ExecuteResult<u16> {
783        let sp = self.cpu.registers.sp();
784        let value = self.read_bus_word(sp)?;
785
786        self.cpu.registers.set_sp(sp.wrapping_add(2));
787
788        Ok(value)
789    }
790
791    fn pop_stack_u32(&mut self) -> ExecuteResult<u32> {
792        let sp = self.cpu.registers.sp();
793        let value = self.read_bus_long_word(sp)?;
794
795        self.cpu.registers.set_sp(sp.wrapping_add(4));
796
797        Ok(value)
798    }
799
800    fn handle_address_error(&mut self, address: u32, op_type: BusOpType) -> ExecuteResult<()> {
801        let sr = self.cpu.registers.status_register();
802        let supervisor_mode = self.cpu.registers.supervisor_mode;
803
804        self.cpu.registers.trace_enabled = false;
805        self.cpu.registers.supervisor_mode = true;
806
807        let dest = self.instruction.and_then(Instruction::dest_addressing_mode);
808        let source = self.instruction.and_then(Instruction::source_addressing_mode);
809
810        let pc = match (op_type, dest, source) {
811            (BusOpType::Write, Some(AddressingMode::AddressIndirectPredecrement(..)), Some(_)) => {
812                self.cpu.registers.pc
813            }
814            (
815                BusOpType::Write,
816                Some(AddressingMode::AbsoluteLong),
817                Some(
818                    AddressingMode::AddressIndirect(..)
819                    | AddressingMode::AddressIndirectPostincrement(..)
820                    | AddressingMode::AddressIndirectPredecrement(..)
821                    | AddressingMode::AddressIndirectDisplacement(..)
822                    | AddressingMode::AddressIndirectIndexed(..)
823                    | AddressingMode::PcRelativeDisplacement
824                    | AddressingMode::PcRelativeIndexed
825                    | AddressingMode::AbsoluteShort
826                    | AddressingMode::AbsoluteLong,
827                ),
828            ) => self.cpu.registers.pc.wrapping_sub(4),
829            _ => self.cpu.registers.pc.wrapping_sub(2),
830        };
831
832        log::trace!("Address error PC: {pc:08X}");
833        self.push_stack_u32(pc)?;
834        log::trace!("Address error SR: {sr:08X}");
835        self.push_stack_u16(sr)?;
836        log::trace!("Address error opcode: {:08X}", self.opcode);
837        self.push_stack_u16(self.opcode)?;
838        self.push_stack_u32(address)?;
839
840        let rw_bit = (op_type == BusOpType::Read || op_type == BusOpType::Jump)
841            ^ matches!(self.instruction, Some(Instruction::MoveFromSr(..)));
842        let status_code = match op_type {
843            BusOpType::Jump => {
844                if supervisor_mode {
845                    0x0E
846                } else {
847                    0x0A
848                }
849            }
850            _ => 0x05,
851        };
852        let status_word = (self.opcode & 0xFFE0) | (u16::from(rw_bit) << 4) | status_code;
853        log::trace!("Pushing status word: {status_word:08X}");
854        self.push_stack_u16(status_word)?;
855
856        let vector = self.bus.read_long_word(ADDRESS_ERROR_VECTOR * 4);
857        self.jump_to_address(vector)?;
858
859        Ok(())
860    }
861
862    fn handle_trap(&mut self, vector: u32, pc: u32) -> ExecuteResult<()> {
863        let sr = self.cpu.registers.status_register();
864        self.cpu.registers.trace_enabled = false;
865        self.cpu.registers.supervisor_mode = true;
866
867        self.push_stack_u32(pc)?;
868        self.push_stack_u16(sr)?;
869
870        let new_pc = self.bus.read_long_word(vector * 4);
871        self.jump_to_address(new_pc)?;
872
873        Ok(())
874    }
875
876    fn handle_auto_vectored_interrupt(&mut self, interrupt_level: u8) -> ExecuteResult<u32> {
877        let sr = self.cpu.registers.status_register();
878        self.cpu.registers.trace_enabled = false;
879        self.cpu.registers.supervisor_mode = true;
880        self.cpu.registers.interrupt_priority_mask = interrupt_level;
881
882        self.push_stack_u32(self.cpu.registers.pc)?;
883        self.push_stack_u16(sr)?;
884
885        let vector_addr = AUTO_VECTORED_INTERRUPT_BASE_ADDRESS + 4 * u32::from(interrupt_level);
886        let new_pc = self.bus.read_long_word(vector_addr);
887        self.jump_to_address(new_pc)?;
888
889        // Auto-vectored interrupt handling takes 49-59 cycles instead of 44:
890        //   https://gendev.spritesmind.net/forum/viewtopic.php?t=2202
891        // For simplicity, use a constant 54 instead of tracking and synchronizing with E clock.
892        // Return 44 here because 10 cycles have already elapsed prior to the interrupt acknowledge
893        Ok(44)
894    }
895
896    fn jump_to_address(&mut self, address: u32) -> ExecuteResult<()> {
897        self.cpu.registers.pc = address.wrapping_sub(2);
898
899        if address & 1 != 0 {
900            return Err(Exception::AddressError(address, BusOpType::Jump));
901        }
902
903        let _ = self.fetch_operand();
904
905        Ok(())
906    }
907
908    fn execute(mut self) -> u32 {
909        self.cpu.registers.address_error = false;
910        self.cpu.registers.last_instruction_was_muldiv = false;
911
912        if let Some(interrupt_level) = self.cpu.registers.pending_interrupt_level {
913            self.cpu.registers.pending_interrupt_level = None;
914            self.bus.acknowledge_interrupt(interrupt_level);
915            self.cpu.registers.stopped = false;
916
917            return match self.handle_auto_vectored_interrupt(interrupt_level) {
918                Ok(cycles) => cycles,
919                Err(exception) => self.handle_exception(exception),
920            };
921        }
922
923        // TODO properly handle non-maskable level 7 interrupts?
924        let interrupt_level = self.bus.interrupt_level() & 0x07;
925        if interrupt_level > self.cpu.registers.interrupt_priority_mask {
926            log::trace!("[{}] Handling interrupt of level {interrupt_level}", self.cpu.name);
927            self.cpu.registers.pending_interrupt_level = Some(interrupt_level);
928
929            if let Some(mut debug_view) = self.bus.debug_view() {
930                debug_view.check_interrupt(interrupt_level, self.cpu);
931            }
932
933            // The 68000 takes about 10 cycles before it begins to acknowledge a received interrupt:
934            //   https://gendev.spritesmind.net/forum/viewtopic.php?t=2202
935            // mcd-verificator IRQ tests depend on this 10-cycle delay
936            return 10;
937        }
938
939        if self.cpu.registers.stopped {
940            return 4;
941        }
942
943        match self.do_execute() {
944            Ok(cycles) => cycles,
945            Err(exception) => self.handle_exception(exception),
946        }
947    }
948
949    fn handle_exception(&mut self, exception: Exception) -> u32 {
950        match exception {
951            Exception::AddressError(address, op_type) => {
952                log::error!(
953                    "[{}] Encountered 68000 address error; address={address:08X}, op_type={op_type:?}",
954                    self.cpu.name
955                );
956
957                self.cpu.registers.address_error = true;
958                if let Err(Exception::AddressError(address, _)) =
959                    self.handle_address_error(address, op_type)
960                {
961                    // An address error while handling address error halts the CPU until reset
962                    log::error!(
963                        "address error triggered while handling address error; CPU is now frozen (address={address:06X})"
964                    );
965                    self.cpu.registers.frozen = true;
966                }
967
968                // Not completely accurate but close enough; this shouldn't occur in real software
969                50
970            }
971            Exception::PrivilegeViolation => {
972                if let Err(Exception::AddressError(address, op_type)) = self
973                    .handle_trap(PRIVILEGE_VIOLATION_VECTOR, self.cpu.registers.pc.wrapping_sub(2))
974                {
975                    log::error!(
976                        "address error triggered while handling privilege violation exception (address={address:06X})"
977                    );
978                    return self.handle_exception(Exception::AddressError(address, op_type));
979                }
980
981                // TODO what should this actually be?
982                34
983            }
984            Exception::IllegalInstruction(opcode) => {
985                // If the highest 4 bits of the opcode are 1010 or 1111, the CPU uses different
986                // exception vectors. Zaxxon's Motherbase 2000 (32X) depends on this
987                let vector = match opcode >> 12 {
988                    0b1010 => LINE_1010_VECTOR,
989                    0b1111 => LINE_1111_VECTOR,
990                    _ => {
991                        log::error!(
992                            "[{}] Illegal opcode executed: {opcode:04X} / {opcode:016b}",
993                            self.cpu.name
994                        );
995                        ILLEGAL_OPCODE_VECTOR
996                    }
997                };
998
999                if let Err(Exception::AddressError(address, op_type)) =
1000                    self.handle_trap(vector, self.cpu.registers.pc.wrapping_sub(2))
1001                {
1002                    log::error!(
1003                        "address error triggered while handling illegal opcode exception (opcode={opcode:04X}, address={address:06X})"
1004                    );
1005                    return self.handle_exception(Exception::AddressError(address, op_type));
1006                }
1007
1008                34
1009            }
1010            Exception::DivisionByZero { cycles } => {
1011                log::warn!("[{}] Encountered 68000 divide by zero exception", self.cpu.name);
1012
1013                if let Err(Exception::AddressError(address, op_type)) =
1014                    self.handle_trap(DIVIDE_BY_ZERO_VECTOR, self.cpu.registers.pc)
1015                {
1016                    log::error!(
1017                        "address error triggered while handling divide by zero exception (address={address:06X})"
1018                    );
1019                    return self.handle_exception(Exception::AddressError(address, op_type));
1020                }
1021
1022                38 + cycles
1023            }
1024            Exception::Trap(vector) => {
1025                if let Err(Exception::AddressError(address, op_type)) =
1026                    self.handle_trap(vector, self.cpu.registers.pc)
1027                {
1028                    log::error!(
1029                        "address error triggered while executing TRAP instruction (address={address:06X})"
1030                    );
1031                    return self.handle_exception(Exception::AddressError(address, op_type));
1032                }
1033
1034                34
1035            }
1036            Exception::CheckRegister { cycles } => {
1037                if let Err(Exception::AddressError(address, op_type)) =
1038                    self.handle_trap(CHECK_REGISTER_VECTOR, self.cpu.registers.pc)
1039                {
1040                    log::error!(
1041                        "address error triggered while executing CHK instruction (address={address:06X})"
1042                    );
1043                    return self.handle_exception(Exception::AddressError(address, op_type));
1044                }
1045
1046                30 + cycles
1047            }
1048        }
1049    }
1050}
1051
1052#[derive(Debug, Clone)]
1053pub struct M68000Builder {
1054    allow_tas_writes: bool,
1055    name: Option<String>,
1056}
1057
1058impl Default for M68000Builder {
1059    fn default() -> Self {
1060        Self { allow_tas_writes: true, name: None }
1061    }
1062}
1063
1064impl M68000Builder {
1065    #[must_use]
1066    pub fn new() -> Self {
1067        Self::default()
1068    }
1069
1070    #[must_use]
1071    pub fn allow_tas_writes(mut self, allow_tas_writes: bool) -> Self {
1072        self.allow_tas_writes = allow_tas_writes;
1073        self
1074    }
1075
1076    #[must_use]
1077    pub fn name(mut self, name: String) -> Self {
1078        self.name = Some(name);
1079        self
1080    }
1081
1082    #[must_use]
1083    pub fn build(self) -> M68000 {
1084        M68000 {
1085            registers: Registers::new(),
1086            halted: false,
1087            allow_tas_writes: self.allow_tas_writes,
1088            name: self.name.unwrap_or_default(),
1089        }
1090    }
1091}
1092
1093const RESET_CYCLES: u32 = 132;
1094
1095#[derive(Debug, Clone)]
1096#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
1097pub struct M68000 {
1098    registers: Registers,
1099    halted: bool,
1100    allow_tas_writes: bool,
1101    // Used only for trace logging
1102    name: String,
1103}
1104
1105impl Default for M68000 {
1106    fn default() -> Self {
1107        M68000Builder::default().build()
1108    }
1109}
1110
1111impl M68000 {
1112    #[must_use]
1113    pub fn builder() -> M68000Builder {
1114        M68000Builder::default()
1115    }
1116
1117    fn reset(&mut self, bus: &mut impl BusInterface) {
1118        // Reset the upper word of the status register
1119        self.registers.supervisor_mode = true;
1120        self.registers.trace_enabled = false;
1121        self.registers.interrupt_priority_mask = DEFAULT_INTERRUPT_MASK;
1122
1123        self.registers.stopped = false;
1124        self.registers.frozen = false;
1125
1126        // Read SSP from $000000 and PC from $000004
1127        self.registers.ssp = bus.read_long_word(0);
1128        self.registers.pc = bus.read_long_word(4);
1129
1130        log::trace!("RESET vector: {:04X}", self.registers.pc);
1131
1132        self.populate_prefetch(bus);
1133    }
1134
1135    fn populate_prefetch(&mut self, bus: &mut impl BusInterface) {
1136        let mut executor = InstructionExecutor::new(self, bus);
1137        if let Err(exception) = executor.jump_to_address(executor.cpu.registers.pc) {
1138            executor.handle_exception(exception);
1139        }
1140    }
1141
1142    #[must_use]
1143    pub fn data_registers(&self) -> [u32; 8] {
1144        self.registers.data
1145    }
1146
1147    pub fn set_data_registers(&mut self, registers: [u32; 8]) {
1148        self.registers.data = registers;
1149    }
1150
1151    #[must_use]
1152    pub fn address_registers(&self) -> [u32; 7] {
1153        self.registers.address
1154    }
1155
1156    #[must_use]
1157    pub fn user_stack_pointer(&self) -> u32 {
1158        self.registers.usp
1159    }
1160
1161    #[must_use]
1162    pub fn supervisor_stack_pointer(&self) -> u32 {
1163        self.registers.ssp
1164    }
1165
1166    #[must_use]
1167    pub fn stack_pointer(&self) -> u32 {
1168        if self.registers.supervisor_mode { self.registers.ssp } else { self.registers.usp }
1169    }
1170
1171    pub fn set_supervisor_stack_pointer(&mut self, ssp: u32) {
1172        self.registers.ssp = ssp;
1173    }
1174
1175    pub fn set_address_registers(&mut self, registers: [u32; 7], usp: u32, ssp: u32) {
1176        self.registers.address = registers;
1177        self.registers.usp = usp;
1178        self.registers.ssp = ssp;
1179    }
1180
1181    #[must_use]
1182    pub fn status_register(&self) -> u16 {
1183        self.registers.status_register()
1184    }
1185
1186    pub fn set_status_register(&mut self, status_register: u16) {
1187        self.registers.set_status_register(status_register);
1188    }
1189
1190    #[must_use]
1191    pub fn pc(&self) -> u32 {
1192        self.registers.pc
1193    }
1194
1195    pub fn set_pc(&mut self, pc: u32, bus: &mut impl BusInterface) {
1196        self.registers.pc = pc;
1197        self.populate_prefetch(bus);
1198    }
1199
1200    #[must_use]
1201    pub fn address_error(&self) -> bool {
1202        self.registers.address_error
1203    }

True if the most recently executed instruction was MULU, MULS, DIVU, or DIVS

1206    #[inline]
1207    #[must_use]
1208    pub fn last_instruction_was_mul_or_div(&self) -> bool {
1209        self.registers.last_instruction_was_muldiv
1210    }
1212    #[inline]
1213    #[must_use]
1214    pub fn next_opcode(&self) -> u16 {
1215        self.registers.prefetch
1216    }
1217
1218    #[inline]
1219    pub fn execute_instruction<B: BusInterface>(&mut self, bus: &mut B) -> u32 {
1220        if bus.reset() {
1221            self.reset(bus);
1222            return RESET_CYCLES;
1223        }
1224
1225        if bus.halt() || self.registers.frozen {
1226            return 1;
1227        }
1228
1229        InstructionExecutor::new(self, bus).execute()
1230    }
1231}