about summary refs log tree commit diff stats
path: root/subx/036global_variables.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-11-19 21:16:56 -0800
committerKartik Agaram <vc@akkartik.com>2018-11-19 21:17:48 -0800
commita6061b9fd2e1476172ebe67376077bd09b516e41 (patch)
tree091e40b6b630f58f44f3ec4e2c2068585722fde8 /subx/036global_variables.cc
parente3c331d0a620b172966bd53a76387f1d837ec418 (diff)
downloadmu-a6061b9fd2e1476172ebe67376077bd09b516e41.tar.gz
4754 - allow data segment to refer to variables
Diffstat (limited to 'subx/036global_variables.cc')
-rw-r--r--subx/036global_variables.cc44
1 files changed, 42 insertions, 2 deletions
diff --git a/subx/036global_variables.cc b/subx/036global_variables.cc
index f1fdd963..afeb7427 100644
--- a/subx/036global_variables.cc
+++ b/subx/036global_variables.cc
@@ -38,7 +38,7 @@ void compute_addresses_for_global_variables(const segment& s, map<string, uint32
     for (int j = 0;  j < SIZE(inst.words);  ++j) {
       const word& curr = inst.words.at(j);
       if (*curr.data.rbegin() != ':') {
-        ++current_address;
+        current_address += size_of(curr);
       }
       else {
         string variable = drop_last(curr.data);
@@ -64,7 +64,12 @@ void drop_global_variables(program& p) {
 
 void replace_global_variables_with_addresses(program& p, const map<string, uint32_t>& address) {
   if (p.segments.empty()) return;
-  segment& code = p.segments.at(0);
+  replace_global_variables_in_code_segment(p.segments.at(0), address);
+  for (int i = /*skip code*/1;  i < SIZE(p.segments);  ++i)
+    replace_global_variables_in_data_segment(p.segments.at(i), address);
+}
+
+void replace_global_variables_in_code_segment(segment& code, const map<string, uint32_t>& address) {
   for (int i = 0;  i < SIZE(code.lines);  ++i) {
     line& inst = code.lines.at(i);
     line new_inst;
@@ -87,6 +92,26 @@ void replace_global_variables_with_addresses(program& p, const map<string, uint3
   }
 }
 
+void replace_global_variables_in_data_segment(segment& data, const map<string, uint32_t>& address) {
+  for (int i = 0;  i < SIZE(data.lines);  ++i) {
+    line& l = data.lines.at(i);
+    line new_l;
+    for (int j = 0;  j < SIZE(l.words);  ++j) {
+      const word& curr = l.words.at(j);
+      if (!contains_key(address, curr.data)) {
+        if (!looks_like_hex_int(curr.data))
+          raise << "missing reference to global '" << curr.data << "'\n" << end();
+        new_l.words.push_back(curr);
+        continue;
+      }
+      trace(99, "transform") << curr.data << " maps to " << HEXWORD << get(address, curr.data) << end();
+      emit_hex_bytes(new_l, get(address, curr.data), 4);
+    }
+    l.words.swap(new_l.words);
+    trace(99, "transform") << "after transform: '" << data_to_string(l) << "'" << end();
+  }
+}
+
 bool valid_use_of_global_variable(const word& curr) {
   if (has_operand_metadata(curr, "imm32")) return true;
   // End Valid Uses Of Global Variable(curr)
@@ -148,6 +173,21 @@ x:
 # sub-optimal error message; should be
 #? +error: can't call to the data segment ('x')
 
+:(scenario global_variable_in_data_segment)
+== 0x1
+b9  x/imm32
+== 0x0a000000
+x:
+  y/imm32
+y:
+  00 00 00 00
+# check that we loaded 'x' with the address of 'y'
++load: 0x0a000000 -> 04
++load: 0x0a000001 -> 00
++load: 0x0a000002 -> 00
++load: 0x0a000003 -> 0a
+$error: 0
+
 :(scenario disp32_data_with_modrm)
 == code
 8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX x/disp32