aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/instruction.cpp
diff options
context:
space:
mode:
authorKarel Kočí <cynerd@email.cz>2018-01-03 12:41:16 +0100
committerKarel Kočí <cynerd@email.cz>2018-01-03 12:41:16 +0100
commit76876d39ba4a9c842786304b8ccf0249fab2999c (patch)
tree05d580a18b6b74840613e2f2e6ae10f6ef074193 /qtmips_machine/instruction.cpp
parente9a4f6a805c25334e2014869f262ee946f698bbf (diff)
downloadqtmips-76876d39ba4a9c842786304b8ccf0249fab2999c.tar.gz
qtmips-76876d39ba4a9c842786304b8ccf0249fab2999c.tar.bz2
qtmips-76876d39ba4a9c842786304b8ccf0249fab2999c.zip
Initial implementation of reverse instruction conversion
This is rude implementation. We always print all fields. In future we should add flags to set what fields should be hidden on per instruction bases.
Diffstat (limited to 'qtmips_machine/instruction.cpp')
-rw-r--r--qtmips_machine/instruction.cpp208
1 files changed, 167 insertions, 41 deletions
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp
index a90fd5a..edb6305 100644
--- a/qtmips_machine/instruction.cpp
+++ b/qtmips_machine/instruction.cpp
@@ -2,41 +2,6 @@
#include "qtmipsexception.h"
using namespace machine;
-
-struct InstructionMap {
- const char *name;
-};
-
-#define IM_UNKNOWN {"UNKNOWN"}
-const struct InstructionMap instruction_map[] = {
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- {"ADDI"},
- {"ADDIU"},
- {"SLTI"},
- {"SLTIU"},
- {"ANDI"},
- {"ORI"},
- {"XORI"},
- {"LUI"},
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN,
- IM_UNKNOWN
-};
-
Instruction::Instruction() {
this->dt = 0;
}
@@ -73,12 +38,6 @@ Instruction::Instruction(const Instruction &i) {
this->dt = i.data();
}
-QString Instruction::to_str() {
- if (this->opcode() >= sizeof(instruction_map))
- return QString("UNKNOWN");
- return QString(instruction_map[this->opcode()].name);
-}
-
#define MASK(LEN,OFF) ((this->dt >> (OFF)) & ((1 << (LEN)) - 1))
std::uint8_t Instruction::opcode() const {
@@ -131,3 +90,170 @@ Instruction &Instruction::operator=(const Instruction &c) {
this->dt = c.data();
return *this;
}
+
+
+enum InstructionType {
+ IT_R,
+ IT_I,
+ IT_J
+};
+
+struct InstructionMap {
+ const char *name;
+ enum InstructionType type;
+};
+
+#define IM_UNKNOWN {"UNKNOWN", IT_R}
+// This table is indexed by opcode
+static const struct InstructionMap instruction_map[] = {
+ {"ALU", IT_R}, // Alu operations
+ {"REGIMM", IT_I}, // REGIMM (BLTZ, BGEZ)
+ {"J", IT_J},
+ {"JAL", IT_J},
+ {"BEQ", IT_I},
+ {"BNE", IT_I},
+ {"BLEZ", IT_I},
+ {"BGTZ", IT_I},
+ {"ADDI", IT_I},
+ {"ADDIU", IT_I},
+ {"SLTI", IT_I},
+ {"SLTIU", IT_I},
+ {"ANDI", IT_I},
+ {"ORI", IT_I},
+ {"XORI", IT_I},
+ {"LUI", IT_I},
+ IM_UNKNOWN, // 16
+ IM_UNKNOWN, // 17
+ IM_UNKNOWN, // 18
+ IM_UNKNOWN, // 19
+ IM_UNKNOWN, // 20
+ IM_UNKNOWN, // 21
+ IM_UNKNOWN, // 22
+ IM_UNKNOWN, // 23
+ IM_UNKNOWN, // 24
+ IM_UNKNOWN, // 25
+ IM_UNKNOWN, // 26
+ IM_UNKNOWN, // 27
+ IM_UNKNOWN, // 28
+ IM_UNKNOWN, // 29
+ IM_UNKNOWN, // 30
+ IM_UNKNOWN, // 31
+ {"LB", IT_I},
+ {"LH", IT_I},
+ {"LWL", IT_I},
+ {"LW", IT_I},
+ {"LBU", IT_I},
+ {"LHU", IT_I},
+ {"LWR", IT_I},
+ IM_UNKNOWN, // 39
+ {"SB", IT_I},
+ {"SH", IT_I},
+ {"SWL", IT_I},
+ {"SW", IT_I},
+ IM_UNKNOWN, // 44
+ IM_UNKNOWN, // 45
+ {"SWR", IT_I},
+ IM_UNKNOWN, // 47
+ IM_UNKNOWN, // 48
+ IM_UNKNOWN, // 49
+ IM_UNKNOWN, // 50
+ IM_UNKNOWN, // 51
+ IM_UNKNOWN, // 52
+ IM_UNKNOWN, // 53
+ IM_UNKNOWN, // 54
+ IM_UNKNOWN, // 55
+ IM_UNKNOWN, // 56
+ IM_UNKNOWN, // 57
+ IM_UNKNOWN, // 58
+ IM_UNKNOWN, // 59
+ IM_UNKNOWN, // 60
+ IM_UNKNOWN, // 61
+ IM_UNKNOWN, // 61
+ IM_UNKNOWN, // 62
+ IM_UNKNOWN // 63
+};
+#undef IM_UNKNOWN
+
+struct AluInstructionMap {
+ const char *name;
+};
+
+#define AIM_UNKNOWN {"UNKNOWN"}
+// This table is indexed by funct
+static const struct AluInstructionMap alu_instruction_map[] = {
+ {"SLL"},
+ AIM_UNKNOWN,
+ {"SRL"},
+ {"SRA"},
+ {"SLLV"},
+ AIM_UNKNOWN,
+ {"SRLV"},
+ {"SRAV"},
+ {"JR"},
+ {"JALR"},
+ {"MOVZ"},
+ {"MOVN"},
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ {"MFHU"},
+ {"MTHI"},
+ {"MFLO"},
+ {"MTLO"},
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ {"ADD"},
+ {"ADDU"},
+ {"SUB"},
+ {"SUBU"},
+ {"AND"},
+ {"OR"},
+ {"XOR"},
+ {"NOR"},
+ AIM_UNKNOWN,
+ AIM_UNKNOWN,
+ {"SLT"},
+ {"SLTU"}
+};
+#undef AIM_UNKNOWN
+
+QString Instruction::to_str() {
+ // TODO there are exception where some fields are zero and such so we should not print them in sych case
+ if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap)))
+ return QString("UNKNOWN");
+ const struct InstructionMap &im = instruction_map[opcode()];
+ QString res;
+ switch (im.type) {
+ case IT_I:
+ res += im.name;
+ res += " $" + QString::number(rs()) + ", $" + QString::number(rt()) + ", " + QString::number(immediate());
+ break;
+ case IT_J:
+ res += im.name;
+ // TODO we need to know instruction address to expand address section by it
+ res += " " + QString::number(address(), 16);
+ break;
+ case IT_R:
+ {
+ // Note that all R instructions we support has opcode == 0 and so they are processed by alu table
+ if (funct() >= (sizeof(alu_instruction_map) / sizeof(struct AluInstructionMap)))
+ return QString("UNKNOWN");
+ const struct AluInstructionMap &am = alu_instruction_map[funct()];
+ res += am.name;
+ res += " $" + QString::number(rs()) + ", $" + QString::number(rt()) + ", $" + QString::number(rd());
+ break;
+ }
+ }
+ return res;
+}