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 } 1204 1205 /// 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 } 1211 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}