From 8e8dce9bec82ceb92e7153ab51210c28fad90e85 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 28 Apr 2019 15:47:21 -0400 Subject: [PATCH] Attempts an implementation of CHK. 1467 is now the official count of things to implement, though I'm starting to get suspicious. --- .../Implementation/68000Implementation.hpp | 42 +++++++++------- .../68000/Implementation/68000Storage.cpp | 48 ++++++++++++++++++- .../68000/Implementation/68000Storage.hpp | 18 +++++++ 3 files changed, 91 insertions(+), 17 deletions(-) diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 64265056b..2b73a16e1 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -944,28 +944,38 @@ template void Proces // TRAP, which is a nicer form of ILLEGAL. case Operation::TRAP: { - // Select the trap steps as next. + // Select the trap steps as next; the initial microcycle should be 4 cycles long. bus_program = trap_steps_; - - // Fill in the status word value. - destination_bus_data_[0].full = get_status(); - - // Switch to supervisor mode. - set_is_supervisor(true); - - // Pick a vector. - effective_address_[0].full = ((decoded_instruction_ & 15) + 32) << 2; - - // Schedule the proper stack activity. - precomputed_addresses_[0] = address_[7].full - 2; - precomputed_addresses_[1] = address_[7].full - 6; - precomputed_addresses_[2] = address_[7].full - 4; - address_[7].full -= 6; + bus_program->microcycle.length = HalfCycles(8); + populate_trap_steps((decoded_instruction_ & 15) + 32, get_status()); // The program counter to push is actually one slot ago. program_counter_.full -= 2; } break; + case Operation::CHK: { + const bool is_under = int16_t(active_program_->destination->halves.low.full) < 0; + const bool is_over = int16_t(active_program_->destination->halves.low.full) > int16_t(active_program_->source->halves.low.full); + + // No exception is the default course of action; deviate only if an + // exception is necessary. + if(is_under || is_over) { + negative_flag_ = is_under ? 1 : 0; + + bus_program = trap_steps_; + if(is_under) { + bus_program->microcycle.length = HalfCycles(16); + } else { + bus_program->microcycle.length = HalfCycles(8); + } + populate_trap_steps(6, get_status()); + + // The program counter to push is two slots ago as whatever was the correct prefetch + // to continue without an exception has already happened, just in case. + program_counter_.full -= 4; + } + } break; + /* NEGs: negatives the destination, setting the zero, negative, overflow and carry flags appropriate, and extend. diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index a33e7b3ef..314d1924e 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -447,6 +447,7 @@ struct ProcessorStorageConstructor { MOVEUSP, // Maps a direction and register to a MOVE [to/from] USP. TRAP, // Maps to a TRAP. + CHK, // Maps to a CHK. NOP, // Maps to a NOP. @@ -664,6 +665,7 @@ struct ProcessorStorageConstructor { {0xfff0, 0x4e60, Operation::MOVEAl, Decoder::MOVEUSP}, // 6-21 (p475) {0xfff0, 0x4e40, Operation::TRAP, Decoder::TRAP}, // 4-188 (p292) + {0xf1c0, 0x4180, Operation::CHK, Decoder::CHK}, // 4-69 (p173) {0xffff, 0x4e77, Operation::RTE_RTR, Decoder::RTE_RTR}, // 4-168 (p272) [RTR] {0xffff, 0x4e73, Operation::RTE_RTR, Decoder::RTE_RTR}, // 6-84 (p538) [RTE] @@ -3211,6 +3213,50 @@ struct ProcessorStorageConstructor { op(); } break; + case Decoder::CHK: { + storage_.instructions[instruction].set_destination(storage_, Dn, data_register); + storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register); + + const int mode = combined_mode(ea_mode, ea_register); + switch(mode) { + default: continue; + + case Dn: // CHK Dn, Dn + op(Action::None, seq("np")); + break; + + case Ind: // CHK (An), Dn + case PostInc: // CHK (An)+, Dn + op(Action::None, seq("nr np", { a(ea_register) })); + if(mode == PostInc) { + op(int(Action::Increment2) | MicroOp::SourceMask); + } + break; + + case PreDec: // CHK (An)-, Dn + op(int(Action::Decrement2) | MicroOp::SourceMask, seq("n nr np", { a(ea_register) })); + break; + + case XXXl: // CHK (xxx).l, Dn + op(Action::None, seq("np")); + case XXXw: // CHK (xxx).w, Dn + case d16An: // CHK (d16, An), Dn + case d16PC: // CHK (d16, PC), Dn + case d8AnXn: // CHK (d8, An, Xn), Dn + case d8PCXn: // CHK (d8, PC, Xn), Dn + op(address_action_for_mode(mode) | MicroOp::SourceMask, seq(pseq("np nr", mode), { ea(0) })); + break; + + case Imm: // CHK #, Dn + op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np np")); + break; + } + + // The nn n here is correct if no exception is issued; otherwise this sequence will + // be replaced. + op(Action::PerformOperation, seq("nn n")); + } break; + case Decoder::TST: { storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register); @@ -3386,7 +3432,7 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() { const size_t movem_write_offset = constructor.assemble_program(movem_writes_pattern, addresses); // Target addresses and values will be filled in by TRAP/illegal too. - const size_t trap_offset = constructor.assemble_program("nn nw nw nW nV nv np np", { &precomputed_addresses_[0], &precomputed_addresses_[1], &precomputed_addresses_[2] }); + const size_t trap_offset = constructor.assemble_program("r nw nw nW nV nv np np", { &precomputed_addresses_[0], &precomputed_addresses_[1], &precomputed_addresses_[2] }); // Install operations. constructor.install_instructions(); diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 8d3263ed9..62e8d7945 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -105,6 +105,7 @@ class ProcessorStorage { RTE_RTR, TRAP, + CHK, EXG, SWAP, @@ -387,6 +388,23 @@ class ProcessorStorage { } } + inline void populate_trap_steps(uint32_t vector, uint16_t status) { + // Fill in the status word value. + destination_bus_data_[0].full = status; + + // Switch to supervisor mode. + set_is_supervisor(true); + + // Pick a vector. + effective_address_[0].full = vector << 2; + + // Schedule the proper stack activity. + precomputed_addresses_[0] = address_[7].full - 2; + precomputed_addresses_[1] = address_[7].full - 6; + precomputed_addresses_[2] = address_[7].full - 4; + address_[7].full -= 6; + } + private: friend class ProcessorStorageConstructor;