summaryrefslogtreecommitdiffhomepage
path: root/asm/segment.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-10-18 19:59:29 +0200
committerRoland Reichwein <mail@reichwein.it>2020-10-18 19:59:29 +0200
commit0cb5824977dbff51fa7b77c20279b6bd4cb49d78 (patch)
tree80af90f2bfda5a6e2c24e08a01b72a3a6b9bef13 /asm/segment.cpp
parentfe722b9304052b7a0a67fe01633c24ba5b4cdafa (diff)
Implemented optimize()
Diffstat (limited to 'asm/segment.cpp')
-rw-r--r--asm/segment.cpp31
1 files changed, 30 insertions, 1 deletions
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
}