diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-09-27 21:12:48 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-09-27 21:12:48 -0700 |
commit | 31e6ed17f84ff5b67803e534cde104b331dd495d (patch) | |
tree | 8ed6d9fe0eeea6d55489172c10d64909cddd7c05 /033check_operands.cc | |
parent | 7258083c6fe720b49c0a2b7e00af662dcb8a2d49 (diff) | |
download | mu-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.cc | 66 |
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) |