mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 16:31:31 +00:00
Takes a run at CMPI.
Also factors out a couple of mode things, clarifies on where things from the prefetch are assembled to, and switches to ordering implemented instructions alphabetically.
This commit is contained in:
parent
3ccec1c996
commit
7163b1132c
@ -65,6 +65,10 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
||||
|
||||
case int(MicroOp::Action::PerformOperation):
|
||||
switch(active_program_->operation) {
|
||||
/*
|
||||
ABCD adds the lowest bytes form the source and destination using BCD arithmetic,
|
||||
obeying the extend flag.
|
||||
*/
|
||||
case Operation::ABCD: {
|
||||
// Pull out the two halves, for simplicity.
|
||||
const uint8_t source = active_program_->source->halves.low.halves.low;
|
||||
@ -86,25 +90,41 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
||||
active_program_->destination->halves.low.halves.low = uint8_t(result);
|
||||
} break;
|
||||
|
||||
case Operation::SBCD: {
|
||||
// Pull out the two halves, for simplicity.
|
||||
/*
|
||||
CMP.b, CMP.l and CMP.w: sets the condition flags (other than extend) based on a subtraction
|
||||
of the source from the destination; the result of the subtraction is not stored.
|
||||
*/
|
||||
case Operation::CMPb: {
|
||||
const uint8_t source = active_program_->source->halves.low.halves.low;
|
||||
const uint8_t destination = active_program_->destination->halves.low.halves.low;
|
||||
const int result = destination - source;
|
||||
|
||||
// Perform the BCD add by evaluating the two nibbles separately.
|
||||
int result = (destination & 0xf) - (source & 0xf) - (extend_flag_ ? 1 : 0);
|
||||
if(result > 0x09) result -= 0x06;
|
||||
result += (destination & 0xf0) - (source & 0xf0);
|
||||
if(result > 0x99) result -= 0x60;
|
||||
|
||||
// Set all flags essentially as if this were normal subtraction.
|
||||
zero_result_ |= result & 0xff;
|
||||
extend_flag_ = carry_flag_ = result & ~0xff;
|
||||
zero_result_ = result & 0xff;
|
||||
carry_flag_ = result & ~0xff;
|
||||
negative_flag_ = result & 0x80;
|
||||
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x80;
|
||||
} break;
|
||||
|
||||
// Store the result.
|
||||
active_program_->destination->halves.low.halves.low = uint8_t(result);
|
||||
case Operation::CMPw: {
|
||||
const uint16_t source = active_program_->source->halves.low.full;
|
||||
const uint16_t destination = active_program_->destination->halves.low.full;
|
||||
const int result = destination - source;
|
||||
|
||||
zero_result_ = result & 0xffff;
|
||||
carry_flag_ = result & ~0xffff;
|
||||
negative_flag_ = result & 0x8000;
|
||||
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x8000;
|
||||
} break;
|
||||
|
||||
case Operation::CMPl: {
|
||||
const uint32_t source = active_program_->source->full;
|
||||
const uint32_t destination = active_program_->destination->full;
|
||||
const uint64_t result = destination - source;
|
||||
|
||||
zero_result_ = uint32_t(result);
|
||||
carry_flag_ = result >> 32;
|
||||
negative_flag_ = result & 0x80000000;
|
||||
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x80000000;
|
||||
} break;
|
||||
|
||||
/*
|
||||
@ -134,7 +154,6 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
||||
MOVEA.w: move the least significant word and sign extend it.
|
||||
Neither sets any flags.
|
||||
*/
|
||||
|
||||
case Operation::MOVEAw:
|
||||
active_program_->destination->halves.low.full = active_program_->source->halves.low.full;
|
||||
active_program_->destination->halves.high.full = (active_program_->destination->halves.low.full & 0x8000) ? 0xffff : 0;
|
||||
@ -156,6 +175,31 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
||||
active_program_->source->halves.low.full = get_status();
|
||||
break;
|
||||
|
||||
/*
|
||||
SBCD subtracts the lowest byte of the source from that of the destination using
|
||||
BCD arithmetic, obeying the extend flag.
|
||||
*/
|
||||
case Operation::SBCD: {
|
||||
// Pull out the two halves, for simplicity.
|
||||
const uint8_t source = active_program_->source->halves.low.halves.low;
|
||||
const uint8_t destination = active_program_->destination->halves.low.halves.low;
|
||||
|
||||
// Perform the BCD add by evaluating the two nibbles separately.
|
||||
int result = (destination & 0xf) - (source & 0xf) - (extend_flag_ ? 1 : 0);
|
||||
if(result > 0x09) result -= 0x06;
|
||||
result += (destination & 0xf0) - (source & 0xf0);
|
||||
if(result > 0x99) result -= 0x60;
|
||||
|
||||
// Set all flags essentially as if this were normal subtraction.
|
||||
zero_result_ |= result & 0xff;
|
||||
extend_flag_ = carry_flag_ = result & ~0xff;
|
||||
negative_flag_ = result & 0x80;
|
||||
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x80;
|
||||
|
||||
// Store the result.
|
||||
active_program_->destination->halves.low.halves.low = uint8_t(result);
|
||||
} break;
|
||||
|
||||
/*
|
||||
Development period debugging.
|
||||
*/
|
||||
@ -275,22 +319,39 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
||||
|
||||
#undef CalculateD8AnXn
|
||||
|
||||
case int(MicroOp::Action::AssembleWordFromPrefetch) | MicroOp::SourceMask:
|
||||
case int(MicroOp::Action::AssembleWordAddressFromPrefetch) | MicroOp::SourceMask:
|
||||
// Assumption: this will be assembling right at the start of the instruction.
|
||||
effective_address_[0] = prefetch_queue_.halves.low.full;
|
||||
break;
|
||||
|
||||
case int(MicroOp::Action::AssembleWordFromPrefetch) | MicroOp::DestinationMask:
|
||||
case int(MicroOp::Action::AssembleWordAddressFromPrefetch) | MicroOp::DestinationMask:
|
||||
effective_address_[1] = prefetch_queue_.halves.low.full;
|
||||
break;
|
||||
|
||||
case int(MicroOp::Action::AssembleLongWordFromPrefetch) | MicroOp::SourceMask:
|
||||
case int(MicroOp::Action::AssembleLongWordAddressFromPrefetch) | MicroOp::SourceMask:
|
||||
effective_address_[0] = prefetch_queue_.full;
|
||||
break;
|
||||
|
||||
case int(MicroOp::Action::AssembleLongWordFromPrefetch) | MicroOp::DestinationMask:
|
||||
case int(MicroOp::Action::AssembleLongWordAddressFromPrefetch) | MicroOp::DestinationMask:
|
||||
effective_address_[1] = prefetch_queue_.full;
|
||||
break;
|
||||
|
||||
case int(MicroOp::Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask:
|
||||
// Assumption: this will be assembling right at the start of the instruction.
|
||||
bus_data_[0] = prefetch_queue_.halves.low.full;
|
||||
break;
|
||||
|
||||
case int(MicroOp::Action::AssembleWordDataFromPrefetch) | MicroOp::DestinationMask:
|
||||
bus_data_[1] = prefetch_queue_.halves.low.full;
|
||||
break;
|
||||
|
||||
case int(MicroOp::Action::AssembleLongWordDataFromPrefetch) | MicroOp::SourceMask:
|
||||
bus_data_[0] = prefetch_queue_.full;
|
||||
break;
|
||||
|
||||
case int(MicroOp::Action::AssembleLongWordDataFromPrefetch) | MicroOp::DestinationMask:
|
||||
bus_data_[1] = prefetch_queue_.full;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we've got to a micro-op that includes bus steps, break out of this loop.
|
||||
|
@ -18,6 +18,8 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
using BusStep = ProcessorStorage::BusStep;
|
||||
|
||||
/*!
|
||||
*/
|
||||
int calc_action_for_mode(int mode) const {
|
||||
using Action = ProcessorBase::MicroOp::Action;
|
||||
switch(mode & 0xff) {
|
||||
@ -29,6 +31,10 @@ struct ProcessorStorageConstructor {
|
||||
}
|
||||
}
|
||||
|
||||
int combined_mode(int mode, int reg) {
|
||||
return (mode == 7) ? (0x10 | reg) : mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Installs BusSteps that implement the described program into the relevant
|
||||
instance storage, returning the offset within @c all_bus_steps_ at which
|
||||
@ -227,9 +233,11 @@ struct ProcessorStorageConstructor {
|
||||
RegOpModeReg,
|
||||
SizeModeRegisterImmediate,
|
||||
DataSizeModeQuick,
|
||||
RegisterModeModeRegister, // i.e. twelve lowest bits are register, mode, mode, register, for destination and source respectively.
|
||||
ModeRegister, // i.e. six lowest bits are mode, then register.
|
||||
MOVEtoSR
|
||||
RegisterModeModeRegister, // twelve lowest bits are register, mode, mode, register, for destination and source respectively.
|
||||
ModeRegister, // six lowest bits are mode, then register.
|
||||
|
||||
MOVEtoSR, // six lowest bits are [mode, register], decoding to MOVE SR
|
||||
CMPI, // eight lowest bits are [size, mode, register], decoding to CMPI
|
||||
};
|
||||
|
||||
using Operation = ProcessorStorage::Operation;
|
||||
@ -271,6 +279,10 @@ struct ProcessorStorageConstructor {
|
||||
{0xf000, 0x3000, Operation::MOVEw, Decoder::RegisterModeModeRegister}, // 4-116 (p220)
|
||||
|
||||
{0xffc0, 0x46c0, Operation::MOVEtoSR, Decoder::MOVEtoSR}, // 6-19 (p473)
|
||||
|
||||
{0xffc0, 0x0c00, Operation::CMPb, Decoder::CMPI},
|
||||
{0xffc0, 0x0c40, Operation::CMPw, Decoder::CMPI},
|
||||
{0xffc0, 0x0c80, Operation::CMPl, Decoder::CMPI},
|
||||
};
|
||||
|
||||
std::vector<size_t> micro_op_pointers(65536, std::numeric_limits<size_t>::max());
|
||||
@ -290,6 +302,10 @@ struct ProcessorStorageConstructor {
|
||||
auto operation = mapping.operation;
|
||||
const auto micro_op_start = storage_.all_micro_ops_.size();
|
||||
|
||||
// The following fields are used commonly enough to be worht pulling out here.
|
||||
const int source_register = instruction & 7;
|
||||
const int source_mode = (instruction >> 3) & 7;
|
||||
|
||||
switch(mapping.decoder) {
|
||||
// Decodes the format used by ABCD and SBCD.
|
||||
case Decoder::Decimal: {
|
||||
@ -312,26 +328,125 @@ struct ProcessorStorageConstructor {
|
||||
}
|
||||
} break;
|
||||
|
||||
case Decoder::MOVEtoSR: {
|
||||
const int source_register = instruction & 7;
|
||||
const int source_mode = (instruction >> 3) & 7;
|
||||
case Decoder::CMPI: {
|
||||
if(source_mode == 1) continue;
|
||||
|
||||
switch(source_mode) {
|
||||
case 0: // Dn
|
||||
storage_.instructions[instruction].source = &storage_.data_[source_register];
|
||||
const auto destination_mode = source_mode;
|
||||
const auto destination_register = source_register;
|
||||
|
||||
storage_.instructions[instruction].source = &storage_.prefetch_queue_;
|
||||
storage_.instructions[instruction].set_destination(storage_, destination_mode, destination_register);
|
||||
|
||||
const bool is_byte_access = mapping.operation == Operation::CMPb;
|
||||
const bool is_long_word_access = mapping.operation == Operation::CMPl;
|
||||
const int mode = (is_long_word_access ? 0x100 : 0) | combined_mode(destination_mode, destination_register);
|
||||
switch(mode) {
|
||||
case 0x000: // CMPI.bw #, Dn
|
||||
op(Action::PerformOperation, seq("np np"));
|
||||
op();
|
||||
break;
|
||||
|
||||
case 1: continue; // An
|
||||
|
||||
default: // (An), (An)+, -(An), (d16, An), (d8, An Xn), (xxx).W, (xxx).L
|
||||
storage_.instructions[instruction].source = &storage_.bus_data_[0];
|
||||
storage_.instructions[instruction].destination = &storage_.bus_data_[1];
|
||||
case 0x100: // CMPI.l #, Dn
|
||||
op(Action::None, seq("np"));
|
||||
op(Action::PerformOperation, seq("np np n"));
|
||||
op();
|
||||
break;
|
||||
|
||||
case 0x002: // CMPI.bw #, (An)
|
||||
case 0x003: // CMPI.bw #, (An)+
|
||||
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np nr np", { &storage_.address_[destination_register].full }, !is_byte_access));
|
||||
if(mode == 0x3) {
|
||||
op(int(is_byte_access ? Action::Increment1 : Action::Increment2) | MicroOp::DestinationMask);
|
||||
}
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x102: // CMPI.l #, (An)
|
||||
case 0x103: // CMPI.l #, (An)+
|
||||
op(Action::CopyDestinationToEffectiveAddress, seq("np"));
|
||||
op(int(Action::AssembleLongWordDataFromPrefetch) | MicroOp::SourceMask, seq("np nR nr np", { &storage_.effective_address_[1] }));
|
||||
if(mode == 0x103) {
|
||||
op(int(Action::Increment4) | MicroOp::DestinationMask);
|
||||
}
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x004: // CMPI.bw #, -(An)
|
||||
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np n"));
|
||||
op(int(is_byte_access ? Action::Decrement1 : Action::Decrement1) | MicroOp::DestinationMask, seq("nr np", { &storage_.address_[destination_register].full }));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x104: // CMPI.l #, -(An)
|
||||
op(int(Action::Decrement4) | MicroOp::DestinationMask, seq("np"));
|
||||
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np n"));
|
||||
op(Action::CopyDestinationToEffectiveAddress, seq("nR nr np", { &storage_.effective_address_[1] }));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
#define pseq(x) ((mode == 0x06) || (mode == 0x13) ? "n" x : x)
|
||||
|
||||
case 0x012: // CMPI.bw #, (d16, PC)
|
||||
case 0x013: // CMPI.bw #, (d8, PC, Xn)
|
||||
case 0x005: // CMPI.bw #, (d16, An)
|
||||
case 0x006: // CMPI.bw #, (d8, An, Xn)
|
||||
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np"));
|
||||
op( calc_action_for_mode(destination_mode) | MicroOp::DestinationMask,
|
||||
seq(pseq("nr np"), { &storage_.effective_address_[1] }, !is_byte_access));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x112: // CMPI.l #, (d16, PC)
|
||||
case 0x113: // CMPI.l #, (d8, PC, Xn)
|
||||
case 0x105: // CMPI.l #, (d16, An)
|
||||
case 0x106: // CMPI.l #, (d8, An, Xn)
|
||||
op(Action::CopyDestinationToEffectiveAddress, seq("np"));
|
||||
op(int(Action::AssembleLongWordDataFromPrefetch) | MicroOp::SourceMask, seq("np"));
|
||||
op( calc_action_for_mode(destination_mode) | MicroOp::DestinationMask,
|
||||
seq(pseq("np nR nr np"), { &storage_.effective_address_[1] }));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
#undef pseq
|
||||
|
||||
case 0x010: // CMPI.bw #, (xxx).w
|
||||
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np"));
|
||||
op(int(Action::AssembleWordAddressFromPrefetch) | MicroOp::DestinationMask, seq("np nr np", { &storage_.effective_address_[1] }, !is_byte_access));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x110: // CMPI.l #, (xxx).w
|
||||
op(Action::None, seq("np"));
|
||||
op(int(Action::AssembleLongWordDataFromPrefetch) | MicroOp::SourceMask, seq("np np"));
|
||||
op(int(Action::AssembleWordAddressFromPrefetch) | MicroOp::DestinationMask, seq("nR nr np", { &storage_.effective_address_[1] }));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x011: // CMPI.bw #, (xxx).l
|
||||
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np np"));
|
||||
op(int(Action::AssembleLongWordAddressFromPrefetch) | MicroOp::DestinationMask, seq("np nr np", { &storage_.effective_address_[1] }, !is_byte_access));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x111: // CMPI.l #, (xxx).l
|
||||
op(Action::None, seq("np"));
|
||||
op(int(Action::AssembleLongWordDataFromPrefetch) | MicroOp::SourceMask, seq("np np"));
|
||||
op(int(Action::AssembleLongWordAddressFromPrefetch) | MicroOp::DestinationMask, seq("np nR nr np", { &storage_.effective_address_[1] }));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
default: continue;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Decoder::MOVEtoSR: {
|
||||
if(source_mode == 1) continue;
|
||||
storage_.instructions[instruction].set_source(storage_, source_mode, source_register);
|
||||
|
||||
/* DEVIATION FROM YACHT.TXT: it has all of these reading an extra word from the PC;
|
||||
this looks like a mistake so I've padded with nil cycles in the middle. */
|
||||
switch( (source_mode == 7) ? (0x10 | source_register) : source_mode) {
|
||||
const int mode = combined_mode(source_mode, source_register);
|
||||
switch(mode) {
|
||||
case 0x00: // MOVE Dn, SR
|
||||
op(Action::PerformOperation, seq("nn np"));
|
||||
op();
|
||||
@ -351,7 +466,7 @@ struct ProcessorStorageConstructor {
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
#define pseq(x) ((source_mode == 0x06) || (source_mode == 0x13) ? "n" x : x)
|
||||
#define pseq(x) ((mode == 0x06) || (mode == 0x13) ? "n" x : x)
|
||||
|
||||
case 0x12: // MOVE (d16, PC), SR
|
||||
case 0x13: // MOVE (d8, PC, Xn), SR
|
||||
@ -365,14 +480,14 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
case 0x10: // MOVE (xxx).W, SR
|
||||
op(
|
||||
int(MicroOp::Action::AssembleWordFromPrefetch) | MicroOp::SourceMask,
|
||||
int(MicroOp::Action::AssembleWordAddressFromPrefetch) | MicroOp::SourceMask,
|
||||
seq("np nr nn nn np", { &storage_.effective_address_[0] }));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
|
||||
case 0x11: // MOVE (xxx).L, SR
|
||||
op(Action::None, seq("np"));
|
||||
op(int(MicroOp::Action::AssembleLongWordFromPrefetch) | MicroOp::SourceMask, seq("np nr", { &storage_.effective_address_[0] }));
|
||||
op(int(MicroOp::Action::AssembleLongWordAddressFromPrefetch) | MicroOp::SourceMask, seq("np nr", { &storage_.effective_address_[0] }));
|
||||
op(Action::PerformOperation, seq("nn nn np"));
|
||||
op();
|
||||
break;
|
||||
@ -389,9 +504,6 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
// Decodes the format used by most MOVEs and all MOVEAs.
|
||||
case Decoder::RegisterModeModeRegister: {
|
||||
const int source_register = instruction & 7;
|
||||
const int source_mode = (instruction >> 3) & 7;
|
||||
|
||||
const int destination_mode = (instruction >> 6) & 7;
|
||||
const int destination_register = (instruction >> 9) & 7;
|
||||
|
||||
@ -454,8 +566,8 @@ struct ProcessorStorageConstructor {
|
||||
//
|
||||
// ... for no reason other than to make the switch below easy to read.
|
||||
const int both_modes =
|
||||
((source_mode == 7) ? (0x1000 | (source_register << 8)) : (source_mode << 8)) |
|
||||
((destination_mode == 7) ? (0x10 | destination_register) : destination_mode) |
|
||||
(combined_mode(source_mode, source_register) << 8) |
|
||||
combined_mode(destination_mode, destination_register) |
|
||||
(is_long_word_access ? 0x10000 : 0);
|
||||
|
||||
switch(both_modes) {
|
||||
@ -704,7 +816,7 @@ struct ProcessorStorageConstructor {
|
||||
operation = Operation::MOVEAw;
|
||||
case 0x1000: // MOVE (xxx).W, Dn
|
||||
op(
|
||||
int(MicroOp::Action::AssembleWordFromPrefetch) | MicroOp::SourceMask,
|
||||
int(MicroOp::Action::AssembleWordAddressFromPrefetch) | MicroOp::SourceMask,
|
||||
seq("np nr np", { &storage_.effective_address_[0] }, !is_byte_access));
|
||||
op(Action::PerformOperation);
|
||||
break;
|
||||
@ -742,7 +854,7 @@ struct ProcessorStorageConstructor {
|
||||
operation = Operation::MOVEAw;
|
||||
case 0x1100: // MOVE (xxx).L, Dn
|
||||
op(Action::None, seq("np"));
|
||||
op(int(MicroOp::Action::AssembleLongWordFromPrefetch) | MicroOp::SourceMask, seq("np nr", { &storage_.effective_address_[0] }, !is_byte_access));
|
||||
op(int(MicroOp::Action::AssembleLongWordAddressFromPrefetch) | MicroOp::SourceMask, seq("np nr", { &storage_.effective_address_[0] }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("np"));
|
||||
op();
|
||||
break;
|
||||
|
@ -48,7 +48,9 @@ class ProcessorStorage {
|
||||
MOVEb, MOVEw, MOVEl,
|
||||
MOVEAw, MOVEAl,
|
||||
|
||||
MOVEtoSR, MOVEfromSR
|
||||
MOVEtoSR, MOVEfromSR,
|
||||
|
||||
CMPb, CMPw, CMPl
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -163,10 +165,17 @@ class ProcessorStorage {
|
||||
|
||||
/// From the next word in the prefetch queue assembles a 0-padded 32-bit long word in either or
|
||||
/// both of effective_address_[0] and effective_address_[1].
|
||||
AssembleWordFromPrefetch,
|
||||
AssembleWordAddressFromPrefetch,
|
||||
|
||||
/// From the next word in the prefetch queue assembles a 0-padded 32-bit long word in either or
|
||||
/// both of bus_data_[0] and bus_data_[1].
|
||||
AssembleWordDataFromPrefetch,
|
||||
|
||||
/// Copies the next two prefetch words into one of the effective_address_.
|
||||
AssembleLongWordFromPrefetch
|
||||
AssembleLongWordAddressFromPrefetch,
|
||||
|
||||
/// Copies the next two prefetch words into one of the bus_data_.
|
||||
AssembleLongWordDataFromPrefetch
|
||||
};
|
||||
static const int SourceMask = 1 << 30;
|
||||
static const int DestinationMask = 1 << 29;
|
||||
@ -197,6 +206,22 @@ class ProcessorStorage {
|
||||
RegisterPair32 *destination = nullptr;
|
||||
Operation operation;
|
||||
bool requires_supervisor = false;
|
||||
|
||||
void set_source(ProcessorStorage &storage, int mode, int reg) {
|
||||
switch(mode) {
|
||||
case 0: source = &storage.data_[reg]; break;
|
||||
case 1: source = &storage.address_[reg]; break;
|
||||
default: source = &storage.bus_data_[0]; break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_destination(ProcessorStorage &storage, int mode, int reg) {
|
||||
switch(mode) {
|
||||
case 0: destination = &storage.data_[reg]; break;
|
||||
case 1: destination = &storage.address_[reg]; break;
|
||||
default: destination = &storage.bus_data_[1]; break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Storage for all the sequences of bus steps and micro-ops used throughout
|
||||
|
Loading…
Reference in New Issue
Block a user