diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-09-01 23:03:50 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-09-01 23:03:50 -0700 |
commit | a6517ed821ff39fa56eb3b975799d22497d78a48 (patch) | |
tree | b934f09748be6c9dce80d4caf926d0f8dd2c9916 /subx/035labels.cc | |
parent | f39c01128dfc6e46828cbab992d4b9e0ba1cb1e5 (diff) | |
download | mu-a6517ed821ff39fa56eb3b975799d22497d78a48.tar.gz |
4535 - support for global variable names
Diffstat (limited to 'subx/035labels.cc')
-rw-r--r-- | subx/035labels.cc | 50 |
1 files changed, 18 insertions, 32 deletions
diff --git a/subx/035labels.cc b/subx/035labels.cc index 659e4391..8c3ce1dd 100644 --- a/subx/035labels.cc +++ b/subx/035labels.cc @@ -1,5 +1,5 @@ //: Labels are defined by ending names with a ':'. This layer will compute -//: addresses for labels, and compute the offset for instructions using them. +//: displacements for labels, and compute the offset for instructions using them. //: //: We won't check this, but our convention will be that jump targets will //: start with a '$', while functions will not. Function names will never be @@ -52,16 +52,15 @@ void rewrite_labels(program& p) { trace(99, "transform") << "-- rewrite labels" << end(); if (p.segments.empty()) return; segment& code = p.segments.at(0); - // Rewrite Labels(segment code) - map<string, int32_t> address; // values are unsigned, but we're going to do subtractions on them so they need to fit in 31 bits - compute_addresses_for_labels(code, address); + map<string, int32_t> byte_index; // values are unsigned, but we're going to do subtractions on them so they need to fit in 31 bits + compute_byte_indices_for_labels(code, byte_index); if (trace_contains_errors()) return; drop_labels(code); if (trace_contains_errors()) return; - replace_labels_with_addresses(code, address); + replace_labels_with_displacements(code, byte_index); } -void compute_addresses_for_labels(const segment& code, map<string, int32_t>& address) { +void compute_byte_indices_for_labels(const segment& code, map<string, int32_t>& byte_index) { int current_byte = 0; for (int i = 0; i < SIZE(code.lines); ++i) { const line& inst = code.lines.at(i); @@ -90,7 +89,7 @@ void compute_addresses_for_labels(const segment& code, map<string, int32_t>& add raise << "'" << to_string(inst) << "': label definition (':') not allowed in operand\n" << end(); if (j > 0) raise << "'" << to_string(inst) << "': labels can only be the first word in a line.\n" << end(); - put(address, label, current_byte); + put(byte_index, label, current_byte); trace(99, "transform") << "label '" << label << "' is at address " << (current_byte+code.start) << end(); // no modifying current_byte; label definitions won't be in the final binary } @@ -110,30 +109,30 @@ bool is_label(const word& w) { return *w.data.rbegin() == ':'; } -void replace_labels_with_addresses(segment& code, const map<string, int32_t>& address) { - int32_t byte_next_instruction_starts_at = 0; +void replace_labels_with_displacements(segment& code, const map<string, int32_t>& byte_index) { + int32_t byte_index_next_instruction_starts_at = 0; for (int i = 0; i < SIZE(code.lines); ++i) { line& inst = code.lines.at(i); - byte_next_instruction_starts_at += num_bytes(inst); + byte_index_next_instruction_starts_at += num_bytes(inst); line new_inst; for (int j = 0; j < SIZE(inst.words); ++j) { const word& curr = inst.words.at(j); - if (contains_key(address, curr.data)) { - int32_t offset = static_cast<int32_t>(get(address, curr.data)) - byte_next_instruction_starts_at; + if (contains_key(byte_index, curr.data)) { + int32_t displacement = static_cast<int32_t>(get(byte_index, curr.data)) - byte_index_next_instruction_starts_at; if (has_metadata(curr, "disp8") || has_metadata(curr, "imm8")) { - if (offset > 0xff || offset < -0x7f) - raise << "'" << to_string(inst) << "': label too far away for distance " << std::hex << offset << " to fit in 8 bits\n" << end(); + if (displacement > 0xff || displacement < -0x7f) + raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 8 bits\n" << end(); else - emit_hex_bytes(new_inst, offset, 1); + emit_hex_bytes(new_inst, displacement, 1); } else if (has_metadata(curr, "disp16")) { - if (offset > 0xffff || offset < -0x7fff) - raise << "'" << to_string(inst) << "': label too far away for distance " << std::hex << offset << " to fit in 16 bits\n" << end(); + if (displacement > 0xffff || displacement < -0x7fff) + raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 16 bits\n" << end(); else - emit_hex_bytes(new_inst, offset, 2); + emit_hex_bytes(new_inst, displacement, 2); } else if (has_metadata(curr, "disp32") || has_metadata(curr, "imm32")) { - emit_hex_bytes(new_inst, offset, 4); + emit_hex_bytes(new_inst, displacement, 4); } } else { @@ -145,19 +144,6 @@ void replace_labels_with_addresses(segment& code, const map<string, int32_t>& ad } } -// Assumes all bitfields are packed. -uint32_t num_bytes(const line& inst) { - uint32_t sum = 0; - for (int i = 0; i < SIZE(inst.words); ++i) { - const word& curr = inst.words.at(i); - if (has_metadata(curr, "disp32") || has_metadata(curr, "imm32")) // only multi-byte operands - sum += 4; - else - sum++; - } - return sum; -} - string data_to_string(const line& inst) { ostringstream out; for (int i = 0; i < SIZE(inst.words); ++i) { |