about summary refs log tree commit diff stats
path: root/subx/023check_operand_sizes.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-07-24 20:55:34 -0700
committerKartik Agaram <vc@akkartik.com>2018-07-24 20:55:34 -0700
commit1b35d4cd8bc9dce84fde4d0145d3058bca370350 (patch)
treea5a1696392bc65a20e20fd8fe50518b773a91790 /subx/023check_operand_sizes.cc
parentd1e2b0aa5b52ac63cbb92d1f1a70cb510ff970fb (diff)
downloadmu-1b35d4cd8bc9dce84fde4d0145d3058bca370350.tar.gz
4397 - temporarily revert syntax checks
I accidentally published commit 4387, which is broken; most example
files are untranslateable.

I spent a while trying to push on through, but packing operands
correctly into bytes has been surprisingly difficult. Fixing the repo
without further delay.
Diffstat (limited to 'subx/023check_operand_sizes.cc')
-rw-r--r--subx/023check_operand_sizes.cc61
1 files changed, 61 insertions, 0 deletions
diff --git a/subx/023check_operand_sizes.cc b/subx/023check_operand_sizes.cc
index 687ee41d..b6a96a1f 100644
--- a/subx/023check_operand_sizes.cc
+++ b/subx/023check_operand_sizes.cc
@@ -43,6 +43,17 @@ void check_operand_bounds(const word& w) {
         raise << "'" << w.original << "' too large to fit in bitfield " << p->first << '\n' << end();
 }
 
+int first_operand(const line& inst) {
+  if (inst.words.at(0).data == "0f") return 2;
+  if (inst.words.at(0).data == "f3") {
+    if (inst.words.at(1).data == "0f")
+      return 3;
+    else
+      return 2;
+  }
+  return 1;
+}
+
 uint32_t parse_int(const string& s) {
   istringstream in(s);
   uint32_t result = 0;
@@ -55,3 +66,53 @@ uint32_t parse_int(const string& s) {
   }
   return result;
 }
+
+void check_metadata_present(const line& inst, const string& type, uint8_t op) {
+  if (!has_metadata(inst, type, op))
+    raise << "'" << to_string(inst) << "' (" << get(name, op) << "): missing " << type << " operand\n" << end();
+}
+
+bool has_metadata(const line& inst, const string& m, uint8_t op) {
+  bool result = false;
+  for (int i = 0;  i < SIZE(inst.words);  ++i) {
+    if (!has_metadata(inst.words.at(i), m)) continue;
+    if (result) {
+      raise << "'" << to_string(inst) << "' has conflicting " << m << " operands\n" << end();
+      return false;
+    }
+    result = true;
+  }
+  return result;
+}
+
+bool has_metadata(const word& w, const string& m) {
+  bool result = false;
+  bool metadata_found = false;
+  for (int i = 0;  i < SIZE(w.metadata);  ++i) {
+    const string& curr = w.metadata.at(i);
+    if (!contains_key(Operand_bound, curr)) continue;  // ignore unrecognized metadata
+    if (metadata_found) {
+      raise << "'" << w.original << "' has conflicting operand types; it should have only one\n" << end();
+      return false;
+    }
+    metadata_found = true;
+    result = (curr == m);
+  }
+  return result;
+}
+
+word metadata(const line& inst, const string& m) {
+  for (int i = 0;  i < SIZE(inst.words);  ++i)
+    if (has_metadata(inst.words.at(i), m))
+      return inst.words.at(i);
+  assert(false);
+}
+
+string to_string(const line& inst) {
+  ostringstream out;
+  for (int i = 0;  i < SIZE(inst.words);  ++i) {
+    if (i > 0) out << ' ';
+    out << inst.words.at(i).original;
+  }
+  return out.str();
+}