aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--qtmips_machine/alu.cpp5
-rw-r--r--qtmips_machine/alu.h3
-rw-r--r--qtmips_machine/instruction.cpp208
-rw-r--r--qtmips_machine/instruction.h7
4 files changed, 170 insertions, 53 deletions
diff --git a/qtmips_machine/alu.cpp b/qtmips_machine/alu.cpp
index f8b919b..2d5783d 100644
--- a/qtmips_machine/alu.cpp
+++ b/qtmips_machine/alu.cpp
@@ -68,8 +68,3 @@ std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, std::u
throw QTMIPS_EXCEPTION(UnsupportedAluOperation, "Unknown ALU operation", QString::number(operation, 16));
}
}
-
-QString machine::alu_str(enum AluOp operation, std::uint32_t s, std::uint32_t t, std::uint8_t sa) {
- // TODO
- return QString("");
-}
diff --git a/qtmips_machine/alu.h b/qtmips_machine/alu.h
index 1f89acf..51cae28 100644
--- a/qtmips_machine/alu.h
+++ b/qtmips_machine/alu.h
@@ -46,9 +46,6 @@ enum AluOp : std::uint8_t {
// Returned value is commonly saved to rt/rd or any other way passed trough core
std::uint32_t alu_operate(enum AluOp operation, std::uint32_t s, std::uint32_t t, std::uint8_t sa, Registers *regs);
-// Returns string representation of ALU instruction (internally used by Instruction::to_str)
-QString alu_str(enum AluOp operation, std::uint32_t s, std::uint32_t t, std::uint8_t sa);
-
}
Q_DECLARE_METATYPE(machine::AluOp)
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;
+}
diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h
index fc8dbf5..6232d3e 100644
--- a/qtmips_machine/instruction.h
+++ b/qtmips_machine/instruction.h
@@ -6,8 +6,7 @@
namespace machine {
-class Instruction : public QObject {
- Q_OBJECT
+class Instruction {
public:
Instruction();
Instruction(std::uint32_t inst);
@@ -16,8 +15,6 @@ public:
Instruction(std::uint8_t opcode, std::uint32_t address); // Type J
Instruction(const Instruction&);
- QString to_str();
-
std::uint8_t opcode() const;
std::uint8_t rs() const;
std::uint8_t rt() const;
@@ -32,6 +29,8 @@ public:
bool operator!=(const Instruction &c) const;
Instruction &operator=(const Instruction &c);
+ QString to_str();
+
private:
std::uint32_t dt;
};