From 827c4e172aaf70085e1b9ee4aa94f929402c34aa Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 24 Jul 2019 18:39:36 -0400 Subject: [PATCH] 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. --- .../Implementation/68000Implementation.hpp | 38 +++++++++--------- .../68000/Implementation/68000Storage.cpp | 6 +-- .../68000/Implementation/68000Storage.hpp | 39 +++++++++++++------ 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 4dd1f0adb..4f323094b 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -365,9 +365,9 @@ template 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 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 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 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 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 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; } diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index 60bd6d61c..259aed5ff 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -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] : diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 14d27a035..20c1b9d39 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -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; } } };