aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/instruction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qtmips_machine/instruction.cpp')
-rw-r--r--qtmips_machine/instruction.cpp275
1 files changed, 146 insertions, 129 deletions
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp
index c4ca492..837b9b4 100644
--- a/qtmips_machine/instruction.cpp
+++ b/qtmips_machine/instruction.cpp
@@ -2,126 +2,36 @@
#include "qtmipsexception.h"
using namespace machine;
-Instruction::Instruction() {
- this->dt = 0;
-}
-
-Instruction::Instruction(std::uint32_t inst) {
- this->dt = inst;
-}
-
-Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint8_t rd, std::uint8_t shamt, std::uint8_t funct) {
- this->dt = 0;
- this->dt |= opcode << 26;
- this->dt |= rs << 21;
- this->dt |= rt << 16;
- this->dt |= rd << 11;
- this->dt |= shamt << 6;
- this->dt |= funct;
-}
-
-Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint16_t immediate) {
- this->dt = 0;
- this->dt |= opcode << 26;
- this->dt |= rs << 21;
- this->dt |= rt << 16;
- this->dt |= immediate;
-}
-
-Instruction::Instruction(std::uint8_t opcode, std::uint32_t address) {
- this->dt = 0;
- this->dt |= opcode << 26;
- this->dt |= address;
-}
-
-Instruction::Instruction(const Instruction &i) {
- this->dt = i.data();
-}
-
-#define MASK(LEN,OFF) ((this->dt >> (OFF)) & ((1 << (LEN)) - 1))
-
-std::uint8_t Instruction::opcode() const {
- return (std::uint8_t) MASK(6, 26);
-}
-
-std::uint8_t Instruction::rs() const {
- return (std::uint8_t) MASK(5, 21);
-}
-
-std::uint8_t Instruction::rt() const {
- return (std::uint8_t) MASK(5, 16);
-}
-
-std::uint8_t Instruction::rd() const {
- return (std::uint8_t) MASK(5, 11);
-}
-
-std::uint8_t Instruction::shamt() const {
- return (std::uint8_t) MASK(5, 6);
-
-}
-
-std::uint8_t Instruction::funct() const {
- return (std::uint8_t) MASK(6, 0);
-}
-
-std::uint16_t Instruction::immediate() const {
- return (std::uint16_t) MASK(16, 0);
-}
-
-std::uint32_t Instruction::address() const {
- return (std::uint32_t) MASK(26, 0);
-}
-
-std::uint32_t Instruction::data() const {
- return this->dt;
-}
-
-bool Instruction::operator==(const Instruction &c) const {
- return (this->data() == c.data());
-}
-
-bool Instruction::operator!=(const Instruction &c) const {
- return ! this->operator==(c);
-}
-
-Instruction &Instruction::operator=(const Instruction &c) {
- if (this != &c)
- this->dt = c.data();
- return *this;
-}
-
-
-enum InstructionType {
- IT_R,
- IT_I,
- IT_J
-};
struct InstructionMap {
const char *name;
- enum InstructionType type;
+ enum Instruction::Type type;
+ bool is_store;
};
-#define IM_UNKNOWN {"UNKNOWN", IT_R}
+#define IT_R Instruction::T_R
+#define IT_I Instruction::T_I
+#define IT_J Instruction::T_J
+
+#define IM_UNKNOWN {"UNKNOWN", Instruction::T_UNKNOWN, false}
// 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},
+ {"ALU", IT_R, false}, // Alu operations
+ {"REGIMM", IT_I, false}, // REGIMM (BLTZ, BGEZ)
+ {"J", IT_J, false},
+ {"JAL", IT_J, false},
+ {"BEQ", IT_I, false},
+ {"BNE", IT_I, false},
+ {"BLEZ", IT_I, false},
+ {"BGTZ", IT_I, false},
+ {"ADDI", IT_I, false},
+ {"ADDIU", IT_I, false},
+ {"SLTI", IT_I, false},
+ {"SLTIU", IT_I, false},
+ {"ANDI", IT_I, false},
+ {"ORI", IT_I, false},
+ {"XORI", IT_I, false},
+ {"LUI", IT_I, false},
IM_UNKNOWN, // 16
IM_UNKNOWN, // 17
IM_UNKNOWN, // 18
@@ -138,22 +48,23 @@ static const struct InstructionMap instruction_map[] = {
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},
+ {"LB", IT_I, false},
+ {"LH", IT_I, false},
+ {"LWL", IT_I, false},
+ {"LW", IT_I, false},
+ {"LBU", IT_I, false},
+ {"LHU", IT_I, false},
+ {"LWR", IT_I, false},
IM_UNKNOWN, // 39
- {"SB", IT_I},
- {"SH", IT_I},
- {"SWL", IT_I},
- {"SW", IT_I},
+ {"SB", IT_I, true},
+ {"SH", IT_I, true},
+ {"SWL", IT_I, true},
+ {"SW", IT_I, true},
IM_UNKNOWN, // 44
IM_UNKNOWN, // 45
- {"SWR", IT_I},
- IM_UNKNOWN, // 47
+ {"SWR", IT_I, true},
+ IM_UNKNOWN,
+ // 47
IM_UNKNOWN, // 48
IM_UNKNOWN, // 49
IM_UNKNOWN, // 50
@@ -228,6 +139,110 @@ static const struct AluInstructionMap alu_instruction_map[] = {
};
#undef AIM_UNKNOWN
+Instruction::Instruction() {
+ this->dt = 0;
+}
+
+Instruction::Instruction(std::uint32_t inst) {
+ this->dt = inst;
+}
+
+Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint8_t rd, std::uint8_t shamt, std::uint8_t funct) {
+ this->dt = 0;
+ this->dt |= opcode << 26;
+ this->dt |= rs << 21;
+ this->dt |= rt << 16;
+ this->dt |= rd << 11;
+ this->dt |= shamt << 6;
+ this->dt |= funct;
+}
+
+Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint16_t immediate) {
+ this->dt = 0;
+ this->dt |= opcode << 26;
+ this->dt |= rs << 21;
+ this->dt |= rt << 16;
+ this->dt |= immediate;
+}
+
+Instruction::Instruction(std::uint8_t opcode, std::uint32_t address) {
+ this->dt = 0;
+ this->dt |= opcode << 26;
+ this->dt |= address;
+}
+
+Instruction::Instruction(const Instruction &i) {
+ this->dt = i.data();
+}
+
+#define MASK(LEN,OFF) ((this->dt >> (OFF)) & ((1 << (LEN)) - 1))
+
+std::uint8_t Instruction::opcode() const {
+ return (std::uint8_t) MASK(6, 26);
+}
+
+std::uint8_t Instruction::rs() const {
+ return (std::uint8_t) MASK(5, 21);
+}
+
+std::uint8_t Instruction::rt() const {
+ return (std::uint8_t) MASK(5, 16);
+}
+
+std::uint8_t Instruction::rd() const {
+ return (std::uint8_t) MASK(5, 11);
+}
+
+std::uint8_t Instruction::shamt() const {
+ return (std::uint8_t) MASK(5, 6);
+
+}
+
+std::uint8_t Instruction::funct() const {
+ return (std::uint8_t) MASK(6, 0);
+}
+
+std::uint16_t Instruction::immediate() const {
+ return (std::uint16_t) MASK(16, 0);
+}
+
+std::uint32_t Instruction::address() const {
+ return (std::uint32_t) MASK(26, 0);
+}
+
+std::uint32_t Instruction::data() const {
+ return this->dt;
+}
+
+enum Instruction::Type Instruction::type() const {
+ if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap)))
+ return T_UNKNOWN;
+ const struct InstructionMap &im = instruction_map[opcode()];
+ return im.type;
+}
+
+bool Instruction::is_store() const {
+ if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap)))
+ return false;
+ const struct InstructionMap &im = instruction_map[opcode()];
+ return im.is_store;
+}
+
+bool Instruction::operator==(const Instruction &c) const {
+ return (this->data() == c.data());
+}
+
+bool Instruction::operator!=(const Instruction &c) const {
+ return ! this->operator==(c);
+}
+
+Instruction &Instruction::operator=(const Instruction &c) {
+ if (this != &c)
+ this->dt = c.data();
+ return *this;
+}
+
+
QString Instruction::to_str() const {
// TODO there are exception where some fields are zero and such so we should not print them in such case
if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap)))
@@ -237,16 +252,16 @@ QString Instruction::to_str() const {
const struct InstructionMap &im = instruction_map[opcode()];
QString res;
switch (im.type) {
- case IT_I:
+ case T_I:
res += im.name;
res += " $" + QString::number(rt()) + ", $" + QString::number(rs()) + ", 0x" + QString::number(immediate(), 16).toUpper();
break;
- case IT_J:
+ case T_J:
res += im.name;
// TODO we need to know instruction address to expand address section by it
res += " " + QString::number(address(), 16).toUpper();
break;
- case IT_R:
+ case T_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)))
@@ -256,6 +271,8 @@ QString Instruction::to_str() const {
res += " $" + QString::number(rd()) + ", $" + QString::number(rs()) + ", $" + QString::number(rt());
break;
}
+ case T_UNKNOWN:
+ return QString("UNKNOWN");
}
return res;
}