mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-23 03:32:32 +00:00
Adds an implementation of SBCD and slightly neatens syntax for building programs.
This commit is contained in:
parent
f9101de956
commit
720aba3f2d
@ -84,4 +84,11 @@ class RAM68000: public CPU::MC68000::BusHandler {
|
||||
_machine->run_for(HalfCycles(400));
|
||||
}
|
||||
|
||||
- (void)testSBCD {
|
||||
_machine->set_program({
|
||||
0x8100 // SBCD D0, D1
|
||||
});
|
||||
_machine->run_for(HalfCycles(400));
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -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;
|
||||
|
||||
// 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;
|
||||
result += (source & 0xf0) + (destination & 0xf0);
|
||||
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) & (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.
|
||||
active_program_->destination->halves.low.halves.low = uint8_t(result);
|
||||
|
@ -232,26 +232,21 @@ void ProcessorStorage::install_instructions(const BusStepCollection &bus_step_co
|
||||
const int source = instruction & 7;
|
||||
|
||||
if(instruction & 8) {
|
||||
// Install source and destination.
|
||||
instructions[instruction].source = &bus_data_[0];
|
||||
instructions[instruction].destination = &bus_data_[1];
|
||||
|
||||
all_micro_ops_.emplace_back();
|
||||
all_micro_ops_.back().bus_program = &all_bus_steps_[bus_step_collection.double_predec_byte[source][destination]];
|
||||
all_micro_ops_.back().action = MicroOp::Action::PredecrementSourceAndDestination1;
|
||||
all_micro_ops_.emplace_back();
|
||||
all_micro_ops_.back().action = MicroOp::Action::PerformOperation;
|
||||
all_micro_ops_.emplace_back(
|
||||
MicroOp::Action::PredecrementSourceAndDestination1,
|
||||
&all_bus_steps_[bus_step_collection.double_predec_byte[source][destination]]);
|
||||
all_micro_ops_.emplace_back(MicroOp::Action::PerformOperation);
|
||||
all_micro_ops_.emplace_back();
|
||||
} else {
|
||||
// Install source and destination.
|
||||
instructions[instruction].source = &data_[source];
|
||||
instructions[instruction].destination = &data_[destination];
|
||||
|
||||
// For micro-ops, just schedule the proper bus cycle to get the next thing into the prefetch queue,
|
||||
// then perform the actual operation.
|
||||
all_micro_ops_.emplace_back();
|
||||
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(
|
||||
MicroOp::Action::PerformOperation,
|
||||
&all_bus_steps_[bus_step_collection.six_step_Dn]);
|
||||
all_micro_ops_.emplace_back();
|
||||
}
|
||||
} break;
|
||||
|
@ -84,6 +84,10 @@ class ProcessorStorage {
|
||||
PredecrementSourceAndDestination4,
|
||||
} action = Action::None;
|
||||
BusStep *bus_program = nullptr;
|
||||
|
||||
MicroOp() {}
|
||||
MicroOp(Action action) : action(action) {}
|
||||
MicroOp(Action action, BusStep *bus_program) : action(action), bus_program(bus_program) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
|
Loading…
Reference in New Issue
Block a user