diff --git a/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm b/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm index 76ee6fc67..3a1a8e074 100644 --- a/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm +++ b/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm @@ -72,16 +72,20 @@ class EmuTOS: public CPU::MC68000::BusHandler { case Microcycle::SelectWord | Microcycle::Read: cycle.value->full = is_peripheral ? peripheral_result : base[word_address]; + if(!(cycle.operation & Microcycle::IsProgram)) printf("[word r %08x -> %04x] ", *cycle.address, cycle.value->full); break; case Microcycle::SelectByte | Microcycle::Read: cycle.value->halves.low = (is_peripheral ? peripheral_result : base[word_address]) >> cycle.byte_shift(); + if(!(cycle.operation & Microcycle::IsProgram)) printf("[byte r %08x -> %02x] ", *cycle.address, cycle.value->halves.low); break; case Microcycle::SelectWord: assert(!(is_rom && !is_peripheral)); + if(!(cycle.operation & Microcycle::IsProgram)) printf("[word w %04x -> %08x] ", cycle.value->full, *cycle.address); base[word_address] = cycle.value->full; break; case Microcycle::SelectByte: assert(!(is_rom && !is_peripheral)); + if(!(cycle.operation & Microcycle::IsProgram)) printf("[byte w %02x -> %08x] ", cycle.value->halves.low, *cycle.address); base[word_address] = (cycle.value->halves.low << cycle.byte_shift()) | (base[word_address] & (0xffff ^ cycle.byte_mask())); break; } diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 373c275a9..fb9be46ff 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -855,6 +855,23 @@ template void Processor: active_program_->destination->halves.low.halves.low = uint8_t(result); } break; + // EXG and SWAP exchange/swap words or long words. + + case Operation::EXG: { + const auto temporary = active_program_->source->full; + active_program_->source->full = active_program_->destination->full; + active_program_->destination->full = temporary; + } break; + + case Operation::SWAP: { + const auto temporary = active_program_->destination->halves.low.full; + active_program_->destination->halves.low.full = active_program_->destination->halves.high.full; + active_program_->destination->halves.high.full = temporary; + + zero_result_ = active_program_->destination->full; + negative_flag_ = temporary & 0x8000; + } break; + /* Shifts and rotates. */ diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index 53bd90054..f61640cbe 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -400,6 +400,9 @@ struct ProcessorStorageConstructor { TRAP, // Maps to a TRAP. NOP, // Maps to a NOP. + + EXG, // Maps source and destination registers and an operation mode to an EXG. + SWAP, // Maps a source register to a SWAP. }; using Operation = ProcessorStorage::Operation; @@ -594,6 +597,12 @@ struct ProcessorStorageConstructor { {0xffff, 0x4e73, Operation::RTE_RTR, Decoder::RTE_RTR}, // 6-84 (p538) [RTE] {0xffff, 0x4e71, Operation::None, Decoder::NOP}, // 8-13 (p469) + + {0xf1f8, 0xc140, Operation::EXG, Decoder::EXG}, // 4-105 (p209) + {0xf1f8, 0xc148, Operation::EXG, Decoder::EXG}, // 4-105 (p209) + {0xf1f8, 0xc188, Operation::EXG, Decoder::EXG}, // 4-105 (p209) + + {0xfff8, 0x4840, Operation::SWAP, Decoder::SWAP}, // 4-185 (p289) }; std::vector micro_op_pointers(65536, std::numeric_limits::max()); @@ -628,6 +637,36 @@ struct ProcessorStorageConstructor { const int ea_mode = (instruction >> 3) & 7; switch(mapping.decoder) { + case Decoder::SWAP: { + storage_.instructions[instruction].set_destination(storage_, Dn, ea_register); + op(Action::None, seq("np")); + } break; + + case Decoder::EXG: { + const int data_register = (instruction >> 9) & 7; + + switch((instruction >> 3)&31) { + default: continue; + + case 0x08: + storage_.instructions[instruction].set_source(storage_, Dn, data_register); + storage_.instructions[instruction].set_destination(storage_, Dn, ea_register); + break; + + case 0x09: + storage_.instructions[instruction].set_source(storage_, An, data_register); + storage_.instructions[instruction].set_destination(storage_, An, ea_register); + break; + + case 0x11: + storage_.instructions[instruction].set_source(storage_, Dn, data_register); + storage_.instructions[instruction].set_destination(storage_, An, ea_register); + break; + } + + op(Action::None, seq("np")); + } break; + case Decoder::NOP: { op(Action::None, seq("np")); } break; diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index ce504c499..21deca651 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -96,6 +96,8 @@ class ProcessorStorage { RTE_RTR, TRAP, + + EXG, SWAP, }; /*!