diff --git a/link.cpp b/link.cpp index 2cd67d3..0783034 100644 --- a/link.cpp +++ b/link.cpp @@ -8,13 +8,18 @@ #include #include #include +#include +#include #include #include #include +#include +#include +#include #include "obj816.h" - #include "expression.h" +#include "expression.h" @@ -23,6 +28,7 @@ struct section { std::string name; uint8_t flags = 0; uint32_t org = 0; + uint32_t size = 0; unsigned number = -1; std::vector data; @@ -37,6 +43,111 @@ struct symbol { int section = -1; }; +template +uint8_t read_8(T &iter) { + uint8_t tmp = *iter; + ++iter; + return tmp; +} + +template +uint16_t read_16(T &iter) { + uint16_t tmp = 0; + + tmp |= *iter << 0; + ++iter; + tmp |= *iter << 8; + ++iter; + return tmp; +} + +template +uint32_t read_32(T &iter) { + uint32_t tmp = 0; + + tmp |= *iter << 0; + ++iter; + tmp |= *iter << 8; + ++iter; + tmp |= *iter << 16; + ++iter; + tmp |= *iter << 24; + ++iter; + + + return tmp; +} + +template +std::string read_cstring(T &iter) { + std::string s; + for(;;) { + uint8_t c = *iter; + ++iter; + if (!c) break; + s.push_back(c); + } + return s; +} + + +template +std::string read_pstring(T &iter) { + std::string s; + unsigned size = *iter; + ++iter; + s.reserve(size); + while (size--) { + uint8_t c = *iter; + ++iter; + s.push_back(c); + } + return s; +} + + +std::vector
read_sections(const std::vector §ion_data) { + + std::vector
sections; + auto iter = section_data.begin(); + while (iter != section_data.end()) { + + section s; + + s.number = read_8(iter); + s.flags = read_8(iter); + s.size = read_32(iter); + s.org = read_32(iter); + + if (!(s.flags & SEC_NONAME)) s.name = read_cstring(iter); + + sections.emplace_back(std::move(s)); + } + return sections; +} + + +std::vector read_symbols(const std::vector &symbol_data) { + + std::vector symbols; + + auto iter = symbol_data.begin(); + while (iter != symbol_data.end()) { + symbol s; + s.type = read_8(iter); + s.flags = read_8(iter); + s.section = read_8(iter); + s.offset = s.type == S_UND ? 0 : read_32(iter); + s.name = read_cstring(iter); + + + symbols.emplace_back(std::move(s)); + } + + return symbols; +} + + std::unordered_map section_map; std::vector
sections; @@ -65,18 +176,18 @@ void simplify() { if (t.tag == OP_SYM) { const auto &ss = symbols[t.section]; - if (ss.type == S_UND) e.undefined = true; - else { - switch(ss.flags & 0x0f) { - case SF_REL: - t = expr{OP_LOC, ss.offset, ss.section}; - delta = true; - break; - case SF_ABS: - t = expr{OP_VAL, ss.offset}; - delta = true; - break; - } + switch(ss.type & 0x0f) { + case S_UND: + e.undefined = true; + break; + case S_REL: + t = expr{OP_LOC, ss.offset, (uint32_t)ss.section}; + delta = true; + break; + case S_ABS: + t = expr{OP_VAL, (uint32_t)ss.offset}; + delta = true; + break; } } } @@ -87,6 +198,7 @@ void simplify() { } + /* * read and process all sections... * if section > 5, remap based on name. @@ -97,22 +209,22 @@ void one_module(const std::vector &data, const std::vector &se std::array remap_section; - int current_section = CODE; - section *section_ptr = §ions[current_section]; + int current_section = SECT_CODE; + std::vector *data_ptr = §ions[current_section].data; std::fill(remap_section.begin(), remap_section.end(), -1); - remap_section[PAGE0] = PAGE0; - remap_section[CODE] = CODE; - remap_section[KDATA] = KDATA; - remap_section[DATA] = DATA; - remap_section[UDATA] = UDATA; + remap_section[SECT_PAGE0] = SECT_PAGE0; + remap_section[SECT_CODE] = SECT_CODE; + remap_section[SECT_KDATA] = SECT_KDATA; + remap_section[SECT_DATA] = SECT_DATA; + remap_section[SECT_UDATA] = SECT_UDATA; std::vector
local_sections = read_sections(section_data); std::vector local_symbols = read_symbols(symbol_data); // convert local sections to global for (auto &s : local_sections) { - if (s.number <= UDATA) continue; + if (s.number <= SECT_UDATA) continue; auto iter = section_map.find(s.name); if (iter == section_map.end()) { @@ -120,9 +232,9 @@ void one_module(const std::vector &data, const std::vector &se remap_section[s.number] = virtual_section; s.number = virtual_section; sections.emplace_back(s); - symbol_map.insert(s.name, virtual_section); + symbol_map.emplace(s.name, virtual_section); } else { - const auto &&s = sections[iter->second]; + const auto &ss = sections[iter->second]; assert(ss.flags == s.flags); // check org???? remap_section[s.number] = iter->second; s.number = iter->second; @@ -135,8 +247,8 @@ void one_module(const std::vector &data, const std::vector &se auto iter = symbol_map.find(s.name); if (iter == symbol_map.end()) { s.section = symbols.size(); - symbol_map.insert(s.name, s.section); - undefined_symbols.insert(s.name); + symbol_map.emplace(s.name, s.section); + undefined_symbols.emplace(s.name); } else { // already exists... @@ -147,7 +259,7 @@ void one_module(const std::vector &data, const std::vector &se } // remap and fudge the offset. - if (s.type & 0x0f == S_REL) { + if ((s.type & 0x0f) == S_REL) { int virtual_section = remap_section[s.section]; assert(virtual_section != -1); s.section = virtual_section; @@ -163,7 +275,7 @@ void one_module(const std::vector &data, const std::vector &se if (iter == symbol_map.end()) { unsigned tmp = symbols.size(); - symbol_map.insert(s.name, tmp); + symbol_map.emplace(s.name, tmp); symbols.emplace_back(s); } else { auto &ss = symbols[iter->second]; @@ -175,7 +287,7 @@ void one_module(const std::vector &data, const std::vector &se } else { // ok if symbols are identical.. - assert(ss.type == ss.type && ss.flags == s.flags && ss.section == s.section && && ss.offset == s.offset); + assert(ss.type == ss.type && ss.flags == s.flags && ss.section == s.section && ss.offset == s.offset); } } @@ -186,12 +298,12 @@ void one_module(const std::vector &data, const std::vector &se auto iter = data.begin(); for(;;) { - uint8_t *op = read_8(iter); + uint8_t op = read_8(iter); if (op == REC_END) return; ++iter; if (op < 0xf0) { - section->data.append(iter, iter + op); + data_ptr->insert(data_ptr->end(), iter, iter + op); iter += op; continue; } @@ -199,7 +311,7 @@ void one_module(const std::vector &data, const std::vector &se switch(op) { case REC_SPACE: { uint16_t count = read_16(iter); - section->data.append(count, 0); + data_ptr->insert(data_ptr->end(), count, 0); break; } @@ -209,7 +321,7 @@ void one_module(const std::vector &data, const std::vector &se current_section = remap_section[s]; assert(current_section > 0 && current_section < sections.size()); - section_ptr = §ions[current_section]; + data_ptr = §ions[current_section].data; break; } @@ -218,15 +330,16 @@ void one_module(const std::vector &data, const std::vector &se break; } - case REC_RELEXPR: + case REC_RELEXP: case REC_EXPR: { expression e; - e.relative = op == REC_RELEXPR; + e.relative = op == REC_RELEXP; - e.offset = section_ptr->data.size(); + e.offset = data_ptr->size(); e.size = read_8(iter); - section_ptr->data.append(e.size, 0); + + data_ptr->insert(data_ptr->end(), e.size, 0); /**/ for(;;) { @@ -236,40 +349,40 @@ void one_module(const std::vector &data, const std::vector &se switch(op) { case OP_VAL: { uint32_t offset = read_32(iter); - e.stack.emplace_back(op, value); + e.stack.emplace_back(op, offset); break; } case OP_SYM: { uint16_t symbol = read_16(iter); assert(symbol < local_symbols.size()); auto &s = local_symbols[symbol]; - if (s.type == S_UND) { - // S_UND indicates it's still undefined globally. - e.stack.emplace_back(OP_SYM, 0, s.section); /* section is actually a symbol number */ - e.undefined = true; - } else { - switch (s.flags & 0x0f) { - case SF_REL: - e.stack.emplace_back(OP_REL, s.offset, s.section); - break; - case SF_ABS: - e.stack.emplace_back(OP_VAL, s.offset); - break; - default: - assert(!"unsupported symbol flags."); - } + switch (s.type & 0x0f) { + case S_UND: + // S_UND indicates it's still undefined globally. + e.stack.emplace_back(OP_SYM, 0, s.section); /* section is actually a symbol number */ + e.undefined = true; + break; + case S_REL: + e.stack.emplace_back(OP_LOC, s.offset, s.section); + break; + + case S_ABS: + e.stack.emplace_back(OP_VAL, s.offset); + break; + + default: + assert(!"unsupported symbol flags."); } break; } case OP_LOC: { uint8_t section = read_8(iter); uint32_t offset = read_32(iter); - int real_section = remap[section]; + int real_section = remap_section[section]; assert(real_section >= 0); e.stack.emplace_back(op, offset, real_section); break; } - case O // operations.. //unary case OP_NOT: @@ -315,7 +428,71 @@ void one_module(const std::vector &data, const std::vector &se +void init() { + sections.resize(5); + + sections[SECT_PAGE0].number = SECT_PAGE0; + sections[SECT_PAGE0].flags = SEC_DATA | SEC_NONAME | SEC_DIRECT | SEC_REF_ONLY; + sections[SECT_PAGE0].name = "page0"; + + sections[SECT_CODE].number = SECT_CODE; + sections[SECT_CODE].flags = SEC_NONAME; + sections[SECT_CODE].name = "code"; + + sections[SECT_KDATA].number = SECT_KDATA; + sections[SECT_KDATA].flags = SEC_DATA | SEC_NONAME; + sections[SECT_KDATA].name = "kdata"; + + sections[SECT_DATA].number = SECT_DATA; + sections[SECT_DATA].flags = SEC_DATA | SEC_NONAME; + sections[SECT_DATA].name = "data"; + + sections[SECT_UDATA].number = SECT_UDATA; + sections[SECT_UDATA].flags = SEC_DATA | SEC_NONAME | SEC_REF_ONLY; + sections[SECT_UDATA].name = "udata"; + + /* + * For each section, [the linker] creates three symbols, + * _ROM_BEG_secname, _BEG_secname and _END_secname, which + * correspond to the rom location and the execution beginning + * and end of the section. These will be used more in the next + * two sections of code. + */ + + // n.b - only for pre-defined sections [?], skip the _ROM_BEG_* symbols... + + static std::string names[] = { + "_BEG_PAGE0", "_END_PAGE0", + "_BEG_CODE", "_END_CODE", + "_BEG_KDATA", "_END_KDATA" + "_BEG_DATA", "_END_DATA" + "_BEG_UDATA", "_END_UDATA" + }; + + for (int i = 0; i < 5; ++i) { + + // begin is 0. + symbol s; + s.name = names[i * 2]; + s.section = i; + s.type = S_REL; + s.flags = SF_DEF | SF_GBL; + symbol_map.emplace(s.name, i * 2); + symbols.emplace_back(s); + + // end is undefined... + s.name = names[i * 2 + 1]; + s.section = i * 2 + 1; // symbol number. + s.type = S_UND; + s.flags = 0; + + symbol_map.emplace(s.name, i * 2 + 1); + symbols.emplace_back(s); + + } + +} @@ -362,9 +539,3 @@ int main(int argc, char **argv) { } - - -struct section { - std::vector data; - uint32_t offset; -} \ No newline at end of file