diff options
Diffstat (limited to 'asm')
-rw-r--r-- | asm/chunk.h | 8 | ||||
-rw-r--r-- | asm/segment.cpp | 31 |
2 files changed, 34 insertions, 5 deletions
diff --git a/asm/chunk.h b/asm/chunk.h index 43cf54e..fb3f303 100644 --- a/asm/chunk.h +++ b/asm/chunk.h @@ -25,12 +25,12 @@ struct AddressFeature bool relativeAddressing{true}; std::vector<uint8_t> machine_code; - size_t addr_size; - size_t addr_offs; ///< offset inside code + size_t addr_size{0}; + size_t addr_offs{0}; ///< offset inside code std::vector<uint8_t> alternative_code; - size_t alternative_size; - size_t alternative_offs; ///< offset inside code + size_t alternative_size{0}; + size_t alternative_offs{0}; ///< offset inside code }; class Label: public Chunk diff --git a/asm/segment.cpp b/asm/segment.cpp index a4544f2..d3050bb 100644 --- a/asm/segment.cpp +++ b/asm/segment.cpp @@ -79,6 +79,35 @@ void Segment::insertAddresses() void Segment::optimize() { - // TODO + bool changed{false}; + + for (size_t i = 0; i < this->size(); i++) { + try { + AddressFeature& af { dynamic_cast<AddressFeature&>(*((*this)[i]))}; + + if (af.relativeAddressing == false) + throw std::runtime_error("Error: Absolute Addressing not supported."); + + if (!af.alternative_code.empty()) { + int64_t target_address = getAddressOfLabel(af.label); // throws if label not found + int64_t start_address = getAddressOfIndex(i); // throws if out of range + int64_t diff = target_address - start_address; + if (af.addr_size == 4 && af.alternative_size == 1 && diff >= -128 && diff <= 127) { + af.machine_code = af.alternative_code; + af.addr_size = af.alternative_size; + af.addr_offs = af.alternative_offs; + af.alternative_code.clear(); + af.alternative_size = 0; + af.alternative_offs = 0; + changed = true; + } + } + } catch (const std::bad_cast& ex) { + // ignore, expected for non-addressing chunks + } + } + + if (changed) + insertAddresses(); // renumber } |