about summary refs log tree commit diff stats
path: root/033check_operands.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-09-27 21:12:48 -0700
committerKartik Agaram <vc@akkartik.com>2020-09-27 21:12:48 -0700
commit31e6ed17f84ff5b67803e534cde104b331dd495d (patch)
tree8ed6d9fe0eeea6d55489172c10d64909cddd7c05 /033check_operands.cc
parent7258083c6fe720b49c0a2b7e00af662dcb8a2d49 (diff)
downloadmu-31e6ed17f84ff5b67803e534cde104b331dd495d.tar.gz
6885 - starting on floating-point instructions
I spent some time deciding on the instructions. x87 is a stack ISA, so
not a good fit for the rest of SubX. So we use SSE instead. They operate
on 32-bit floats, which seems like a good fit.

SSE has a bunch of instructions for operating on up to 4 floats at once.
We'll ignore all that and just focus on so-called scalar instructions.
Diffstat (limited to '033check_operands.cc')
-rw-r--r--033check_operands.cc66
1 files changed, 64 insertions, 2 deletions
diff --git a/033check_operands.cc b/033check_operands.cc
index f46176c7..3e1f12d1 100644
--- a/033check_operands.cc
+++ b/033check_operands.cc
@@ -610,8 +610,23 @@ void check_operands_0f(const line& inst) {
   check_operands_0f(inst, op);
 }
 
-void check_operands_f3(const line& /*unused*/) {
-  raise << "no supported opcodes starting with f3\n" << end();
+void check_operands_f3(const line& inst) {
+  assert(inst.words.at(0).data == "f3");
+  if (SIZE(inst.words) == 1) {
+    raise << "opcode 'f3' requires a second opcode\n" << end();
+    return;
+  }
+  word op = preprocess_op(inst.words.at(1));
+  if (op.data == "0f") {
+    word op2 = preprocess_op(inst.words.at(2));
+    check_operands_f3_0f(inst, op2);
+    return;
+  }
+  if (!contains_key(Name_f3, op.data)) {
+    raise << "unknown 2-byte opcode 'f3 " << op.data << "'\n" << end();
+    return;
+  }
+  check_operands_f3(inst, op);
 }
 
 void test_check_missing_disp32_operand() {
@@ -666,6 +681,15 @@ put_new(Permitted_operands_0f, "9d", 0x01);
 put_new(Permitted_operands_0f, "9e", 0x01);
 put_new(Permitted_operands_0f, "9f", 0x01);
 
+:(before "End Globals")
+map</*op*/string, /*bitvector*/uint8_t> Permitted_operands_f3;
+map</*op*/string, /*bitvector*/uint8_t> Permitted_operands_f3_0f;
+:(before "End Init Permitted Operands")
+//// Class M: using ModR/M byte
+//  imm32 imm8  disp32 |disp16  disp8 subop modrm
+//  0     0     0      |0       0     0     1
+put_new(Permitted_operands_f3_0f, "2a", 0x01);
+
 :(code)
 void check_operands_0f(const line& inst, const word& op) {
   uint8_t expected_bitvector = get(Permitted_operands_0f, op.data);
@@ -678,6 +702,28 @@ void check_operands_0f(const line& inst, const word& op) {
   }
 }
 
+void check_operands_f3(const line& inst, const word& op) {
+  uint8_t expected_bitvector = get(Permitted_operands_f3, op.data);
+  if (HAS(expected_bitvector, MODRM)) {
+    check_operands_modrm(inst, op);
+    compare_bitvector_modrm(inst, expected_bitvector, maybe_name_f3(op));
+  }
+  else {
+    compare_bitvector(inst, CLEAR(expected_bitvector, MODRM), maybe_name_f3(op));
+  }
+}
+
+void check_operands_f3_0f(const line& inst, const word& op) {
+  uint8_t expected_bitvector = get(Permitted_operands_f3_0f, op.data);
+  if (HAS(expected_bitvector, MODRM)) {
+    check_operands_modrm(inst, op);
+    compare_bitvector_modrm(inst, expected_bitvector, maybe_name_f3_0f(op));
+  }
+  else {
+    compare_bitvector(inst, CLEAR(expected_bitvector, MODRM), maybe_name_f3_0f(op));
+  }
+}
+
 string maybe_name_0f(const word& op) {
   if (!is_hex_byte(op)) return "";
   if (!contains_key(Name_0f, op.data)) return "";
@@ -686,6 +732,22 @@ string maybe_name_0f(const word& op) {
   return " ("+s.substr(0, s.find(" ("))+')';
 }
 
+string maybe_name_f3(const word& op) {
+  if (!is_hex_byte(op)) return "";
+  if (!contains_key(Name_f3, op.data)) return "";
+  // strip stuff in parens from the name
+  const string& s = get(Name_f3, op.data);
+  return " ("+s.substr(0, s.find(" ("))+')';
+}
+
+string maybe_name_f3_0f(const word& op) {
+  if (!is_hex_byte(op)) return "";
+  if (!contains_key(Name_f3_0f, op.data)) return "";
+  // strip stuff in parens from the name
+  const string& s = get(Name_f3_0f, op.data);
+  return " ("+s.substr(0, s.find(" ("))+')';
+}
+
 string tolower(const char* s) {
   ostringstream out;
   for (/*nada*/;  *s;  ++s)