mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-28 07:29:45 +00:00
Implements (arguably: fixes) BSR.
This commit is contained in:
parent
1f0e3b157a
commit
dec5535e54
@ -190,15 +190,21 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
|||||||
active_step_->microcycle.length = HalfCycles(8 + ((active_program_->source->full & 31) / 16) * 4);
|
active_step_->microcycle.length = HalfCycles(8 + ((active_program_->source->full & 31) / 16) * 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Bcc: evaluates the relevant condition and displacement size and then:
|
// Bcc: ordinarily evaluates the relevant condition and displacement size and then:
|
||||||
// if condition is false, schedules bus operations to get past this instruction;
|
// if condition is false, schedules bus operations to get past this instruction;
|
||||||
// otherwise applies the offset and schedules bus operations to refill the prefetch queue.
|
// otherwise applies the offset and schedules bus operations to refill the prefetch queue.
|
||||||
|
//
|
||||||
|
// Special case: the condition code is 1, which is ordinarily false. In that case this
|
||||||
|
// is the trailing step of a BSR.
|
||||||
case Operation::Bcc: {
|
case Operation::Bcc: {
|
||||||
// Grab the 8-bit offset.
|
// Grab the 8-bit offset.
|
||||||
const int8_t byte_offset = int8_t(prefetch_queue_.halves.high.halves.low);
|
const int8_t byte_offset = int8_t(prefetch_queue_.halves.high.halves.low);
|
||||||
|
|
||||||
// Test the conditional.
|
// Check whether this is secretly BSR.
|
||||||
const bool should_branch = evaluate_condition(prefetch_queue_.halves.high.halves.high);
|
const bool is_bsr = ((decoded_instruction_ >> 8) & 0xf) == 1;
|
||||||
|
|
||||||
|
// Test the conditional, treating 'false' as true.
|
||||||
|
const bool should_branch = is_bsr || evaluate_condition(prefetch_queue_.halves.high.halves.high);
|
||||||
|
|
||||||
// Schedule something appropriate, by rewriting the program for this instruction temporarily.
|
// Schedule something appropriate, by rewriting the program for this instruction temporarily.
|
||||||
if(should_branch) {
|
if(should_branch) {
|
||||||
@ -208,7 +214,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
|||||||
program_counter_.full += int16_t(prefetch_queue_.halves.low.full);
|
program_counter_.full += int16_t(prefetch_queue_.halves.low.full);
|
||||||
}
|
}
|
||||||
program_counter_.full -= 2;
|
program_counter_.full -= 2;
|
||||||
bus_program = branch_taken_bus_steps_;
|
bus_program = is_bsr ? bsr_bus_steps_ : branch_taken_bus_steps_;
|
||||||
} else {
|
} else {
|
||||||
if(byte_offset) {
|
if(byte_offset) {
|
||||||
bus_program = branch_byte_not_taken_bus_steps_;
|
bus_program = branch_byte_not_taken_bus_steps_;
|
||||||
|
@ -332,7 +332,7 @@ struct ProcessorStorageConstructor {
|
|||||||
ADDASUBA, // Maps a destination register and a source mode and register to an ADDA or SUBA.
|
ADDASUBA, // Maps a destination register and a source mode and register to an ADDA or SUBA.
|
||||||
|
|
||||||
BRA, // Maps to a BRA. All fields are decoded at runtime.
|
BRA, // Maps to a BRA. All fields are decoded at runtime.
|
||||||
Bcc, // Maps to a Bcc. All fields are decoded at runtime.
|
BccBSR, // Maps to a Bcc or BSR. Other than determining the type of operation, fields are decoded at runtime.
|
||||||
|
|
||||||
BTST, // Maps a source register and a destination register and mode to a BTST.
|
BTST, // Maps a source register and a destination register and mode to a BTST.
|
||||||
BTSTIMM, // Maps a destination mode and register to a BTST #.
|
BTSTIMM, // Maps a destination mode and register to a BTST #.
|
||||||
@ -427,7 +427,7 @@ struct ProcessorStorageConstructor {
|
|||||||
{0xf1f8, 0xb188, Operation::CMPl, Decoder::CMPM}, // 4-81 (p185)
|
{0xf1f8, 0xb188, Operation::CMPl, Decoder::CMPM}, // 4-81 (p185)
|
||||||
|
|
||||||
// {0xff00, 0x6000, Operation::BRA, Decoder::BRA}, // 4-55 (p159) TODO: confirm that this really, really is just a special case of Bcc.
|
// {0xff00, 0x6000, Operation::BRA, Decoder::BRA}, // 4-55 (p159) TODO: confirm that this really, really is just a special case of Bcc.
|
||||||
{0xf000, 0x6000, Operation::Bcc, Decoder::Bcc}, // 4-25 (p129)
|
{0xf000, 0x6000, Operation::Bcc, Decoder::BccBSR}, // 4-25 (p129) and 4-59 (p163)
|
||||||
|
|
||||||
{0xf1c0, 0x41c0, Operation::MOVEAl, Decoder::LEA}, // 4-110 (p214)
|
{0xf1c0, 0x41c0, Operation::MOVEAl, Decoder::LEA}, // 4-110 (p214)
|
||||||
{0xf100, 0x7000, Operation::MOVEq, Decoder::MOVEq}, // 4-134 (p238)
|
{0xf100, 0x7000, Operation::MOVEq, Decoder::MOVEq}, // 4-134 (p238)
|
||||||
@ -848,7 +848,16 @@ struct ProcessorStorageConstructor {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
// This decoder actually decodes nothing; it just schedules a PerformOperation followed by an empty step.
|
// This decoder actually decodes nothing; it just schedules a PerformOperation followed by an empty step.
|
||||||
case Decoder::Bcc: {
|
case Decoder::BccBSR: {
|
||||||
|
const int condition = (instruction >> 8) & 0xf;
|
||||||
|
if(condition == 1) {
|
||||||
|
// This is BSR, which is unconditional and means pushing a return address to the stack first.
|
||||||
|
|
||||||
|
// Push the return address to the stack.
|
||||||
|
op(Action::PrepareJSR, seq("n nW+ nw", { ea(1), ea(1) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is Bcc.
|
||||||
op(Action::PerformOperation);
|
op(Action::PerformOperation);
|
||||||
op(); // The above looks terminal, but will be dynamically reprogrammed.
|
op(); // The above looks terminal, but will be dynamically reprogrammed.
|
||||||
} break;
|
} break;
|
||||||
@ -2511,6 +2520,7 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
|
|||||||
const size_t branch_taken_offset = constructor.assemble_program("n np np");
|
const size_t branch_taken_offset = constructor.assemble_program("n np np");
|
||||||
const size_t branch_byte_not_taken_offset = constructor.assemble_program("nn np");
|
const size_t branch_byte_not_taken_offset = constructor.assemble_program("nn np");
|
||||||
const size_t branch_word_not_taken_offset = constructor.assemble_program("nn np np");
|
const size_t branch_word_not_taken_offset = constructor.assemble_program("nn np np");
|
||||||
|
const size_t bsr_offset = constructor.assemble_program("np np");
|
||||||
|
|
||||||
const size_t dbcc_condition_true_offset = constructor.assemble_program("nn np np");
|
const size_t dbcc_condition_true_offset = constructor.assemble_program("nn np np");
|
||||||
const size_t dbcc_condition_false_no_branch_offset = constructor.assemble_program("n nr np np", { &dbcc_false_address_ });
|
const size_t dbcc_condition_false_no_branch_offset = constructor.assemble_program("n nr np np", { &dbcc_false_address_ });
|
||||||
@ -2539,6 +2549,7 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
|
|||||||
branch_taken_bus_steps_ = &all_bus_steps_[branch_taken_offset];
|
branch_taken_bus_steps_ = &all_bus_steps_[branch_taken_offset];
|
||||||
branch_byte_not_taken_bus_steps_ = &all_bus_steps_[branch_byte_not_taken_offset];
|
branch_byte_not_taken_bus_steps_ = &all_bus_steps_[branch_byte_not_taken_offset];
|
||||||
branch_word_not_taken_bus_steps_ = &all_bus_steps_[branch_word_not_taken_offset];
|
branch_word_not_taken_bus_steps_ = &all_bus_steps_[branch_word_not_taken_offset];
|
||||||
|
bsr_bus_steps_ = &all_bus_steps_[bsr_offset];
|
||||||
|
|
||||||
dbcc_condition_true_steps_ = &all_bus_steps_[dbcc_condition_true_offset];
|
dbcc_condition_true_steps_ = &all_bus_steps_[dbcc_condition_true_offset];
|
||||||
dbcc_condition_false_no_branch_steps_ = &all_bus_steps_[dbcc_condition_false_no_branch_offset];
|
dbcc_condition_false_no_branch_steps_ = &all_bus_steps_[dbcc_condition_false_no_branch_offset];
|
||||||
|
@ -297,6 +297,7 @@ class ProcessorStorage {
|
|||||||
BusStep *branch_taken_bus_steps_;
|
BusStep *branch_taken_bus_steps_;
|
||||||
BusStep *branch_byte_not_taken_bus_steps_;
|
BusStep *branch_byte_not_taken_bus_steps_;
|
||||||
BusStep *branch_word_not_taken_bus_steps_;
|
BusStep *branch_word_not_taken_bus_steps_;
|
||||||
|
BusStep *bsr_bus_steps_;
|
||||||
|
|
||||||
uint32_t dbcc_false_address_;
|
uint32_t dbcc_false_address_;
|
||||||
BusStep *dbcc_condition_true_steps_;
|
BusStep *dbcc_condition_true_steps_;
|
||||||
|
Loading…
Reference in New Issue
Block a user