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

Takes a run at TRAP.

This commit is contained in:
Thomas Harte 2019-04-17 22:21:56 -04:00
parent b8a0f4e831
commit e49b257e94
3 changed files with 83 additions and 34 deletions

View File

@ -548,7 +548,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
} \
\
auto step = bus_program; \
uint32_t *address_storage = movem_addresses_; \
uint32_t *address_storage = precomputed_addresses_; \
mask = next_word_; \
int offset = 0;
@ -596,7 +596,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
}
case Operation::MOVEMtoRl: {
setup_movem(2, movem_reads_steps_);
setup_movem(2, movem_read_steps_);
// Everything for move to registers is based on an incrementing
// address; per M68000PRM:
@ -613,23 +613,23 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
// MOVEM to R always reads one word too many.
address_storage[0] = start_address;
step[0].microcycle.address = step[1].microcycle.address = address_storage;
step[0].microcycle.value = step[1].microcycle.value = &movem_spare_value_;
step[0].microcycle.value = step[1].microcycle.value = &throwaway_value_;
movem_final_address_ = start_address;
} break;
case Operation::MOVEMtoRw: {
setup_movem(1, movem_reads_steps_);
setup_movem(1, movem_read_steps_);
write_address_sequence_word(inc_action);
// MOVEM to R always reads one word too many.
address_storage[0] = start_address;
step[0].microcycle.address = step[1].microcycle.address = address_storage;
step[0].microcycle.value = step[1].microcycle.value = &movem_spare_value_;
step[0].microcycle.value = step[1].microcycle.value = &throwaway_value_;
movem_final_address_ = start_address;
} break;
case Operation::MOVEMtoMl: {
setup_movem(2, movem_writes_steps_);
setup_movem(2, movem_write_steps_);
// MOVEM to M counts downwards and enumerates the registers in reverse order
// if subject to the predecrementing mode; otherwise it counts upwards and
@ -652,7 +652,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
} break;
case Operation::MOVEMtoMw: {
setup_movem(1, movem_writes_steps_);
setup_movem(1, movem_write_steps_);
if(mode == 4) {
offset = 15;
@ -669,6 +669,27 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
#undef inc_action
#undef dec_action
// TRAP, which is a nicer form of ILLEGAL.
case Operation::TRAP: {
// Select the trap steps as next.
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;
} break;
/*
NEGs: negatives the destination, setting the zero,
negative, overflow and carry flags appropriate, and extend.

View File

@ -377,6 +377,8 @@ struct ProcessorStorageConstructor {
RTS, // Maps to an RST.
MOVEUSP, // Maps a direction and register to a MOVE [to/from] USP.
TRAP, // Maps to a TRAP.
};
using Operation = ProcessorStorage::Operation;
@ -557,6 +559,7 @@ struct ProcessorStorageConstructor {
{0xfff0, 0x4e60, Operation::MOVEAl, Decoder::MOVEUSP}, // 6-21 (p475)
{0xfff0, 0x4e40, Operation::TRAP, Decoder::TRAP}, // 4-188 (p292)
};
#ifndef NDEBUG
@ -2424,24 +2427,6 @@ struct ProcessorStorageConstructor {
// n np nr n np nw np
// continue;
// case 0x1005: // MOVE (xxx).W, (d16, An)
// np nr np nw np
// continue;
// case 0x1006: // MOVE (xxx).W, (d8, An, Xn)
// np nr n np nw np
// continue;
case bw2(Imm, d16An): // MOVE.bw #, (d16, An)
case bw2(Imm, d8AnXn): // MOVE.bw #, (d8, An, Xn)
case bw2(Imm, d16PC): // MOVE.bw #, (d16, PC)
case bw2(Imm, d8PCXn): // MOVE.bw #, (d8, PC, Xn)
storage_.instructions[instruction].source = &storage_.destination_bus_data_[0];
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::DestinationMask, seq("np"));
op(calc_action_for_mode(combined_destination_mode) | MicroOp::DestinationMask, seq(pseq("np nw np", combined_destination_mode), { ea(1) }, !is_byte_access ));
op(is_byte_access ? Action::SetMoveFlagsb : Action::SetMoveFlagsl);
break;
case bw2(XXXl, d16An): // MOVE.bw (xxx).l, (d16, An)
case bw2(XXXl, d8AnXn): // MOVE.bw (xxx).l, (d8, An, Xn)
case bw2(XXXl, d16PC): // MOVE.bw (xxx).l, (d16, PC)
@ -2470,6 +2455,25 @@ struct ProcessorStorageConstructor {
op(Action::PerformOperation, seq(pseq("np nW+ nw np", combined_destination_mode), { ea(1), ea(1) }));
break;
case bw2(Imm, d16An): // MOVE.bw #, (d16, An)
case bw2(Imm, d16PC): // MOVE.bw #, (d16, PC)
case bw2(Imm, d8PCXn): // MOVE.bw #, (d8, PC, Xn)
case bw2(Imm, d8AnXn): // MOVE.bw #, (d8, An, Xn)
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np"));
op(calc_action_for_mode(combined_destination_mode) | MicroOp::DestinationMask, seq(pseq("np", combined_destination_mode)));
op(Action::PerformOperation, seq("nw np", { ea(1) }, !is_byte_access));
break;
case l2(Imm, d16An): // MOVE.l #, (d16, An)
case l2(Imm, d16PC): // MOVE.l #, (d16, PC)
case l2(Imm, d8PCXn): // MOVE.l #, (d8, PC, Xn)
case l2(Imm, d8AnXn): // MOVE.l #, (d8, An, Xn)
op(Action::None, seq("np"));
op(int(Action::AssembleLongWordDataFromPrefetch) | MicroOp::SourceMask, seq("np"));
op(calc_action_for_mode(combined_destination_mode) | MicroOp::DestinationMask, seq(pseq("np", combined_destination_mode)));
op(Action::PerformOperation, seq("nW+ nw np", { ea(1), ea(1) }));
break;
//
// MOVE <ea>, (xxx).W
// MOVE <ea>, (xxx).L
@ -2697,6 +2701,14 @@ struct ProcessorStorageConstructor {
op(Action::None, seq("nn _ np"));
break;
case Decoder::TRAP: {
// TRAP involves some oddly-sequenced stack writes, so is calculated
// at runtime; also the same sequence is used for illegal instructions.
// So the entirety is scheduled at runtime.
op(Action::PerformOperation);
op();
} break;
case Decoder::TST: {
storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register);
@ -2864,8 +2876,11 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
}
movem_reads_pattern += "nr";
addresses.push_back(nullptr);
const size_t movem_reads_offset = constructor.assemble_program(movem_reads_pattern, addresses);
const size_t movem_writes_offset = constructor.assemble_program(movem_writes_pattern, addresses);
const size_t movem_read_offset = constructor.assemble_program(movem_reads_pattern, addresses);
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] });
// Install operations.
constructor.install_instructions();
@ -2882,8 +2897,17 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
dbcc_condition_false_no_branch_steps_ = &all_bus_steps_[dbcc_condition_false_no_branch_offset];
dbcc_condition_false_branch_steps_ = &all_bus_steps_[dbcc_condition_false_branch_offset];
movem_reads_steps_ = &all_bus_steps_[movem_reads_offset];
movem_writes_steps_ = &all_bus_steps_[movem_writes_offset];
movem_read_steps_ = &all_bus_steps_[movem_read_offset];
movem_write_steps_ = &all_bus_steps_[movem_write_offset];
// Link the trap steps but also fill in the program counter as the source
// for its parts, and use the computed addresses.
//
// Order of output is: PC.l, SR, PC.h.
trap_steps_ = &all_bus_steps_[trap_offset];
trap_steps_[1].microcycle.value = trap_steps_[2].microcycle.value = &program_counter_.halves.low;
trap_steps_[3].microcycle.value = trap_steps_[4].microcycle.value = &destination_bus_data_[0].halves.low;
trap_steps_[5].microcycle.value = trap_steps_[6].microcycle.value = &program_counter_.halves.high;
// Set initial state. Largely TODO.
active_step_ = reset_bus_steps_;

View File

@ -92,6 +92,8 @@ class ProcessorStorage {
ORb, ORw, ORl,
MULU, MULS,
TRAP,
};
/*!
@ -313,8 +315,10 @@ class ProcessorStorage {
BusStep *dbcc_condition_false_no_branch_steps_;
BusStep *dbcc_condition_false_branch_steps_;
BusStep *movem_reads_steps_;
BusStep *movem_writes_steps_;
BusStep *movem_read_steps_;
BusStep *movem_write_steps_;
BusStep *trap_steps_;
// Current bus step pointer, and outer program pointer.
Program *active_program_ = nullptr;
@ -329,9 +333,9 @@ class ProcessorStorage {
/// Sets or clears the supervisor flag, ensuring the stack pointer is properly updated.
void set_is_supervisor(bool);
// Transient storage for MOVEM.
uint32_t movem_addresses_[65];
RegisterPair16 movem_spare_value_;
// Transient storage for MOVEM, TRAP and others.
uint32_t precomputed_addresses_[65];
RegisterPair16 throwaway_value_;
uint32_t movem_final_address_;
/*!