1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Takes a run at TAS, clarifying bus cycles.

This commit is contained in:
Thomas Harte 2019-04-25 12:19:40 -04:00
parent d2491633ce
commit 8557e563bc
3 changed files with 80 additions and 6 deletions

View File

@ -849,6 +849,18 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
case Operation::None: case Operation::None:
break; break;
/*
TAS: sets zero and negative depending on the current value of the destination,
and sets the high bit.
*/
case Operation::TAS:
overflow_flag_ = carry_flag_ = 0;
zero_result_ = active_program_->destination->halves.low.halves.low;
negative_flag_ = active_program_->destination->halves.low.halves.low & 0x80;
active_program_->destination->halves.low.halves.low |= 0x80;
break;
/* /*
Bitwise operators: AND, OR and EOR. All three clear the overflow and carry flags, Bitwise operators: AND, OR and EOR. All three clear the overflow and carry flags,
and set zero and negative appropriately. and set zero and negative appropriately.

View File

@ -145,6 +145,7 @@ struct ProcessorStorageConstructor {
* nF: fetch the SSPs MSW; * nF: fetch the SSPs MSW;
* nf: fetch the SSP's LSW; * nf: fetch the SSP's LSW;
* _: hold the reset line active for the usual period. * _: hold the reset line active for the usual period.
* tas: perform the final 6 cycles of a TAS: like an n nw but with the address strobe active for the entire period.
Quite a lot of that is duplicative, implying both something about internal Quite a lot of that is duplicative, implying both something about internal
state and something about what's observable on the bus, but it's helpful to state and something about what's observable on the bus, but it's helpful to
@ -213,7 +214,7 @@ struct ProcessorStorageConstructor {
steps.push_back(step); steps.push_back(step);
step.microcycle.length = HalfCycles(3); step.microcycle.length = HalfCycles(3);
step.microcycle.operation = Microcycle::SelectWord | Microcycle::Read | Microcycle::IsProgram; step.microcycle.operation = Microcycle::SameAddress | Microcycle::Read | Microcycle::IsProgram | Microcycle::SelectWord;
step.action = Action::IncrementEffectiveAddress0; step.action = Action::IncrementEffectiveAddress0;
steps.push_back(step); steps.push_back(step);
@ -229,7 +230,7 @@ struct ProcessorStorageConstructor {
steps.push_back(step); steps.push_back(step);
step.microcycle.length = HalfCycles(3); step.microcycle.length = HalfCycles(3);
step.microcycle.operation |= Microcycle::SelectWord | Microcycle::Read | Microcycle::IsProgram; step.microcycle.operation = Microcycle::SameAddress | Microcycle::Read | Microcycle::IsProgram | Microcycle::SelectWord;
step.action = Action::IncrementEffectiveAddress0; step.action = Action::IncrementEffectiveAddress0;
steps.push_back(step); steps.push_back(step);
@ -246,7 +247,7 @@ struct ProcessorStorageConstructor {
steps.push_back(step); steps.push_back(step);
step.microcycle.length = HalfCycles(3); step.microcycle.length = HalfCycles(3);
step.microcycle.operation |= Microcycle::SelectWord | Microcycle::Read | Microcycle::IsProgram; step.microcycle.operation = Microcycle::SameAddress | Microcycle::Read | Microcycle::IsProgram | Microcycle::SelectWord;
step.action = Action::IncrementProgramCounter; step.action = Action::IncrementProgramCounter;
steps.push_back(step); steps.push_back(step);
@ -277,7 +278,7 @@ struct ProcessorStorageConstructor {
steps.push_back(step); steps.push_back(step);
step.microcycle.length = HalfCycles(3); step.microcycle.length = HalfCycles(3);
step.microcycle.operation |= (read_full_words ? Microcycle::SelectWord : Microcycle::SelectByte) | (is_read ? Microcycle::Read : 0); step.microcycle.operation = Microcycle::SameAddress | (is_read ? Microcycle::Read : 0) | (read_full_words ? Microcycle::SelectWord : Microcycle::SelectByte);
if(post_adjustment) { if(post_adjustment) {
// nr and nR should affect address 0; nw, nW, nrd and nRd should affect address 1. // nr and nR should affect address 0; nw, nW, nrd and nRd should affect address 1.
if(tolower(token[1]) == 'r' && token.size() == 2) { if(tolower(token[1]) == 'r' && token.size() == 2) {
@ -293,6 +294,26 @@ struct ProcessorStorageConstructor {
continue; continue;
} }
// The completing part of a TAS.
if(token == "tas") {
RegisterPair32 *const scratch_data = &storage_.destination_bus_data_[0];
assert(address_iterator != addresses.end());
step.microcycle.length = HalfCycles(9);
step.microcycle.operation = Microcycle::SameAddress;
step.microcycle.address = *address_iterator;
step.microcycle.value = &scratch_data->halves.low;
steps.push_back(step);
step.microcycle.length = HalfCycles(3);
step.microcycle.operation = Microcycle::SameAddress | Microcycle::SelectByte;
steps.push_back(step);
++address_iterator;
continue;
}
// A stack write. // A stack write.
if(token == "nS" || token == "ns") { if(token == "nS" || token == "ns") {
RegisterPair32 *const scratch_data = &storage_.destination_bus_data_[0]; RegisterPair32 *const scratch_data = &storage_.destination_bus_data_[0];
@ -304,7 +325,7 @@ struct ProcessorStorageConstructor {
steps.push_back(step); steps.push_back(step);
step.microcycle.length = HalfCycles(3); step.microcycle.length = HalfCycles(3);
step.microcycle.operation |= Microcycle::SelectWord; step.microcycle.operation = Microcycle::SameAddress | Microcycle::SelectWord;
step.action = Action::DecrementEffectiveAddress1; step.action = Action::DecrementEffectiveAddress1;
steps.push_back(step); steps.push_back(step);
@ -322,7 +343,7 @@ struct ProcessorStorageConstructor {
steps.push_back(step); steps.push_back(step);
step.microcycle.length = HalfCycles(3); step.microcycle.length = HalfCycles(3);
step.microcycle.operation |= Microcycle::SelectWord; step.microcycle.operation = Microcycle::SameAddress | Microcycle::Read | Microcycle::SelectWord;
step.action = Action::IncrementEffectiveAddress0; step.action = Action::IncrementEffectiveAddress0;
steps.push_back(step); steps.push_back(step);
@ -432,6 +453,8 @@ struct ProcessorStorageConstructor {
EORI_ORI_ANDI_SR, // Maps to an EORI, ORI or ANDI to SR/CCR. EORI_ORI_ANDI_SR, // Maps to an EORI, ORI or ANDI to SR/CCR.
BCHG_BSET, // Maps a mode and register, and possibly a source register, to a BCHG or BSET. BCHG_BSET, // Maps a mode and register, and possibly a source register, to a BCHG or BSET.
TAS, // Maps a mode and register to a TAS.
}; };
using Operation = ProcessorStorage::Operation; using Operation = ProcessorStorage::Operation;
@ -644,6 +667,8 @@ struct ProcessorStorageConstructor {
{0xffc0, 0x0840, Operation::BCHGb, Decoder::BCHG_BSET}, // 4-29 (p133) {0xffc0, 0x0840, Operation::BCHGb, Decoder::BCHG_BSET}, // 4-29 (p133)
{0xf1c0, 0x01c0, Operation::BSETb, Decoder::BCHG_BSET}, // 4-57 (p161) {0xf1c0, 0x01c0, Operation::BSETb, Decoder::BCHG_BSET}, // 4-57 (p161)
{0xffc0, 0x08c0, Operation::BSETb, Decoder::BCHG_BSET}, // 4-58 (p162) {0xffc0, 0x08c0, Operation::BSETb, Decoder::BCHG_BSET}, // 4-58 (p162)
{0xffc0, 0x4ac0, Operation::TAS, Decoder::TAS}, // 4-186 (p290)
}; };
std::vector<size_t> micro_op_pointers(65536, std::numeric_limits<size_t>::max()); std::vector<size_t> micro_op_pointers(65536, std::numeric_limits<size_t>::max());
@ -689,6 +714,41 @@ struct ProcessorStorageConstructor {
#define inc(n) increment_action(is_long_word_access, is_byte_access, n) #define inc(n) increment_action(is_long_word_access, is_byte_access, n)
switch(mapping.decoder) { switch(mapping.decoder) {
case Decoder::TAS: {
const int mode = combined_mode(ea_mode, ea_register);
storage_.instructions[instruction].set_destination(storage_, ea_mode, ea_register);
switch(mode) {
default: continue;
case Dn: // TAS Dn
op(Action::PerformOperation, seq("np"));
break;
case Ind: // TAS (An)
case PostInc: // TAS (An)+
op(Action::None, seq("nrd", { a(ea_register) }, false));
op(Action::PerformOperation, seq("tas np", { a(ea_register) }, false));
if(mode == PostInc) {
op(byte_inc(ea_register) | MicroOp::DestinationMask);
}
break;
case PreDec: // TAS -(An)
op(byte_dec(ea_register) | MicroOp::DestinationMask, seq("n nrd", { a(ea_register) }, false));
op(Action::PerformOperation, seq("tas np", { a(ea_register) }, false));
break;
case XXXl: // TAS (xxx).l
op(Action::None, seq("np"));
case XXXw: // TAS (xxx).w
case d16An: // TAS (d16, An)
case d8AnXn: // TAS (d8, An, Xn)
op(address_action_for_mode(mode), seq("np nrd", { ea(1) }, false));
op(Action::PerformOperation, seq("tas np", { ea(1) }, false));
break;
}
} break;
case Decoder::BCHG_BSET: { case Decoder::BCHG_BSET: {
const int mode = combined_mode(ea_mode, ea_register); const int mode = combined_mode(ea_mode, ea_register);

View File

@ -107,6 +107,8 @@ class ProcessorStorage {
BCHGl, BCHGb, BCHGl, BCHGb,
BSETl, BSETb, BSETl, BSETb,
TAS,
}; };
/*! /*!