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

Adds an implementation of SBCD and slightly neatens syntax for building programs.

This commit is contained in:
Thomas Harte 2019-03-14 21:22:02 -04:00
parent f9101de956
commit 720aba3f2d
4 changed files with 42 additions and 15 deletions

View File

@ -84,4 +84,11 @@ class RAM68000: public CPU::MC68000::BusHandler {
_machine->run_for(HalfCycles(400)); _machine->run_for(HalfCycles(400));
} }
- (void)testSBCD {
_machine->set_program({
0x8100 // SBCD D0, D1
});
_machine->run_for(HalfCycles(400));
}
@end @end

View File

@ -26,16 +26,37 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
const uint8_t destination = active_program_->destination->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. // Perform the BCD add by evaluating the two nibbles separately.
int result = (source & 0xf) + (destination & 0xf) + (extend_flag_ ? 1 : 0); int result = (destination & 0xf) + (source & 0xf) + (extend_flag_ ? 1 : 0);
if(result > 0x9) result += 0x06; if(result > 0x9) result += 0x06;
result += (source & 0xf0) + (destination & 0xf0); result += (destination & 0xf0) + (source & 0xf0);
if(result > 0x90) result += 0x60; if(result > 0x90) result += 0x60;
// Set all flags essentially as if this were normal addition. // Set all flags essentially as if this were normal addition.
zero_flag_ |= result & 0xff; zero_flag_ |= result & 0xff;
extend_flag_ = carry_flag_ = result & ~0xff; extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80; negative_flag_ = result & 0x80;
overflow_flag_ = ~(source ^ destination) & (source ^ result) & 0x80; overflow_flag_ = ~(source ^ destination) & (destination ^ result) & 0x80;
// Store the result.
active_program_->destination->halves.low.halves.low = uint8_t(result);
} break;
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 > 0x9) result -= 0x06;
result += (destination & 0xf0) - (source & 0xf0);
if(result > 0x90) result -= 0x60;
// Set all flags essentially as if this were normal addition.
zero_flag_ |= result & 0xff;
extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x80;
// Store the result. // Store the result.
active_program_->destination->halves.low.halves.low = uint8_t(result); active_program_->destination->halves.low.halves.low = uint8_t(result);

View File

@ -232,26 +232,21 @@ void ProcessorStorage::install_instructions(const BusStepCollection &bus_step_co
const int source = instruction & 7; const int source = instruction & 7;
if(instruction & 8) { if(instruction & 8) {
// Install source and destination.
instructions[instruction].source = &bus_data_[0]; instructions[instruction].source = &bus_data_[0];
instructions[instruction].destination = &bus_data_[1]; instructions[instruction].destination = &bus_data_[1];
all_micro_ops_.emplace_back(); all_micro_ops_.emplace_back(
all_micro_ops_.back().bus_program = &all_bus_steps_[bus_step_collection.double_predec_byte[source][destination]]; MicroOp::Action::PredecrementSourceAndDestination1,
all_micro_ops_.back().action = MicroOp::Action::PredecrementSourceAndDestination1; &all_bus_steps_[bus_step_collection.double_predec_byte[source][destination]]);
all_micro_ops_.emplace_back(); all_micro_ops_.emplace_back(MicroOp::Action::PerformOperation);
all_micro_ops_.back().action = MicroOp::Action::PerformOperation;
all_micro_ops_.emplace_back(); all_micro_ops_.emplace_back();
} else { } else {
// Install source and destination.
instructions[instruction].source = &data_[source]; instructions[instruction].source = &data_[source];
instructions[instruction].destination = &data_[destination]; instructions[instruction].destination = &data_[destination];
// For micro-ops, just schedule the proper bus cycle to get the next thing into the prefetch queue, all_micro_ops_.emplace_back(
// then perform the actual operation. MicroOp::Action::PerformOperation,
all_micro_ops_.emplace_back(); &all_bus_steps_[bus_step_collection.six_step_Dn]);
all_micro_ops_.back().bus_program = &all_bus_steps_[bus_step_collection.six_step_Dn];
all_micro_ops_.back().action = MicroOp::Action::PerformOperation;
all_micro_ops_.emplace_back(); all_micro_ops_.emplace_back();
} }
} break; } break;

View File

@ -84,6 +84,10 @@ class ProcessorStorage {
PredecrementSourceAndDestination4, PredecrementSourceAndDestination4,
} action = Action::None; } action = Action::None;
BusStep *bus_program = nullptr; BusStep *bus_program = nullptr;
MicroOp() {}
MicroOp(Action action) : action(action) {}
MicroOp(Action action, BusStep *bus_program) : action(action), bus_program(bus_program) {}
}; };
/*! /*!