about summary refs log tree commit diff stats
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
parente3c331d0a620b172966bd53a76387f1d837ec418 (diff)
downloadmu-a6061b9fd2e1476172ebe67376077bd09b516e41.tar.gz
4754 - allow data segment to refer to variables
-rw-r--r--subx/034compute_segment_address.cc18
-rw-r--r--subx/035labels.cc6
-rw-r--r--subx/036global_variables.cc44
3 files changed, 55 insertions, 13 deletions
diff --git a/subx/034compute_segment_address.cc b/subx/034compute_segment_address.cc
index f6513114..b302e4d8 100644
--- a/subx/034compute_segment_address.cc
+++ b/subx/034compute_segment_address.cc
@@ -111,17 +111,19 @@ uint32_t size_of(const segment& s) {
 // 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_operand_metadata(curr, "disp32") || has_operand_metadata(curr, "imm32"))  // only multi-byte operands
-      sum += 4;
-    // End num_bytes(curr) Special-cases
-    else
-      sum++;
-  }
+  for (int i = 0;  i < SIZE(inst.words);  ++i)
+    sum += size_of(inst.words.at(i));
   return sum;
 }
 
+int size_of(const word& w) {
+  if (has_operand_metadata(w, "disp32") || has_operand_metadata(w, "imm32"))
+    return 4;
+  // End size_of(word w) Special-cases
+  else
+    return 1;
+}
+
 //: Dependencies:
 //: - We'd like to compute segment addresses before setting up global variables,
 //:   because computing addresses for global variables requires knowing where
diff --git a/subx/035labels.cc b/subx/035labels.cc
index 30a6082e..e07cede8 100644
--- a/subx/035labels.cc
+++ b/subx/035labels.cc
@@ -265,6 +265,6 @@ bar:
   00
 +transform: segment 1 begins at address 0x0a000079
 
-:(before "End num_bytes(curr) Special-cases")
-else if (is_label(curr))
-  ;  // don't count it
+:(before "End size_of(word w) Special-cases")
+else if (is_label(w))
+  return 0;
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