jevsnes.git / third-party / rust / jgenesis / cpu / m68000-emu / src / core / instructions.rs
1mod arithmetic;
2mod bits;
3mod controlflow;
4mod load;
5mod table;
6
7use crate::core::{
8    AddressRegister, AddressingMode, ConditionCodes, DataRegister, Exception, ExecuteResult,
9    InstructionExecutor, OpSize, Registers,
10};
11use crate::debug::BusDebugExt;
12use crate::traits::BusInterface;
13use jgenesis_proc_macros::EnumAll;
14use std::fmt::{Display, Formatter};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum Direction {
18    RegisterToMemory,
19    MemoryToRegister,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum UspDirection {
24    RegisterToUsp,
25    UspToRegister,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum ShiftDirection {
30    Left,
31    Right,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum ShiftCount {
36    Constant(u8),
37    Register(DataRegister),
38}
39
40impl ShiftCount {
41    fn get(self, registers: &Registers) -> u8 {
42        match self {
43            Self::Constant(count) => count,
44            Self::Register(register) => register.read_from(registers) as u8,
45        }
46    }
47}
48
49impl Display for ShiftCount {
50    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
51        match self {
52            Self::Constant(n) => write!(f, "#<{n}>"),
53            Self::Register(register) => write!(f, "D{}", register.0),
54        }
55    }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumAll)]
59pub enum BranchCondition {
60    True,
61    False,
62    Higher,
63    LowerOrSame,
64    CarryClear,
65    CarrySet,
66    NotEqual,
67    Equal,
68    OverflowClear,
69    OverflowSet,
70    Plus,
71    Minus,
72    GreaterOrEqual,
73    LessThan,
74    GreaterThan,
75    LessOrEqual,
76}
77
78impl BranchCondition {
79    fn check(self, ccr: ConditionCodes) -> bool {
80        match self {
81            Self::True => true,
82            Self::False => false,
83            Self::Higher => !ccr.carry && !ccr.zero,
84            Self::LowerOrSame => ccr.carry || ccr.zero,
85            Self::CarryClear => !ccr.carry,
86            Self::CarrySet => ccr.carry,
87            Self::NotEqual => !ccr.zero,
88            Self::Equal => ccr.zero,
89            Self::OverflowClear => !ccr.overflow,
90            Self::OverflowSet => ccr.overflow,
91            Self::Plus => !ccr.negative,
92            Self::Minus => ccr.negative,
93            Self::GreaterOrEqual => ccr.negative == ccr.overflow,
94            Self::LessThan => ccr.negative != ccr.overflow,
95            Self::GreaterThan => !ccr.zero && ccr.negative == ccr.overflow,
96            Self::LessOrEqual => ccr.zero || ccr.negative != ccr.overflow,
97        }
98    }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub enum Instruction {
103    Add { size: OpSize, source: AddressingMode, dest: AddressingMode, with_extend: bool },
104    AddDecimal { source: AddressingMode, dest: AddressingMode },
105    And { size: OpSize, source: AddressingMode, dest: AddressingMode },
106    AndToCcr,
107    AndToSr,
108    ArithmeticShiftMemory(ShiftDirection, AddressingMode),
109    ArithmeticShiftRegister(OpSize, ShiftDirection, DataRegister, ShiftCount),
110    BitTest { source: AddressingMode, dest: AddressingMode },
111    BitTestAndChange { source: AddressingMode, dest: AddressingMode },
112    BitTestAndClear { source: AddressingMode, dest: AddressingMode },
113    BitTestAndSet { source: AddressingMode, dest: AddressingMode },
114    Branch(BranchCondition, i8),
115    BranchDecrement(BranchCondition, DataRegister),
116    BranchToSubroutine(i8),
117    CheckRegister(DataRegister, AddressingMode),
118    Clear(OpSize, AddressingMode),
119    Compare { size: OpSize, source: AddressingMode, dest: AddressingMode },
120    DivideSigned(DataRegister, AddressingMode),
121    DivideUnsigned(DataRegister, AddressingMode),
122    ExchangeAddress(AddressRegister, AddressRegister),
123    ExchangeData(DataRegister, DataRegister),
124    ExchangeDataAddress(DataRegister, AddressRegister),
125    ExclusiveOr { size: OpSize, source: AddressingMode, dest: AddressingMode },
126    ExclusiveOrToCcr,
127    ExclusiveOrToSr,
128    Extend(OpSize, DataRegister),
129    Illegal { opcode: u16 },
130    Jump(AddressingMode),
131    JumpToSubroutine(AddressingMode),
132    Link(AddressRegister),
133    LoadEffectiveAddress(AddressingMode, AddressRegister),
134    LogicalShiftMemory(ShiftDirection, AddressingMode),
135    LogicalShiftRegister(OpSize, ShiftDirection, DataRegister, ShiftCount),
136    Move { size: OpSize, source: AddressingMode, dest: AddressingMode },
137    MoveFromSr(AddressingMode),
138    MoveMultiple(OpSize, AddressingMode, Direction),
139    MovePeripheral(OpSize, DataRegister, AddressRegister, Direction),
140    MoveQuick(i8, DataRegister),
141    MoveToCcr(AddressingMode),
142    MoveToSr(AddressingMode),
143    MoveUsp(UspDirection, AddressRegister),
144    MultiplySigned(DataRegister, AddressingMode),
145    MultiplyUnsigned(DataRegister, AddressingMode),
146    Negate { size: OpSize, dest: AddressingMode, with_extend: bool },
147    NegateDecimal(AddressingMode),
148    NoOp,
149    Not(OpSize, AddressingMode),
150    Or { size: OpSize, source: AddressingMode, dest: AddressingMode },
151    OrToCcr,
152    OrToSr,
153    PushEffectiveAddress(AddressingMode),
154    Reset,
155    Return { restore_ccr: bool },
156    ReturnFromException,
157    RotateMemory(ShiftDirection, AddressingMode),
158    RotateRegister(OpSize, ShiftDirection, DataRegister, ShiftCount),
159    RotateThruExtendMemory(ShiftDirection, AddressingMode),
160    RotateThruExtendRegister(OpSize, ShiftDirection, DataRegister, ShiftCount),
161    Set(BranchCondition, AddressingMode),
162    Subtract { size: OpSize, source: AddressingMode, dest: AddressingMode, with_extend: bool },
163    SubtractDecimal { source: AddressingMode, dest: AddressingMode },
164    Swap(DataRegister),
165    Stop,
166    Test(OpSize, AddressingMode),
167    TestAndSet(AddressingMode),
168    Trap(u32),
169    TrapOnOverflow,
170    Unlink(AddressRegister),
171}
172
173impl Instruction {
174    pub fn source_addressing_mode(self) -> Option<AddressingMode> {
175        match self {
176            Self::Add { source, .. }
177            | Self::AddDecimal { source, .. }
178            | Self::And { source, .. }
179            | Self::ArithmeticShiftMemory(_, source)
180            | Self::BitTest { source, .. }
181            | Self::BitTestAndChange { source, .. }
182            | Self::BitTestAndClear { source, .. }
183            | Self::BitTestAndSet { source, .. }
184            | Self::CheckRegister(_, source)
185            | Self::Compare { source, .. }
186            | Self::DivideSigned(_, source)
187            | Self::DivideUnsigned(_, source)
188            | Self::ExclusiveOr { source, .. }
189            | Self::LoadEffectiveAddress(source, ..)
190            | Self::LogicalShiftMemory(_, source)
191            | Self::Jump(source)
192            | Self::JumpToSubroutine(source)
193            | Self::Move { source, .. }
194            | Self::MoveToCcr(source)
195            | Self::MoveToSr(source)
196            | Self::MultiplySigned(_, source)
197            | Self::MultiplyUnsigned(_, source)
198            | Self::Or { source, .. }
199            | Self::PushEffectiveAddress(source)
200            | Self::RotateMemory(_, source)
201            | Self::RotateThruExtendMemory(_, source)
202            | Self::Subtract { source, .. }
203            | Self::SubtractDecimal { source, .. }
204            | Self::Test(_, source) => Some(source),
205            Self::AndToCcr
206            | Self::AndToSr
207            | Self::ArithmeticShiftRegister(..)
208            | Self::Branch(..)
209            | Self::BranchDecrement(..)
210            | Self::BranchToSubroutine(..)
211            | Self::Clear(..)
212            | Self::ExchangeAddress(..)
213            | Self::ExchangeData(..)
214            | Self::ExchangeDataAddress(..)
215            | Self::ExclusiveOrToCcr
216            | Self::ExclusiveOrToSr
217            | Self::Extend(..)
218            | Self::Illegal { .. }
219            | Self::Link(..)
220            | Self::LogicalShiftRegister(..)
221            | Self::MoveFromSr(..)
222            | Self::MoveMultiple(..)
223            | Self::MovePeripheral(..)
224            | Self::MoveQuick(..)
225            | Self::MoveUsp(..)
226            | Self::Negate { .. }
227            | Self::NegateDecimal(..)
228            | Self::NoOp
229            | Self::Not(..)
230            | Self::OrToCcr
231            | Self::OrToSr
232            | Self::Reset
233            | Self::Return { .. }
234            | Self::ReturnFromException
235            | Self::RotateRegister(..)
236            | Self::RotateThruExtendRegister(..)
237            | Self::Set(..)
238            | Self::Swap(..)
239            | Self::Stop
240            | Self::TestAndSet(..)
241            | Self::Trap(..)
242            | Self::TrapOnOverflow
243            | Self::Unlink(..) => None,
244        }
245    }
246
247    pub fn dest_addressing_mode(self) -> Option<AddressingMode> {
248        match self {
249            Self::Add { dest, .. }
250            | Self::AddDecimal { dest, .. }
251            | Self::And { dest, .. }
252            | Self::Clear(_, dest)
253            | Self::Compare { dest, .. }
254            | Self::ExclusiveOr { dest, .. }
255            | Self::Move { dest, .. }
256            | Self::MoveFromSr(dest)
257            | Self::Negate { dest, .. }
258            | Self::Not(_, dest)
259            | Self::Or { dest, .. }
260            | Self::Set(_, dest)
261            | Self::Subtract { dest, .. }
262            | Self::SubtractDecimal { dest, .. }
263            | Self::TestAndSet(dest) => Some(dest),
264            Self::AndToCcr
265            | Self::AndToSr
266            | Self::ArithmeticShiftMemory(..)
267            | Self::ArithmeticShiftRegister(..)
268            | Self::BitTest { .. }
269            | Self::BitTestAndChange { .. }
270            | Self::BitTestAndClear { .. }
271            | Self::BitTestAndSet { .. }
272            | Self::Branch(..)
273            | Self::BranchDecrement(..)
274            | Self::BranchToSubroutine(..)
275            | Self::CheckRegister(..)
276            | Self::DivideSigned(..)
277            | Self::DivideUnsigned(..)
278            | Self::ExchangeAddress(..)
279            | Self::ExchangeData(..)
280            | Self::ExchangeDataAddress(..)
281            | Self::ExclusiveOrToCcr
282            | Self::ExclusiveOrToSr
283            | Self::Extend(..)
284            | Self::Illegal { .. }
285            | Self::Jump(..)
286            | Self::JumpToSubroutine(..)
287            | Self::Link(..)
288            | Self::LoadEffectiveAddress(..)
289            | Self::LogicalShiftMemory(..)
290            | Self::LogicalShiftRegister(..)
291            | Self::MoveMultiple(..)
292            | Self::MovePeripheral(..)
293            | Self::MoveToCcr(..)
294            | Self::MoveToSr(..)
295            | Self::MoveUsp(..)
296            | Self::MoveQuick(..)
297            | Self::MultiplySigned(..)
298            | Self::MultiplyUnsigned(..)
299            | Self::NegateDecimal(..)
300            | Self::NoOp
301            | Self::OrToCcr
302            | Self::OrToSr
303            | Self::PushEffectiveAddress(..)
304            | Self::Reset
305            | Self::Return { .. }
306            | Self::ReturnFromException
307            | Self::RotateMemory(..)
308            | Self::RotateRegister(..)
309            | Self::RotateThruExtendMemory(..)
310            | Self::RotateThruExtendRegister(..)
311            | Self::Swap(..)
312            | Self::Stop
313            | Self::Test(..)
314            | Self::Trap(..)
315            | Self::TrapOnOverflow
316            | Self::Unlink(..) => None,
317        }
318    }
319
320    pub(crate) fn decode_from(opcode: u16) -> Self {
321        table::decode(opcode)
322    }
323}
324
325impl<B: BusInterface> InstructionExecutor<'_, '_, B> {
326    pub(super) fn do_execute(&mut self) -> ExecuteResult<u32> {
327        use Instruction::*;
328
329        let initial_pc = self.cpu.registers.pc;
330
331        self.bus.check_execute(initial_pc, self.cpu);
332
333        let opcode = self.fetch_operand()?;
334        self.opcode = opcode;
335
336        let instruction = table::decode(opcode);
337        self.instruction = Some(instruction);
338        log::trace!(
339            "[{}] Decoded opcode {opcode:04X} (PC={initial_pc:06X}): {instruction}",
340            self.cpu.name
341        );
342
343        self.cpu.registers.last_instruction_was_muldiv = matches!(
344            instruction,
345            MultiplyUnsigned(..) | MultiplySigned(..) | DivideUnsigned(..) | DivideSigned(..)
346        );
347
348        match instruction {
349            Add { size: OpSize::Byte, source, dest, with_extend } => {
350                self.add_byte(source, dest, with_extend)
351            }
352            Add { size: OpSize::Word, source, dest, with_extend } => {
353                self.add_word(source, dest, with_extend)
354            }
355            Add { size: OpSize::LongWord, source, dest, with_extend } => {
356                self.add_long_word(source, dest, with_extend)
357            }
358            AddDecimal { source, dest } => self.abcd(source, dest),
359            And { size: OpSize::Byte, source, dest } => self.and_byte(source, dest),
360            And { size: OpSize::Word, source, dest } => self.and_word(source, dest),
361            And { size: OpSize::LongWord, source, dest } => self.and_long_word(source, dest),
362            AndToCcr => self.andi_to_ccr(),
363            AndToSr => self.andi_to_sr(),
364            ArithmeticShiftMemory(direction, dest) => self.asd_memory(direction, dest),
365            ArithmeticShiftRegister(size, direction, register, count) => {
366                Ok(self.asd_register(size, direction, register, count))
367            }
368            BitTest { source, dest } => self.btst(source, dest),
369            BitTestAndChange { source, dest } => self.bchg(source, dest),
370            BitTestAndClear { source, dest } => self.bclr(source, dest),
371            BitTestAndSet { source, dest } => self.bset(source, dest),
372            Branch(condition, displacement) => self.branch(condition, displacement),
373            BranchDecrement(condition, register) => self.dbcc(condition, register),
374            BranchToSubroutine(displacement) => self.bsr(displacement),
375            CheckRegister(register, source) => self.chk(register, source),
376            Clear(OpSize::Byte, dest) => self.clr_byte(dest),
377            Clear(OpSize::Word, dest) => self.clr_word(dest),
378            Clear(OpSize::LongWord, dest) => self.clr_long_word(dest),
379            Compare { size: OpSize::Byte, source, dest } => self.cmp_byte(source, dest),
380            Compare { size: OpSize::Word, source, dest } => self.cmp_word(source, dest),
381            Compare { size: OpSize::LongWord, source, dest } => self.cmp_long_word(source, dest),
382            DivideSigned(register, source) => self.divs(register, source),
383            DivideUnsigned(register, source) => self.divu(register, source),
384            ExchangeAddress(rx, ry) => Ok(self.exg_address(rx, ry)),
385            ExchangeData(rx, ry) => Ok(self.exg_data(rx, ry)),
386            ExchangeDataAddress(rx, ry) => Ok(self.exg_data_address(rx, ry)),
387            ExclusiveOr { size: OpSize::Byte, source, dest } => self.eor_byte(source, dest),
388            ExclusiveOr { size: OpSize::Word, source, dest } => self.eor_word(source, dest),
389            ExclusiveOr { size: OpSize::LongWord, source, dest } => {
390                self.eor_long_word(source, dest)
391            }
392            ExclusiveOrToCcr => self.eori_to_ccr(),
393            ExclusiveOrToSr => self.eori_to_sr(),
394            Extend(size, register) => Ok(self.ext(size, register)),
395            Illegal { opcode } => Err(Exception::IllegalInstruction(opcode)),
396            Jump(source) => self.jmp(source),
397            JumpToSubroutine(source) => self.jsr(source),
398            Link(register) => self.link(register),
399            LoadEffectiveAddress(source, dest) => self.lea(source, dest),
400            LogicalShiftMemory(direction, dest) => self.lsd_memory(direction, dest),
401            LogicalShiftRegister(size, direction, register, count) => {
402                Ok(self.lsd_register(size, direction, register, count))
403            }
404            Move { size: OpSize::Byte, source, dest } => self.move_byte(source, dest),
405            Move { size: OpSize::Word, source, dest } => self.move_word(source, dest),
406            Move { size: OpSize::LongWord, source, dest } => self.move_long_word(source, dest),
407            MoveFromSr(dest) => self.move_from_sr(dest),
408            MoveMultiple(size, addressing_mode, direction) => {
409                self.movem(size, addressing_mode, direction)
410            }
411            MovePeripheral(size, d_register, a_register, direction) => {
412                self.movep(size, d_register, a_register, direction)
413            }
414            MoveQuick(data, register) => Ok(self.moveq(data, register)),
415            MoveToCcr(source) => self.move_to_ccr(source),
416            MoveToSr(source) => self.move_to_sr(source),
417            MoveUsp(direction, register) => self.move_usp(direction, register),
418            MultiplySigned(register, source) => self.muls(register, source),
419            MultiplyUnsigned(register, source) => self.mulu(register, source),
420            Negate { size: OpSize::Byte, dest, with_extend } => self.neg_byte(dest, with_extend),
421            Negate { size: OpSize::Word, dest, with_extend } => self.neg_word(dest, with_extend),
422            Negate { size: OpSize::LongWord, dest, with_extend } => {
423                self.neg_long_word(dest, with_extend)
424            }
425            NegateDecimal(dest) => self.nbcd(dest),
426            NoOp => Ok(controlflow::nop()),
427            Not(OpSize::Byte, dest) => self.not_byte(dest),
428            Not(OpSize::Word, dest) => self.not_word(dest),
429            Not(OpSize::LongWord, dest) => self.not_long_word(dest),
430            Or { size: OpSize::Byte, source, dest } => self.or_byte(source, dest),
431            Or { size: OpSize::Word, source, dest } => self.or_word(source, dest),
432            Or { size: OpSize::LongWord, source, dest } => self.or_long_word(source, dest),
433            OrToCcr => self.ori_to_ccr(),
434            OrToSr => self.ori_to_sr(),
435            PushEffectiveAddress(source) => self.pea(source),
436            Reset => Ok(controlflow::reset()),
437            Return { restore_ccr } => self.ret(restore_ccr),
438            ReturnFromException => self.rte(),
439            RotateMemory(direction, dest) => self.rod_memory(direction, dest),
440            RotateRegister(size, direction, register, count) => {
441                Ok(self.rod_register(size, direction, register, count))
442            }
443            RotateThruExtendMemory(direction, dest) => self.roxd_memory(direction, dest),
444            RotateThruExtendRegister(size, direction, register, count) => {
445                Ok(self.roxd_register(size, direction, register, count))
446            }
447            Set(condition, dest) => self.scc(condition, dest),
448            Subtract { size: OpSize::Byte, source, dest, with_extend } => {
449                self.sub_byte(source, dest, with_extend)
450            }
451            Subtract { size: OpSize::Word, source, dest, with_extend } => {
452                self.sub_word(source, dest, with_extend)
453            }
454            Subtract { size: OpSize::LongWord, source, dest, with_extend } => {
455                self.sub_long_word(source, dest, with_extend)
456            }
457            SubtractDecimal { source, dest } => self.sbcd(source, dest),
458            Swap(register) => Ok(self.swap(register)),
459            Stop => self.stop(),
460            Test(OpSize::Byte, source) => self.tst_byte(source),
461            Test(OpSize::Word, source) => self.tst_word(source),
462            Test(OpSize::LongWord, source) => self.tst_long_word(source),
463            TestAndSet(dest) => self.tas(dest),
464            Trap(vector) => controlflow::trap(vector),
465            TrapOnOverflow => self.trapv(),
466            Unlink(register) => self.unlk(register),
467        }
468    }
469}
470
471fn unary_op_cycles(size: OpSize, dest: AddressingMode) -> u32 {
472    let mut cycles = match size {
473        OpSize::Byte | OpSize::Word => 4,
474        OpSize::LongWord => 8,
475    };
476
477    cycles += dest.address_calculation_cycles(size);
478
479    // 2 cycles are saved in .l ops if operating on a data register
480    if size == OpSize::LongWord && dest.is_data_direct() {
481        cycles -= 2;
482    }
483
484    // Add 4 cycles if need to write back to memory
485    if !dest.is_data_direct() {
486        cycles += 4;
487    }
488
489    cycles
490}
491
492#[inline]
493fn binary_op_cycles(size: OpSize, source: AddressingMode, dest: AddressingMode) -> u32 {
494    let mut cycles = match size {
495        OpSize::Byte | OpSize::Word => 4,
496        OpSize::LongWord => 8,
497    };
498
499    // Word-size operations that write to address registers use the same circuitry as long word
500    // operations
501    if size == OpSize::Word && dest.is_address_direct() {
502        cycles += 4;
503    }
504
505    cycles += source.address_calculation_cycles(size);
506    cycles += dest.address_calculation_cycles(size);
507
508    // 2 cycles are saved in .l ops if the source is in memory and the destination is a register
509    if size == OpSize::LongWord
510        && source.is_memory()
511        && (dest.is_data_direct() || dest.is_address_direct())
512    {
513        cycles -= 2;
514    }
515
516    // 4 extra cycles are needed if the result is written back to memory
517    if dest.is_memory() {
518        cycles += 4;
519    }
520
521    cycles
522}
523
524#[inline]
525#[must_use]
526pub fn cycles_if_move_btst_cmp(opcode: u16) -> Option<u32> {
527    match table::decode(opcode) {
528        Instruction::Move { size, source, dest } => {
529            // -(An) destinations take 2 fewer cycles than they do in other operations
530            let base_cycles = match dest {
531                AddressingMode::AddressIndirectPredecrement(..) => 2,
532                _ => 4,
533            };
534
535            Some(
536                base_cycles
537                    + source.address_calculation_cycles(size)
538                    + dest.address_calculation_cycles(size),
539            )
540        }
541        Instruction::BitTest { source, dest } => {
542            let dest_cycles = match dest {
543                AddressingMode::DataDirect(..) => 2,
544                AddressingMode::Immediate => 6,
545                _ => dest.address_calculation_cycles(OpSize::Byte),
546            };
547
548            let source_cycles = match source {
549                AddressingMode::Immediate => 4,
550                _ => 0,
551            };
552
553            Some(4 + source_cycles + dest_cycles)
554        }
555        Instruction::Compare { size, source, dest } => Some(match size {
556            OpSize::Byte => arithmetic::cmp_cycles_byte(source, dest),
557            OpSize::Word => arithmetic::cmp_cycles_word(source, dest),
558            OpSize::LongWord => arithmetic::cmp_cycles_long_word(source, dest),
559        }),
560        _ => None,
561    }
562}
563
564impl Display for Instruction {
565    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
566        match self {
567            Self::Add { size, source, dest, with_extend: false } => {
568                write!(f, "ADD.{size} {source}, {dest}")
569            }
570            Self::Add { size, source, dest, with_extend: true } => {
571                write!(f, "ADDX.{size} {source}, {dest}")
572            }
573            Self::AddDecimal { source, dest } => {
574                write!(f, "ABCD {source}, {dest}")
575            }
576            Self::And { size, source, dest } => {
577                write!(f, "AND.{size} {source}, {dest}")
578            }
579            Self::AndToCcr => write!(f, "AND to CCR #<d>"),
580            Self::AndToSr => write!(f, "AND to SR #<d>"),
581            Self::ArithmeticShiftMemory(ShiftDirection::Left, dest) => {
582                write!(f, "ASL.w {dest}")
583            }
584            Self::ArithmeticShiftMemory(ShiftDirection::Right, dest) => {
585                write!(f, "ASR.w {dest}")
586            }
587            Self::ArithmeticShiftRegister(size, ShiftDirection::Left, register, count) => {
588                write!(f, "ASL.{size} {count}, D{}", register.0)
589            }
590            Self::ArithmeticShiftRegister(size, ShiftDirection::Right, register, count) => {
591                write!(f, "ASR.{size} {count}, D{}", register.0)
592            }
593            Self::BitTest { source, dest } => {
594                write!(f, "BTST {source}, {dest}")
595            }
596            Self::BitTestAndChange { source, dest } => {
597                write!(f, "BCHG {source}, {dest}")
598            }
599            Self::BitTestAndClear { source, dest } => {
600                write!(f, "BCLR {source}, {dest}")
601            }
602            Self::BitTestAndSet { source, dest } => {
603                write!(f, "BSET {source}, {dest}")
604            }
605            Self::Branch(BranchCondition::True, displacement) => {
606                write!(f, "BRA {displacement}")
607            }
608            Self::Branch(condition, displacement) => {
609                write!(f, "Bcc {displacement} (cc = {condition:?})")
610            }
611            Self::BranchDecrement(condition, register) => {
612                write!(f, "DBcc D{}, #<d> (cc = {condition:?})", register.0)
613            }
614            Self::BranchToSubroutine(displacement) => {
615                write!(f, "BSR {displacement}")
616            }
617            Self::CheckRegister(register, addressing_mode) => {
618                write!(f, "CHK {addressing_mode}, D{}", register.0)
619            }
620            Self::Clear(size, dest) => {
621                write!(f, "CLR.{size} {dest}")
622            }
623            Self::Compare { size, source, dest } => {
624                write!(f, "CMP.{size} {source}, {dest}")
625            }
626            Self::DivideSigned(register, addressing_mode) => {
627                write!(f, "DIVS {addressing_mode}, D{}", register.0)
628            }
629            Self::DivideUnsigned(register, addressing_mode) => {
630                write!(f, "DIVU {addressing_mode}, D{}", register.0)
631            }
632            Self::ExchangeAddress(a, b) => {
633                write!(f, "EXG A{}, A{}", a.0, b.0)
634            }
635            Self::ExchangeData(a, b) => {
636                write!(f, "EXG D{}, D{}", a.0, b.0)
637            }
638            Self::ExchangeDataAddress(data, address) => {
639                write!(f, "EXG D{}, A{}", data.0, address.0)
640            }
641            Self::ExclusiveOr { size, source, dest } => {
642                write!(f, "EOR.{size} {source}, {dest}")
643            }
644            Self::ExclusiveOrToCcr => write!(f, "EOR to CCR"),
645            Self::ExclusiveOrToSr => write!(f, "EOR to SR"),
646            Self::Extend(size, register) => {
647                write!(f, "EXT.{size} D{}", register.0)
648            }
649            Self::Illegal { .. } => write!(f, "ILLEGAL"),
650            Self::Jump(dest) => {
651                write!(f, "JMP {dest}")
652            }
653            Self::JumpToSubroutine(dest) => {
654                write!(f, "JSR {dest}")
655            }
656            Self::Link(register) => {
657                write!(f, "LINK A{}, #<d>", register.0)
658            }
659            Self::LoadEffectiveAddress(addressing_mode, register) => {
660                write!(f, "LEA {addressing_mode}, A{}", register.0)
661            }
662            Self::LogicalShiftMemory(ShiftDirection::Left, dest) => {
663                write!(f, "LSL.w {dest}")
664            }
665            Self::LogicalShiftMemory(ShiftDirection::Right, dest) => {
666                write!(f, "LSR.w {dest}")
667            }
668            Self::LogicalShiftRegister(size, ShiftDirection::Left, register, count) => {
669                write!(f, "LSL.{size} {count}, D{}", register.0)
670            }
671            Self::LogicalShiftRegister(size, ShiftDirection::Right, register, count) => {
672                write!(f, "LSR.{size} {count}, D{}", register.0)
673            }
674            Self::Move { size, source, dest } => {
675                write!(f, "MOVE.{size} {source}, {dest}")
676            }
677            Self::MoveFromSr(dest) => write!(f, "MOVE from SR {dest}"),
678            Self::MoveMultiple(size, addressing_mode, Direction::MemoryToRegister) => {
679                write!(f, "MOVEM.{size} {addressing_mode}, registers")
680            }
681            Self::MoveMultiple(size, addressing_mode, Direction::RegisterToMemory) => {
682                write!(f, "MOVEM.{size} registers, {addressing_mode}")
683            }
684            Self::MovePeripheral(size, data, address, Direction::MemoryToRegister) => {
685                write!(f, "MOVEP.{size} (d, A{}), D{}", address.0, data.0)
686            }
687            Self::MovePeripheral(size, data, address, Direction::RegisterToMemory) => {
688                write!(f, "MOVEP.{size} D{}, (d, A{})", data.0, address.0)
689            }
690            Self::MoveQuick(value, register) => {
691                write!(f, "MOVEQ #<{value}>, D{}", register.0)
692            }
693            Self::MoveToCcr(source) => {
694                write!(f, "MOVE to CCR {source}")
695            }
696            Self::MoveToSr(source) => {
697                write!(f, "MOVE to SR {source}")
698            }
699            Self::MoveUsp(UspDirection::RegisterToUsp, register) => {
700                write!(f, "MOVE to USP A{}", register.0)
701            }
702            Self::MoveUsp(UspDirection::UspToRegister, register) => {
703                write!(f, "MOVE from USP A{}", register.0)
704            }
705            Self::MultiplySigned(register, addressing_mode) => {
706                write!(f, "MULS {addressing_mode}, D{}", register.0)
707            }
708            Self::MultiplyUnsigned(register, addressing_mode) => {
709                write!(f, "MULU {addressing_mode}, D{}", register.0)
710            }
711            Self::Negate { size, dest, with_extend: false } => {
712                write!(f, "NEG.{size} {dest}")
713            }
714            Self::Negate { size, dest, with_extend: true } => {
715                write!(f, "NEGX.{size} {dest}")
716            }
717            Self::NegateDecimal(dest) => {
718                write!(f, "NBCD {dest}")
719            }
720            Self::NoOp => write!(f, "NOP"),
721            Self::Not(size, dest) => {
722                write!(f, "NOT.{size} {dest}")
723            }
724            Self::Or { size, source, dest } => {
725                write!(f, "OR.{size} {source}, {dest}")
726            }
727            Self::OrToCcr => write!(f, "OR to CCR #<d>"),
728            Self::OrToSr => write!(f, "OR to SR #<d>"),
729            Self::PushEffectiveAddress(source) => {
730                write!(f, "PEA {source}")
731            }
732            Self::Reset => write!(f, "RESET"),
733            Self::Return { restore_ccr: false } => write!(f, "RTS"),
734            Self::Return { restore_ccr: true } => write!(f, "RTR"),
735            Self::ReturnFromException => write!(f, "RTE"),
736            Self::RotateMemory(ShiftDirection::Left, dest) => {
737                write!(f, "ROL.w {dest}")
738            }
739            Self::RotateMemory(ShiftDirection::Right, dest) => {
740                write!(f, "ROR.w {dest}")
741            }
742            Self::RotateRegister(size, ShiftDirection::Left, register, count) => {
743                write!(f, "ROL.{size} {count}, D{}", register.0)
744            }
745            Self::RotateRegister(size, ShiftDirection::Right, register, count) => {
746                write!(f, "ROR.{size} {count}, D{}", register.0)
747            }
748            Self::RotateThruExtendMemory(ShiftDirection::Left, dest) => {
749                write!(f, "ROXL.w {dest}")
750            }
751            Self::RotateThruExtendMemory(ShiftDirection::Right, dest) => {
752                write!(f, "ROXR.w {dest}")
753            }
754            Self::RotateThruExtendRegister(size, ShiftDirection::Left, register, count) => {
755                write!(f, "ROXL.{size} {count}, D{}", register.0)
756            }
757            Self::RotateThruExtendRegister(size, ShiftDirection::Right, register, count) => {
758                write!(f, "ROXR.{size} {count}, D{}", register.0)
759            }
760            Self::Set(condition, dest) => {
761                write!(f, "Scc {dest} (cc = {condition:?})")
762            }
763            Self::Subtract { size, source, dest, with_extend: false } => {
764                write!(f, "SUB.{size} {source}, {dest}")
765            }
766            Self::Subtract { size, source, dest, with_extend: true } => {
767                write!(f, "SUBX.{size} {source}, {dest}")
768            }
769            Self::SubtractDecimal { source, dest } => {
770                write!(f, "SBCD {source}, {dest}")
771            }
772            Self::Swap(register) => {
773                write!(f, "SWAP D{}", register.0)
774            }
775            Self::Stop => write!(f, "STOP"),
776            Self::Test(size, source) => {
777                write!(f, "TST.{size} {source}")
778            }
779            Self::TestAndSet(dest) => {
780                write!(f, "TAS {dest}")
781            }
782            Self::Trap(vector) => {
783                write!(f, "TRAP #<{vector}>")
784            }
785            Self::TrapOnOverflow => {
786                write!(f, "TRAPV")
787            }
788            Self::Unlink(register) => {
789                write!(f, "UNLK A{}", register.0)
790            }
791        }
792    }
793}