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:
parent
f9101de956
commit
720aba3f2d
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Loading…
Reference in New Issue
Block a user