about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-09-29 12:06:28 -0700
committerKartik Agaram <vc@akkartik.com>2018-09-29 17:44:50 -0700
commitef79039287b7a76f4fcb0628a6295582d8caf768 (patch)
tree15cccf34d0a8a451c95e16bb8ae05e2e389d4fd1 /subx
parent8fb01417031f2c6eaa8af505112ed1bb1a51ea21 (diff)
downloadmu-ef79039287b7a76f4fcb0628a6295582d8caf768.tar.gz
4616 - fix subx/examples/ex7
It was broken since I added support for global variables, back on Sep 1.

One other subtle thing I've improved is the name `looks_like_hex_int`.
We can now distinguish in the pack-operands transform between ignoring
'foo' because it doesn't look like a number, and immediately flagging '0xfoo'
as an error because it *should* be a number.
Diffstat (limited to 'subx')
-rw-r--r--subx/030---operands.cc28
-rw-r--r--subx/032check_operand_bounds.cc2
-rw-r--r--subx/035labels.cc31
-rw-r--r--subx/036global_variables.cc2
-rwxr-xr-xsubx/examples/ex7bin313 -> 313 bytes
5 files changed, 51 insertions, 12 deletions
diff --git a/subx/030---operands.cc b/subx/030---operands.cc
index f4602581..a9c85778 100644
--- a/subx/030---operands.cc
+++ b/subx/030---operands.cc
@@ -247,9 +247,10 @@ void add_imm_bytes(const line& in, line& out) {
 
 void emit_hex_bytes(line& out, const word& w, int num) {
   assert(num <= 4);
-  if (num == 1 || !is_hex_int(w.data)) {
-    out.words.push_back(w);
-    if (is_hex_int(w.data))
+  bool is_number = looks_like_hex_int(w.data);
+  if (num == 1 || !is_number) {
+    out.words.push_back(w);  // preserve existing metadata
+    if (is_number)
       out.words.back().data = hex_byte_to_string(parse_int(w.data));
     return;
   }
@@ -354,13 +355,22 @@ b9 0x080490a7/imm32  # copy to ECX
 # instruction                     effective address                                                   operand     displacement    immediate
 # op          subop               mod             rm32          base        index         scale       r32
 # 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
-  bb                                                                                                                              foo/imm32         # copy foo to EBX
+  bb                                                                                                                              foo/imm32         # copy to EBX
 +transform: packing instruction 'bb foo/imm32'
 # no change (we're just not printing metadata to the trace)
 +transform: instruction after packing: 'bb foo'
 $error: 0
 :(scenarios run)
 
+:(scenario pack_flags_bad_hex)
+% Hide_errors = true;
+== 0x1
+# instruction                     effective address                                                   operand     displacement    immediate
+# op          subop               mod             rm32          base        index         scale       r32
+# 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+  bb                                                                                                                              0xfoo/imm32       # copy to EBX
++error: not a number: 0xfoo
+
 //:: helpers
 
 :(code)
@@ -424,12 +434,12 @@ word metadata(const line& inst, const string& m) {
   assert(false);
 }
 
-bool is_hex_int(const string& s) {
+bool looks_like_hex_int(const string& s) {
   if (s.empty()) return false;
-  size_t pos = 0;
-  if (s.at(0) == '-' || s.at(0) == '+') pos++;
-  if (s.substr(pos, pos+2) == "0x") pos += 2;
-  return s.find_first_not_of("0123456789abcdefABCDEF", pos) == string::npos;
+  if (s.at(0) == '-' || s.at(0) == '+') return true;
+  if (isdigit(s.at(0))) return true;  // includes '0x' prefix
+  // End looks_like_hex_int(s) Detectors
+  return false;
 }
 
 :(code)
diff --git a/subx/032check_operand_bounds.cc b/subx/032check_operand_bounds.cc
index 69daeb46..966913e9 100644
--- a/subx/032check_operand_bounds.cc
+++ b/subx/032check_operand_bounds.cc
@@ -39,7 +39,7 @@ void check_operand_bounds(const segment& code) {
 void check_operand_bounds(const word& w) {
   for (map<string, uint32_t>::iterator p = Operand_bound.begin();  p != Operand_bound.end();  ++p) {
     if (!has_operand_metadata(w, p->first)) continue;
-    if (!is_hex_int(w.data)) continue;  // later transforms are on their own to do their own bounds checking
+    if (!looks_like_hex_int(w.data)) continue;  // later transforms are on their own to do their own bounds checking
     int32_t x = parse_int(w.data);
     if (x >= 0) {
       if (static_cast<uint32_t>(x) >= p->second)
diff --git a/subx/035labels.cc b/subx/035labels.cc
index 96668075..ddaeabad 100644
--- a/subx/035labels.cc
+++ b/subx/035labels.cc
@@ -18,6 +18,34 @@
 //: be a single character long. 'a' is not a hex number, it's a variable.
 //: Later layers may add more conventions partitioning the space of names. But
 //: the above rules will remain inviolate.
+
+:(before "End looks_like_hex_int(s) Detectors")
+if (SIZE(s) == 2) return true;
+
+:(scenarios transform)
+:(scenario pack_immediate_ignores_single_byte_nondigit_operand)
+== 0x1
+b9/copy a/imm32  # copy to ECX
++transform: packing instruction 'b9/copy a/imm32'
+# no change (we're just not printing metadata to the trace)
++transform: instruction after packing: 'b9 a'
+
+:(scenario pack_immediate_ignores_3_hex_digit_operand)
+== 0x1
+b9/copy aaa/imm32  # copy to ECX
++transform: packing instruction 'b9/copy aaa/imm32'
+# no change (we're just not printing metadata to the trace)
++transform: instruction after packing: 'b9 aaa'
+
+:(scenario pack_immediate_ignores_non_hex_operand)
+== 0x1
+b9/copy xxx/imm32  # copy to ECX
++transform: packing instruction 'b9/copy xxx/imm32'
+# no change (we're just not printing metadata to the trace)
++transform: instruction after packing: 'b9 xx'
+
+//: a helper we'll find handy later
+:(code)
 void check_valid_name(const string& s) {
   if (s.empty()) {
     raise << "empty name!\n" << end();
@@ -35,7 +63,8 @@ void check_valid_name(const string& s) {
     raise << "'" << s << "' is two characters long which can look like raw hex bytes at a glance; use a different name\n" << end();
 }
 
-:(scenarios transform)
+//: Now that that's done, let's start using names as labels.
+
 :(scenario map_label)
 == 0x1
           # instruction                     effective address                                                   operand     displacement    immediate
diff --git a/subx/036global_variables.cc b/subx/036global_variables.cc
index c565014f..f278ee29 100644
--- a/subx/036global_variables.cc
+++ b/subx/036global_variables.cc
@@ -4,7 +4,7 @@
 //: However, they can only be used in imm32 and not disp32 operands. And they
 //: can't be used with jump and call instructions.
 //:
-//: This layer much the same structure as rewriting labels.
+//: This layer has much the same structure as rewriting labels.
 
 :(scenario global_variable)
 == code
diff --git a/subx/examples/ex7 b/subx/examples/ex7
index 39f6f98d..d756271e 100755
--- a/subx/examples/ex7
+++ b/subx/examples/ex7
Binary files differ