1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-01 13:58:20 +00:00

Cuts a third from the Program struct.

Observation: [source/destination]_address are always one of the address registers. So you can fit both within a single byte.

Net effect: around a 12% reduction in execution costs, given that this reduces the size of the instructions table from 3mb to 2mb.
This commit is contained in:
Thomas Harte 2019-07-24 18:39:36 -04:00
parent c300bd17fa
commit 827c4e172a
3 changed files with 47 additions and 36 deletions

View File

@ -365,9 +365,9 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
case int(MicroOp::Action::None): break;
#define source() active_program_->source
#define source_address() active_program_->source_address
#define source_address() address_[active_program_->source_dest >> 4]
#define destination() active_program_->destination
#define destination_address() active_program_->destination_address
#define destination_address() address_[active_program_->source_dest & 0x0f]
case int(MicroOp::Action::PerformOperation):
#define sub_overflow() ((result ^ destination) & (destination ^ source))
@ -1157,7 +1157,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
const auto mode = (decoded_instruction_.full >> 3) & 7; \
uint32_t start_address; \
if(mode <= 4) { \
start_address = destination_address()->full; \
start_address = destination_address().full; \
} else { \
start_address = effective_address_[1].full; \
} \
@ -1996,11 +1996,11 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
#define op_add(x, y) x += y
#define op_sub(x, y) x -= y
#define Adjust(op, quantity, effect) \
case int(op) | MicroOp::SourceMask: effect(source_address()->full, quantity); break; \
case int(op) | MicroOp::DestinationMask: effect(destination_address()->full, quantity); break; \
case int(op) | MicroOp::SourceMask: effect(source_address().full, quantity); break; \
case int(op) | MicroOp::DestinationMask: effect(destination_address().full, quantity); break; \
case int(op) | MicroOp::SourceMask | MicroOp::DestinationMask: \
effect(destination_address()->full, quantity); \
effect(source_address()->full, quantity); \
effect(destination_address().full, quantity); \
effect(source_address().full, quantity); \
break;
Adjust(MicroOp::Action::Decrement1, 1, op_sub);
@ -2056,16 +2056,16 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
break;
case int(MicroOp::Action::CalcD16An) | MicroOp::SourceMask:
effective_address_[0] = u_extend16(prefetch_queue_.halves.low.full) + source_address()->full;
effective_address_[0] = u_extend16(prefetch_queue_.halves.low.full) + source_address().full;
break;
case int(MicroOp::Action::CalcD16An) | MicroOp::DestinationMask:
effective_address_[1] = u_extend16(prefetch_queue_.halves.low.full) + destination_address()->full;
effective_address_[1] = u_extend16(prefetch_queue_.halves.low.full) + destination_address().full;
break;
case int(MicroOp::Action::CalcD16An) | MicroOp::SourceMask | MicroOp::DestinationMask:
effective_address_[0] = u_extend16(prefetch_queue_.halves.high.full) + source_address()->full;
effective_address_[1] = u_extend16(prefetch_queue_.halves.low.full) + destination_address()->full;
effective_address_[0] = u_extend16(prefetch_queue_.halves.high.full) + source_address().full;
effective_address_[1] = u_extend16(prefetch_queue_.halves.low.full) + destination_address().full;
break;
#define CalculateD8AnXn(data, source, target) {\
@ -2080,16 +2080,16 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
} \
}
case int(MicroOp::Action::CalcD8AnXn) | MicroOp::SourceMask: {
CalculateD8AnXn(prefetch_queue_.halves.low, source_address()->full, effective_address_[0]);
CalculateD8AnXn(prefetch_queue_.halves.low, source_address().full, effective_address_[0]);
} break;
case int(MicroOp::Action::CalcD8AnXn) | MicroOp::DestinationMask: {
CalculateD8AnXn(prefetch_queue_.halves.low, destination_address()->full, effective_address_[1]);
CalculateD8AnXn(prefetch_queue_.halves.low, destination_address().full, effective_address_[1]);
} break;
case int(MicroOp::Action::CalcD8AnXn) | MicroOp::SourceMask | MicroOp::DestinationMask: {
CalculateD8AnXn(prefetch_queue_.halves.high, source_address()->full, effective_address_[0]);
CalculateD8AnXn(prefetch_queue_.halves.low, destination_address()->full, effective_address_[1]);
CalculateD8AnXn(prefetch_queue_.halves.high, source_address().full, effective_address_[0]);
CalculateD8AnXn(prefetch_queue_.halves.low, destination_address().full, effective_address_[1]);
} break;
case int(MicroOp::Action::CalcD8PCXn) | MicroOp::SourceMask: {
@ -2140,16 +2140,16 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
break;
case int(MicroOp::Action::CopyToEffectiveAddress) | MicroOp::SourceMask:
effective_address_[0] = *active_program_->source_address;
effective_address_[0] = source_address();
break;
case int(MicroOp::Action::CopyToEffectiveAddress) | MicroOp::DestinationMask:
effective_address_[1] = *active_program_->destination_address;
effective_address_[1] = destination_address();
break;
case int(MicroOp::Action::CopyToEffectiveAddress) | MicroOp::SourceMask | MicroOp::DestinationMask:
effective_address_[0] = *active_program_->source_address;
effective_address_[1] = *active_program_->destination_address;
effective_address_[0] = source_address();
effective_address_[1] = destination_address();
break;
}

