summaryrefslogtreecommitdiffhomepage
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
parentfe722b9304052b7a0a67fe01633c24ba5b4cdafa (diff)
Implemented optimize()
-rw-r--r--asm/chunk.h8
-rw-r--r--asm/segment.cpp31
-rw-r--r--test-asm.cpp14
3 files changed, 48 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
}
diff --git a/test-asm.cpp b/test-asm.cpp
index efdeab9..1d4634e 100644
--- a/test-asm.cpp
+++ b/test-asm.cpp
@@ -115,4 +115,18 @@ TEST_F(AsmTest, Intel64_multiple) {
0xE9, 0xFF, 0xFF, 0xFF, 0xFF, // jmp data1
0x01, 0x02, 0x03 // data
}));
+
+ segment.optimize();
+
+ ASSERT_EQ(segment.size(), 7);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>(
+ {
+ 0x90, // nop
+ 0xCD, 0x05, // int 5
+ 0xC3, // ret
+ // data1:
+ 0xC3, // ret
+ 0xEB, 0xFF, // jmp data1
+ 0x01, 0x02, 0x03 // data
+ }));
}