From 637df6ee3356a7fc111956430ab7e8524037aac1 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sun, 15 Dec 2019 13:04:45 -0500 Subject: [PATCH] ORG and LKV 1 support (untested) --- link.cpp | 21 ++++++++++++++++++--- omf.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/link.cpp b/link.cpp index cb2564a..d050194 100644 --- a/link.cpp +++ b/link.cpp @@ -31,6 +31,8 @@ #include "script.h" void save_omf(const std::string &path, std::vector &segments, bool compress, bool expressload); +void save_bin(const std::string &path, omf::segment &segment, uint32_t org); + int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type, std::error_code &ec); void set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type); @@ -594,8 +596,14 @@ void finish(void) { std::string path = save_file; if (path.empty()) path = "gs.out"; + + try { - save_omf(path, segments, compress, express); + if (lkv == 0) + save_bin(path, segments.back(), org); + else + save_omf(path, segments, compress, express); + set_file_type(path, ftype, atype); } catch (std::exception &ex) { errx(EX_OSERR, "%s: %s", path.c_str(), ex.what()); @@ -743,6 +751,12 @@ void evaluate(label_t label, opcode_t opcode, const char *cursor) { case OP_ADR: atype = number_operand(cursor, local_symbol_table); break; + + case OP_ORG: + org = number_operand(cursor, local_symbol_table); + atype = org; + break; + case OP_KND: { uint32_t kind = number_operand(cursor, local_symbol_table); if (!segments.empty()) @@ -773,8 +787,8 @@ void evaluate(label_t label, opcode_t opcode, const char *cursor) { uint32_t value = number_operand(cursor, local_symbol_table); switch (value) { - case 0: throw std::runtime_error("binary linker not supported"); case 3: throw std::runtime_error("object file linker not supported"); + case 0: case 1: case 2: lkv = value; @@ -841,7 +855,8 @@ void evaluate(label_t label, opcode_t opcode, const char *cursor) { seg.loadname = base; // seg.kind = kind; } - if (lkv == 1) { + + if (lkv == 0 || lkv == 1) { finish(); // reset. could have another link afterwards. segments.clear(); diff --git a/omf.cpp b/omf.cpp index 65af576..8853e1e 100644 --- a/omf.cpp +++ b/omf.cpp @@ -351,6 +351,38 @@ uint32_t add_relocs(std::vector &data, size_t data_offset, omf::segment return reloc_size; } +void save_bin(const std::string &path, omf::segment &segment, uint32_t org) { + + int fd; + fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + if (fd < 0) { + err(EX_CANTCREAT, "Unable to open %s", path.c_str()); + } + + auto &data = segment.data; + + for (auto &r : segment.relocs) { + + uint32_t value = r.value + org; + value >>= -(int8_t)r.shift; + + unsigned offset = r.offset; + unsigned size = r.size; + while (size--) { + data[offset++] = value & 0xff; + value >>= 8; + } + } + + auto ok = write(fd, data.data(), data.size()); + if (ok < 0) { + close(fd); + err(EX_OSERR, "write %s", path.c_str()); + } + close(fd); +} + + void save_omf(const std::string &path, std::vector &segments, bool compress, bool expressload) { // expressload doesn't support links to other files.