View File

@ -862,10 +862,6 @@ struct ProcessorStorageConstructor {
// Temporary storage for the Program fields.
ProcessorBase::Program program;
// if(instruction == 0x4879) {
// printf("");
// }
#define dec(n) decrement_action(is_long_word_access, is_byte_access, n)
#define inc(n) increment_action(is_long_word_access, is_byte_access, n)
@ -2478,7 +2474,7 @@ struct ProcessorStorageConstructor {
program.set_destination(storage_, An, data_register);
const int mode = combined_mode(ea_mode, ea_register);
program.source_address = &storage_.address_[ea_register];
program.set_source_address(storage_, ea_register);
program.source =
(mode == Ind) ?
&storage_.address_[ea_register] :

View File

@ -344,29 +344,44 @@ class ProcessorStorage {
non-pointer fields doesn't seem to be helpful immediately.)
*/
struct Program {
Operation operation;
uint8_t source_dest = 0;
bool requires_supervisor = false;
MicroOp *micro_operations = nullptr;
RegisterPair32 *source = nullptr;
RegisterPair32 *destination = nullptr;
RegisterPair32 *source_address = nullptr;
RegisterPair32 *destination_address = nullptr;
Operation operation;
bool requires_supervisor = false;
void set_source_address(ProcessorStorage &storage, int index) {
source_dest = uint8_t((source_dest & 0x0f) | (index << 4));
}
void set_destination_address(ProcessorStorage &storage, int index) {
source_dest = uint8_t((source_dest & 0xf0) | index);
}
void set_source(ProcessorStorage &storage, RegisterPair32 *target) {
source = target;
}
void set_destination(ProcessorStorage &storage, RegisterPair32 *target) {
destination = target;
}
void set_source(ProcessorStorage &storage, int mode, int reg) {
source_address = &storage.address_[reg];
set_source_address(storage, reg);
switch(mode) {
case 0: source = &storage.data_[reg]; break;
case 1: source = &storage.address_[reg]; break;
default: source = &storage.source_bus_data_[0]; break;
case 0: set_source(storage, &storage.data_[reg]); break;
case 1: set_source(storage, &storage.address_[reg]); break;
default: set_source(storage, &storage.source_bus_data_[0]); break;
}
}
void set_destination(ProcessorStorage &storage, int mode, int reg) {
destination_address = &storage.address_[reg];
set_destination_address(storage, reg);
switch(mode) {
case 0: destination = &storage.data_[reg]; break;
case 1: destination = &storage.address_[reg]; break;
default: destination = &storage.destination_bus_data_[0]; break;
case 0: set_destination(storage, &storage.data_[reg]); break;
case 1: set_destination(storage, &storage.address_[reg]); break;
default: set_destination(storage, &storage.destination_bus_data_[0]); break;
}
}
};