1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Attempts an implementation of CHK.

1467 is now the official count of things to implement, though I'm starting to get suspicious.
This commit is contained in:
Thomas Harte 2019-04-28 15:47:21 -04:00
parent f4350522bf
commit 8e8dce9bec
3 changed files with 91 additions and 17 deletions

View File

@ -944,28 +944,38 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> 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.

View File

@ -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();

View File

@ -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;