about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--subx/023check_operand_sizes.cc2
-rw-r--r--subx/024pack_instructions.cc25
2 files changed, 26 insertions, 1 deletions
diff --git a/subx/023check_operand_sizes.cc b/subx/023check_operand_sizes.cc
index 158b1465..048cc28a 100644
--- a/subx/023check_operand_sizes.cc
+++ b/subx/023check_operand_sizes.cc
@@ -57,7 +57,7 @@ int32_t parse_int(const string& s) {
   istringstream in(s);
   int32_t result = 0;
   in >> std::hex >> result;
-  if (!in) {
+  if (!in || !in.eof()) {
     raise << "not a number: " << s << '\n' << end();
     return 0;
   }
diff --git a/subx/024pack_instructions.cc b/subx/024pack_instructions.cc
index bbaa7369..62d47d22 100644
--- a/subx/024pack_instructions.cc
+++ b/subx/024pack_instructions.cc
@@ -145,6 +145,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 (!is_hex_int(w.data)) {
+    out.words.push_back(w);
+    return;
+  }
   uint32_t val = static_cast<uint32_t>(parse_int(w.data));
   for (int i = 0;  i < num;  ++i) {
     out.words.push_back(hex_byte_text(val & 0xff));
@@ -152,6 +156,14 @@ void emit_hex_bytes(line& out, const word& w, int num) {
   }
 }
 
+bool is_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;
+}
+
 word hex_byte_text(uint8_t val) {
   ostringstream out;
   out << HEXBYTE << NUM(val);
@@ -187,3 +199,16 @@ void transform(const string& text_bytes) {
 +translate: packing instruction 'bb 0x2a/imm32'
 +translate: instruction after packing: 'bb 2a 00 00 00'
 +run: copy imm32 0x0000002a to EBX
+
+:(scenarios transform)
+:(scenario pack_silently_ignores_non_hex)
+== 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                                                                                                                      foo/imm32         # copy foo to EBX
++translate: packing instruction 'bb foo/imm32'
+# no change (we're just not printing metadata to the trace)
++translate: instruction after packing: 'bb foo'
+$error: 0
+:(scenarios run)