mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 01:31:42 +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:
parent
c300bd17fa
commit
827c4e172a
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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] :
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user