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}