aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_machine/instruction.cpp63
-rw-r--r--qtmips_machine/instruction.h27
-rw-r--r--qtmips_machine/instructions/arithmetic.cpp90
-rw-r--r--qtmips_machine/instructions/arithmetic.h14
-rw-r--r--qtmips_machine/programmemory.cpp145
-rw-r--r--qtmips_machine/programmemory.h4
-rw-r--r--qtmips_machine/tests/testinstruction.cpp76
-rw-r--r--qtmips_machine/tests/testprogrammemory.cpp100
-rw-r--r--qtmips_machine/tests/tests.pro3
-rw-r--r--qtmips_machine/tests/tst_machine.h5
10 files changed, 491 insertions, 36 deletions
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp
index e03f794..1771afb 100644
--- a/qtmips_machine/instruction.cpp
+++ b/qtmips_machine/instruction.cpp
@@ -1,6 +1,51 @@
#include "instruction.h"
+#include "qtmipsexception.h"
-InstructionR::InstructionR(std::uint8_t rs, std::uint8_t rd, std::uint8_t rt, std::uint8_t sa) {
+Instruction::Instruction() {
+ this->st = IS_FETCH;
+}
+
+void Instruction::decode(Registers *regs) {
+ if (this->st != IS_FETCH)
+ // TODO other exception
+ throw std::exception();
+ this->st = IS_DECODE;
+}
+
+void Instruction::execute() {
+ if (this->st != IS_DECODE)
+ // TODO other exception
+ throw std::exception();
+ this->st = IS_EXECUTE;
+}
+
+void Instruction::memory(Memory *mem) {
+ if (this->st != IS_EXECUTE)
+ // TODO other exception
+ throw std::exception();
+ this->st = IS_MEMORY;
+}
+
+void Instruction::write_back(Registers *regs) {
+ if (this->st != IS_MEMORY)
+ // TODO other exception
+ throw std::exception();
+ this->st = IS_WRITE_BACK;
+}
+
+enum InstructionState Instruction::state() {
+ return this->st;
+}
+
+bool Instruction::running() {
+ return this->st > IS_FETCH && this->st < IS_WRITE_BACK;
+}
+
+bool Instruction::done() {
+ return this->st >= IS_WRITE_BACK;
+}
+
+InstructionR::InstructionR(std::uint8_t rs, std::uint8_t rd, std::uint8_t rt, std::uint8_t sa) : Instruction() {
this->rs = rs;
this->rd = rd;
this->rt = rt;
@@ -14,17 +59,17 @@ QVector<QString> InstructionR::to_strs() {
// Instruction name
str << "unknown"; // unknown instruction, should be replaced by child
// Source register
- str << QString::number((unsigned)this->rs, 16);
+ str << QString::number((unsigned)this->rs, 10);
// Target register
- str << QString::number((unsigned)this->rt, 16);
+ str << QString::number((unsigned)this->rt, 10);
// Destination register
- str << QString::number((unsigned)this->rd, 16);
+ str << QString::number((unsigned)this->rd, 10);
// Shift amount
- str << QString::number((unsigned)this->sa, 16);
+ str << QString::number((unsigned)this->sa, 10);
return str;
}
-InstructionI::InstructionI(std::uint8_t rs, std::uint8_t rt, std::uint16_t immediate) {
+InstructionI::InstructionI(std::uint8_t rs, std::uint8_t rt, std::uint16_t immediate) : Instruction() {
this->rs = rs;
this->rt = rt;
this->immediate = immediate;
@@ -35,15 +80,15 @@ QVector<QString> InstructionI::to_strs() {
// Instruction name
str << "unknown"; // unknown instruction, should be replaced by child
// Source register
- str << QString::number((unsigned)this->rs, 16);
+ str << QString::number((unsigned)this->rs, 10);
// Target register
- str << QString::number((unsigned)this->rt, 16);
+ str << QString::number((unsigned)this->rt, 10);
// Immediate value
str << QString::number((unsigned)this->immediate, 16);
return str;
}
-InstructionJ::InstructionJ(std::uint32_t address) {
+InstructionJ::InstructionJ(std::uint32_t address) : Instruction() {
this->address = address;
}
diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h
index 99a3ba4..8c5ede9 100644
--- a/qtmips_machine/instruction.h
+++ b/qtmips_machine/instruction.h
@@ -6,15 +6,32 @@
#include "registers.h"
#include "memory.h"
+enum InstructionState {
+ IS_FETCH,
+ IS_DECODE,
+ IS_EXECUTE,
+ IS_MEMORY,
+ IS_WRITE_BACK,
+};
+
class Instruction {
public:
- // TODO return types should be according to what instruction can pass from this stage
- //virtual void decode(Registers *regs) = 0; // Read and prepare instructions
- //virtual void execute() = 0; // ALU operations
- //virtual void memory(Memory *mem) = 0; // Read or write to memory
- //virtual void write_back(Registers *regs) = 0; // Write results to registers
+ Instruction();
+
+ // TODO return some info for forwarding, stall, flush
+ virtual void decode(Registers *regs); // Read and prepare instructions
+ virtual void execute(); // ALU operations
+ virtual void memory(Memory *mem); // Read or write to memory
+ virtual void write_back(Registers *regs); // Write results to registers
+
+ enum InstructionState state();
+ bool running();
+ bool done();
virtual QVector<QString> to_strs() = 0; // Returns all fields of instructions in string
+
+private:
+ enum InstructionState st;
};
class InstructionR : public Instruction {
diff --git a/qtmips_machine/instructions/arithmetic.cpp b/qtmips_machine/instructions/arithmetic.cpp
index a620436..f3cad86 100644
--- a/qtmips_machine/instructions/arithmetic.cpp
+++ b/qtmips_machine/instructions/arithmetic.cpp
@@ -5,6 +5,58 @@ InstructionArithmetic::InstructionArithmetic(enum InstructionArithmeticT type, s
this->type = type;
}
+void InstructionArithmetic::decode(Registers *regs) {
+ Instruction::decode(regs);
+ this->rs_d = regs->read_gp(this->rs);
+ this->rd_d = regs->read_gp(this->rd);
+}
+
+void InstructionArithmetic::execute() {
+ Instruction::execute();
+ switch (this->type) {
+ case IAT_ADD:
+ this->rt_d = (std::uint32_t)((std::int32_t)this->rs_d + (std::int32_t)this->rd_d);
+ break;
+ case IAT_ADDU:
+ this->rt_d = this->rs_d + this->rd_d;
+ break;
+ case IAT_SUB:
+ this->rt_d = (std::uint32_t)((std::int32_t)this->rs_d - (std::int32_t)this->rd_d);
+ break;
+ case IAT_SUBU:
+ this->rt_d = this->rs_d - this->rd_d;
+ break;
+ case IAT_AND:
+ this->rt_d = this->rs_d & this->rd_d;
+ break;
+ case IAT_OR:
+ this->rt_d = this->rs_d | this->rd_d;
+ break;
+ case IAT_XOR:
+ this->rt_d = this->rs_d ^ this->rd_d;
+ break;
+ case IAT_NOR:
+ // TODO
+ break;
+ case IAT_SLT:
+ // TODO
+ break;
+ case IAT_SLTU:
+ // TODO
+ break;
+ }
+}
+
+void InstructionArithmetic::memory(Memory *mem) {
+ Instruction::memory(mem);
+ // pass
+}
+
+void InstructionArithmetic::write_back(Registers *regs) {
+ Instruction::write_back(regs);
+ regs->write_gp(this->rt, this->rt_d);
+}
+
QVector<QString> InstructionArithmetic::to_strs() {
QVector<QString> str = this->InstructionR::to_strs();
str.erase(str.begin() + 4); // Drop sa field
@@ -51,6 +103,42 @@ InstructionArithmeticImmediate::InstructionArithmeticImmediate(enum InstructionA
this->type = type;
}
+void InstructionArithmeticImmediate::decode(Registers *regs) {
+ Instruction::decode(regs);
+ this->rs_d = regs->read_gp(this->rs);
+}
+
+void InstructionArithmeticImmediate::execute() {
+ Instruction::execute();
+ switch (this->type) {
+ case IAT_ADDI:
+ this->rt_d = (std::uint32_t)((std::int32_t)this->rs_d + (std::int32_t)this->immediate);
+ break;
+ case IAT_ADDIU:
+ this->rt_d = this->rs_d + this->immediate;
+ break;
+ case IAT_ANDI:
+ this->rt_d = (std::uint32_t)((std::int32_t)this->rs_d - (std::int32_t)this->immediate);
+ break;
+ case IAT_ORI:
+ this->rt_d = this->rs_d - this->immediate;
+ break;
+ case IAT_XORI:
+ this->rt_d = this->rs_d & this->immediate;
+ break;
+ }
+}
+
+void InstructionArithmeticImmediate::memory(Memory *mem) {
+ Instruction::memory(mem);
+ // pass
+}
+
+void InstructionArithmeticImmediate::write_back(Registers *regs) {
+ Instruction::write_back(regs);
+ regs->write_gp(this->rt, this->rt_d);
+}
+
QVector<QString> InstructionArithmeticImmediate::to_strs() {
QVector<QString> str = this->InstructionI::to_strs();
switch (this->type) {
@@ -76,7 +164,7 @@ QVector<QString> InstructionArithmeticImmediate::to_strs() {
str[0] = "sltiu";
break;
case IAT_LUI:
- str[0] = "lu";
+ str[0] = "lui";
break;
default:
// TODO different exception
diff --git a/qtmips_machine/instructions/arithmetic.h b/qtmips_machine/instructions/arithmetic.h
index 19f1df5..185ed95 100644
--- a/qtmips_machine/instructions/arithmetic.h
+++ b/qtmips_machine/instructions/arithmetic.h
@@ -19,9 +19,16 @@ enum InstructionArithmeticT {
class InstructionArithmetic : public InstructionR {
public:
InstructionArithmetic(enum InstructionArithmeticT type, std::uint8_t rs, std::uint8_t rd, std::uint8_t rt);
+
+ void decode(Registers *regs);
+ void execute();
+ void memory(Memory *mem);
+ void write_back(Registers *regs);
+
QVector<QString> to_strs();
private:
enum InstructionArithmeticT type;
+ std::uint32_t rs_d, rd_d, rt_d;
};
enum InstructionArithmeticImmediateT {
@@ -38,9 +45,16 @@ enum InstructionArithmeticImmediateT {
class InstructionArithmeticImmediate : public InstructionI {
public:
InstructionArithmeticImmediate(enum InstructionArithmeticImmediateT type, std::uint8_t rs, std::uint8_t rt, std::uint16_t value);
+
+ void decode(Registers *regs);
+ void execute();
+ void memory(Memory *mem);
+ void write_back(Registers *regs);
+
QVector<QString> to_strs();
private:
enum InstructionArithmeticImmediateT type;
+ std::uint32_t rs_d, rt_d;
};
#endif // ARITHMETIC_H
diff --git a/qtmips_machine/programmemory.cpp b/qtmips_machine/programmemory.cpp
index 74b16a8..2f0e19e 100644
--- a/qtmips_machine/programmemory.cpp
+++ b/qtmips_machine/programmemory.cpp
@@ -5,6 +5,7 @@
#include "instructions/loadstore.h"
#include "instructions/nop.h"
#include "instructions/shift.h"
+#include <iostream>
ProgramMemory::ProgramMemory(MemoryAccess *memory) {
this->memory = memory;
@@ -12,7 +13,7 @@ ProgramMemory::ProgramMemory(MemoryAccess *memory) {
void ProgramMemory::load(ProgramLoader *loader) {
// Load program to memory (just dump it byte by byte, decode is done on demand)
- for (int i = 0; i < loader->get_nsec(); i++) {
+ for (unsigned i = 0; i < loader->get_nsec(); i++) {
std::uint32_t base_address = loader->get_address(i);
QVector<std::uint8_t> data = loader->get_data(i);
for (auto it = data.begin(); it < data.end(); it++) {
@@ -21,7 +22,7 @@ void ProgramMemory::load(ProgramLoader *loader) {
}
}
-#define MASKSUB(VAR, LEN, OFFSET) ((VAR & ~((1 << (LEN+OFFSET+1)) - 1)) >> OFFSET)
+#define MASKSUB(VAR, LEN, OFFSET) (((VAR) >> (OFFSET)) & ((1 << (LEN)) - 1))
Instruction *ProgramMemory::at(std::uint32_t address) {
if (address % 4)
@@ -31,14 +32,15 @@ Instruction *ProgramMemory::at(std::uint32_t address) {
std::uint32_t dt = this->memory->read_word(address);
// Decode instruction
- Instruction *inst;
+ if (dt == 0)
+ return new InstructionNop();
std::uint8_t opcode = dt >> 26; // upper 6 bits
if (opcode == 0) { // Arithmetic and shift instructions
return this->decode_r(dt);
} else if (opcode == 2 || opcode == 3) { // Jump instructions
- return decode_j(dt);
+ return decode_j(dt, opcode);
} else {
- return decode_i(dt);
+ return decode_i(dt, opcode);
}
}
@@ -47,8 +49,6 @@ Instruction *ProgramMemory::at(std::uint32_t address) {
Instruction *ProgramMemory::decode_r(std::uint32_t dt) {
std::uint8_t func = MASKSUB(dt, 6, 0);
- if (!func)
- return new InstructionNop();
std::uint8_t rs, rt, rd, sa;
rs = MASKSUB(dt, 5, 21);
@@ -91,23 +91,146 @@ Instruction *ProgramMemory::decode_r(std::uint32_t dt) {
} else if (func < 10) { // Jump instructions
// TODO
I_UNKNOWN(dt);
+ } else if (func > 31 && func < 44) {
+ enum InstructionArithmeticT type;
+ switch (func) {
+ case 32:
+ type = IAT_ADD;
+ break;
+ case 33:
+ type = IAT_ADDU;
+ break;
+ case 34:
+ type = IAT_SUB;
+ break;
+ case 35:
+ type = IAT_SUBU;
+ break;
+ case 36:
+ type = IAT_AND;
+ break;
+ case 37:
+ type = IAT_OR;
+ break;
+ case 38:
+ type = IAT_XOR;
+ break;
+ case 39:
+ type = IAT_NOR;
+ break;
+ case 42:
+ type = IAT_SLT;
+ break;
+ case 43:
+ type = IAT_SLTU;
+ break;
+ default:
+ I_UNKNOWN(dt);
+ }
+ return new InstructionArithmetic(type, rs, rd, rt);
} else { // TODO filter rest
I_UNKNOWN(dt);
}
}
-Instruction *ProgramMemory::decode_j(std::uint32_t dt) {
+Instruction *ProgramMemory::decode_j(std::uint32_t dt, std::uint8_t opcode) {
std::uint32_t address = MASKSUB(dt, 26, 0);
// TODO
I_UNKNOWN(dt);
}
-Instruction *ProgramMemory::decode_i(std::uint32_t dt) {
+Instruction *ProgramMemory::decode_i(std::uint32_t dt, std::uint8_t opcode) {
// InstructionI
std::uint8_t rs, rt;
rs = MASKSUB(dt, 5, 21);
rt = MASKSUB(dt, 5, 16);
std::uint16_t immediate = MASKSUB(dt, 16, 0);
- // TODO
- I_UNKNOWN(dt);
+
+ if (opcode > 7 && opcode < 16) {
+ enum InstructionArithmeticImmediateT type;
+ switch (opcode) {
+ case 8:
+ type = IAT_ADDI;
+ break;
+ case 9:
+ type = IAT_ADDIU;
+ break;
+ case 10:
+ type = IAT_SLTI;
+ break;
+ case 11:
+ type = IAT_SLTIU;
+ break;
+ case 12:
+ type = IAT_ANDI;
+ break;
+ case 13:
+ type = IAT_ORI;
+ break;
+ case 14:
+ type = IAT_XORI;
+ break;
+ case 15:
+ type = IAT_LUI;
+ break;
+ default:
+ I_UNKNOWN(dt);
+ }
+ return new InstructionArithmeticImmediate(type, rs, rt, immediate);
+ } else if (opcode > 31 && opcode < 47) {
+ enum InstructionLoadStoreT type;
+ bool isload = false;
+ switch (opcode) {
+ case 32:
+ type = ILST_B;
+ isload = true;
+ break;
+ case 33:
+ type = ILST_HW;
+ isload = true;
+ break;
+ case 34:
+ type = ILST_WL;
+ isload = true;
+ break;
+ case 35:
+ type = ILST_W;
+ isload = true;
+ break;
+ case 36:
+ type = ILST_BU;
+ isload = true;
+ break;
+ case 37:
+ type = ILST_HU;
+ isload = true;
+ break;
+ case 38:
+ type = ILST_WR;
+ isload = true;
+ break;
+ case 40:
+ type = ILST_B;
+ break;
+ case 41:
+ type = ILST_HW;
+ break;
+ case 42:
+ type = ILST_WL;
+ break;
+ case 43:
+ type = ILST_W;
+ break;
+ case 46:
+ type = ILST_WR;
+ break;
+ default:
+ I_UNKNOWN(dt);
+ }
+ if (isload)
+ return new InstructionLoad(type, rs, rt, immediate);
+ else
+ return new InstructionStore(type, rs, rt, immediate);
+ } else
+ I_UNKNOWN(dt);
}
diff --git a/qtmips_machine/programmemory.h b/qtmips_machine/programmemory.h
index 158adb1..14187c5 100644
--- a/qtmips_machine/programmemory.h
+++ b/qtmips_machine/programmemory.h
@@ -16,8 +16,8 @@ public:
private:
MemoryAccess *memory;
Instruction *decode_r(std::uint32_t dt);
- Instruction *decode_j(std::uint32_t dt);
- Instruction *decode_i(std::uint32_t dt);
+ Instruction *decode_j(std::uint32_t dt, std::uint8_t opcode);
+ Instruction *decode_i(std::uint32_t dt, std::uint8_t opcode);
};
#endif // PROGRAMMEMORY_H
diff --git a/qtmips_machine/tests/testinstruction.cpp b/qtmips_machine/tests/testinstruction.cpp
new file mode 100644
index 0000000..a299bcf
--- /dev/null
+++ b/qtmips_machine/tests/testinstruction.cpp
@@ -0,0 +1,76 @@
+#include "tst_machine.h"
+#include "instructions/arithmetic.h"
+#include "instructions/jumpbranch.h"
+#include "instructions/loadstore.h"
+#include "instructions/nop.h"
+#include "instructions/shift.h"
+#include <iostream>
+
+void MachineTests::instruction_arithmetic_data() {
+ QTest::addColumn<size_t>("type");
+ QTest::addColumn<std::uint32_t>("res");
+
+ QTest::newRow("ADD") << (size_t)IAT_ADD << (unsigned)749;
+ QTest::newRow("ADDU") << (size_t)IAT_ADDU << (unsigned)749;
+ QTest::newRow("SUB") << (size_t)IAT_SUB << (unsigned)-665;
+ QTest::newRow("SUBU") << (size_t)IAT_SUBU << (unsigned)-665;
+ QTest::newRow("AND") << (size_t)IAT_AND << (unsigned)2;
+ QTest::newRow("OR") << (size_t)IAT_OR << (unsigned)747;
+ QTest::newRow("XOR") << (size_t)IAT_XOR << (unsigned)745;
+ // TODO others
+}
+
+void MachineTests::instruction_arithmetic() {
+ Registers regs;
+
+ QFETCH(size_t, type);
+ QFETCH(std::uint32_t, res);
+
+ // TODO meaby one more dataset?
+
+ regs.write_gp(12, 42);
+ regs.write_gp(8, 707);
+ regs.write_gp(5, 0);
+
+ Instruction *i = new InstructionArithmetic((enum InstructionArithmeticT)type, 12, 8, 5);
+
+ i->decode(&regs);
+ i->execute();
+ i->memory(nullptr); // We should not work with memory so segfault here is basically a test
+ i->write_back(&regs);
+
+ QCOMPARE(regs.read_gp(5), (std::uint32_t)res);
+}
+
+void MachineTests::instruction_arithmetic_immediate_data() {
+ QTest::addColumn<size_t>("type");
+ QTest::addColumn<std::uint32_t>("res");
+
+ QTest::newRow("ADDI") << (size_t)IAT_ADDI << (unsigned)749;
+ QTest::newRow("ADDIU") << (size_t)IAT_ADDIU << (unsigned)749;
+ QTest::newRow("ANDI") << (size_t)IAT_ANDI << (unsigned)-665;
+ QTest::newRow("ORI") << (size_t)IAT_ORI << (unsigned)-665;
+ QTest::newRow("XORI") << (size_t)IAT_XORI << (unsigned)2;
+ // TODO others
+}
+
+void MachineTests::instruction_arithmetic_immediate() {
+ Registers regs;
+
+ QFETCH(size_t, type);
+ QFETCH(std::uint32_t, res);
+
+ // TODO meaby one more dataset?
+
+ regs.write_gp(9, 42);
+ regs.write_gp(3, 0);
+
+ Instruction *i = new InstructionArithmeticImmediate((enum InstructionArithmeticImmediateT)type, 9, 3, 707);
+
+ i->decode(&regs);
+ i->execute();
+ i->memory(nullptr); // We should not work with memory so segfault here is basically a test
+ i->write_back(&regs);
+
+ QCOMPARE(regs.read_gp(3), (std::uint32_t)res);
+}
diff --git a/qtmips_machine/tests/testprogrammemory.cpp b/qtmips_machine/tests/testprogrammemory.cpp
index a08bbab..220b463 100644
--- a/qtmips_machine/tests/testprogrammemory.cpp
+++ b/qtmips_machine/tests/testprogrammemory.cpp
@@ -2,6 +2,7 @@
#include "programmemory.h"
#include <qstring.h>
#include <qvector.h>
+#include <iostream>
QVector<QString> str_inst_r(const char *inst, const char *rs, const char *rd, const char *rt, const char *sa) {
QVector<QString> ret;
@@ -17,15 +18,91 @@ QVector<QString> str_inst_r(const char *inst, const char *rs, const char *rd, co
return ret;
}
+QVector<QString> str_inst_i(const char *inst, const char *rs, const char *rt, const char *immediate) {
+ QVector<QString> ret;
+ ret << inst;
+ if (rs)
+ ret << rs;
+ if (rt)
+ ret << rt;
+ ret << immediate;
+ return ret;
+}
+
+QVector<QString> str_inst_j(const char *inst, const char *address) {
+ QVector<QString> ret;
+ ret << inst;
+ ret << address;
+ return ret;
+}
+
#define I(II) ((std::uint32_t) II)
+#define I_R(OP, RS, RD, RT, SA, F) ((std::uint32_t)(((OP) << 26) | ((RS) << 21) | ((RT) << 16) | ((RD) << 11) | ((SA) << 6) | (F)))
+#define I_I(OP, RS, RT, IMM) ((std::uint32_t)(((OP) << 26) | ((RS) << 21) | ((RT) << 16) | (IMM)))
+#define I_J(OP, ADDR) ((std::uint32_t)(((OP) << 26) | (ADDR)))
void MachineTests::program_memory_data() {
QTest::addColumn<std::uint32_t>("bin");
QTest::addColumn<QVector<QString>>("str");
- // TODO correct instruction
- QTest::newRow("NOP") << I(0x000000) << str_inst_r("nop", nullptr, nullptr, nullptr, nullptr);
- //QTest::newRow("SLL") << I(0x000000) << str_inst_r("sll", "", "", nullptr, nullptr);
+ /* NOP */
+ QTest::newRow("NOP") << I(0) << str_inst_r("nop", nullptr, nullptr, nullptr, nullptr);
+ /* ALU */
+ QTest::newRow("ADD") << I_R(0, 12, 14, 13, 0, 32) << str_inst_r("add", "12", "13", "14", nullptr);
+ QTest::newRow("ADDU") << I_R(0, 12, 14, 13, 0, 33) << str_inst_r("addu", "12", "13", "14", nullptr);
+ QTest::newRow("SUB") << I_R(0, 12, 14, 13, 0, 34) << str_inst_r("sub", "12", "13", "14", nullptr);
+ QTest::newRow("SUBU") << I_R(0, 12, 14, 13, 0, 35) << str_inst_r("subu", "12", "13", "14", nullptr);
+ QTest::newRow("AND") << I_R(0, 12, 14, 13, 0, 36) << str_inst_r("and", "12", "13", "14", nullptr);
+ QTest::newRow("OR") << I_R(0, 12, 14, 13, 0, 37) << str_inst_r("or", "12", "13", "14", nullptr);
+ QTest::newRow("XOR") << I_R(0, 12, 14, 13, 0, 38) << str_inst_r("xor", "12", "13", "14", nullptr);
+ QTest::newRow("NOR") << I_R(0, 12, 14, 13, 0, 39) << str_inst_r("nor", "12", "13", "14", nullptr);
+ // TODO missing
+ QTest::newRow("SLT") << I_R(0, 12, 14, 13, 0, 42) << str_inst_r("slt", "12", "13", "14", nullptr);
+ QTest::newRow("SLTU") << I_R(0, 12, 14, 13, 0, 43) << str_inst_r("sltu", "12", "13", "14", nullptr);
+ QTest::newRow("ADDI") << I_I(8, 12, 13, 42) << str_inst_i("addi", "12", "13", "2a");
+ QTest::newRow("ADDIU") << I_I(9, 12, 13, 42) << str_inst_i("addiu", "12", "13", "2a");
+ QTest::newRow("SLTI") << I_I(10, 12, 13, 42) << str_inst_i("slti", "12", "13", "2a");
+ QTest::newRow("SLTIU") << I_I(11, 12, 13, 42) << str_inst_i("sltiu", "12", "13", "2a");
+ QTest::newRow("ANDI") << I_I(12, 12, 13, 42) << str_inst_i("andi", "12", "13", "2a");
+ QTest::newRow("ORI") << I_I(13, 12, 13, 42) << str_inst_i("ori", "12", "13", "2a");
+ QTest::newRow("XORI") << I_I(14, 12, 13, 42) << str_inst_i("xori", "12", "13", "2a");
+ QTest::newRow("LUI") << I_I(15, 12, 13, 42) << str_inst_i("lui", "12", "13", "2a");
+ /* Load and store */
+ QTest::newRow("LB") << I_I(32, 12, 13, 42) << str_inst_i("lb", "12", "13", "2a");
+ QTest::newRow("LH") << I_I(33, 12, 13, 42) << str_inst_i("lh", "12", "13", "2a");
+ QTest::newRow("LWL") << I_I(34, 12, 13, 42) << str_inst_i("lwl", "12", "13", "2a");
+ QTest::newRow("LW") << I_I(35, 12, 13, 42) << str_inst_i("lw", "12", "13", "2a");
+ QTest::newRow("LBU") << I_I(36, 12, 13, 42) << str_inst_i("lbu", "12", "13", "2a");
+ QTest::newRow("LHU") << I_I(37, 12, 13, 42) << str_inst_i("lhu", "12", "13", "2a");
+ QTest::newRow("LWR") << I_I(38, 12, 13, 42) << str_inst_i("lwr", "12", "13", "2a");
+ // TODO missing
+ QTest::newRow("SB") << I_I(40, 12, 13, 42) << str_inst_i("sb", "12", "13", "2a");
+ QTest::newRow("SH") << I_I(41, 12, 13, 42) << str_inst_i("sh", "12", "13", "2a");
+ QTest::newRow("SWL") << I_I(42, 12, 13, 42) << str_inst_i("swl", "12", "13", "2a");
+ QTest::newRow("SW") << I_I(43, 12, 13, 42) << str_inst_i("sw", "12", "13", "2a");
+ // TODO missing
+ QTest::newRow("SWR") << I_I(46, 12, 13, 42) << str_inst_i("swr", "12", "13", "2a");
+ /* Shifts */
+ QTest::newRow("SLL") << I_R(0, 0, 13, 14, 12, 0) << str_inst_r("sll", nullptr, "13", "14", "12");
+ // TODO missing
+ QTest::newRow("SRL") << I_R(0, 0, 13, 14, 12, 2) << str_inst_r("srl", nullptr, "13", "14", "12");
+ QTest::newRow("SRA") << I_R(0, 0, 13, 14, 12, 3) << str_inst_r("sra", nullptr, "13", "14", "12");
+ QTest::newRow("SLLV") << I_R(0, 12, 13, 14, 0, 4) << str_inst_r("sllv", "12", "13", "14", nullptr);
+ // TODO missing
+ QTest::newRow("SRLV") << I_R(0, 12, 13, 14, 0, 6) << str_inst_r("srlv", "12", "13", "14", nullptr);
+ QTest::newRow("SRAV") << I_R(0, 12, 13, 14, 0, 7) << str_inst_r("srav", "12", "13", "14", nullptr);
+ /* Jump and branch */
+ //QTest::newRow("JR") << I_R(0, 12, 13, 14, 0, 8) << str_inst_r("jr", "12", "13", "14", nullptr);
+ //QTest::newRow("JALR") << I_R(0, 12, 13, 14, 0, 9) << str_inst_r("jalr", "12", "13", "14", nullptr);
+ //QTest::newRow("BLTZ") << I_I(1, 12, 0, 42) << str_inst_i("bltz", "12", nullptr, "2a");
+ //QTest::newRow("BGEZ") << I_I(1, 12, 1, 42) << str_inst_i("bltz", "12", nullptr, "2a");
+ // TODO missing
+ //QTest::newRow("BLTZAL") << I_I(1, 12, 16, 42) << str_inst_i("bltzal", "12", nullptr, "2a");
+ //QTest::newRow("BGEZAL") << I_I(1, 12, 17, 42) << str_inst_i("bgezal", "12", nullptr, "2a");
+ // TODO missing?
+ //QTest::newRow("J") << I_J(1, 4242) << str_inst_j("j", "1092");
+ //QTest::newRow("JAL") << I_J(2, 4242) << str_inst_j("jal", "1092");
+
// TODO other instructions
}
@@ -33,9 +110,18 @@ void MachineTests::program_memory() {
Memory m;
ProgramMemory pm(&m);
- QFETCH(std::uint32_t, bin);
- QFETCH(QVector<QString>, str);
+ QFETCH(std::uint32_t, bin);
+ QFETCH(QVector<QString>, str);
- m.write_word(0x00, bin);
- QCOMPARE(pm.at(0x00)->to_strs(), str);
+ m.write_word(0x00, bin);
+ /*
+ Instruction *i = pm.at(0x00);
+ QVector<QString> s = i->to_strs();
+ for (int i = 0; i < str.size(); i++) {
+ std::cout << s[i].toStdString() << " ";
+ }
+ std::cout << std::endl;
+ std::cout.flush();
+ */
+ QCOMPARE(pm.at(0x00)->to_strs(), str);
}
diff --git a/qtmips_machine/tests/tests.pro b/qtmips_machine/tests/tests.pro
index b9f1497..287d1e8 100644
--- a/qtmips_machine/tests/tests.pro
+++ b/qtmips_machine/tests/tests.pro
@@ -18,7 +18,8 @@ DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += tst_machine.cpp \
testmemory.cpp \
testregisters.cpp \
- testprogrammemory.cpp
+ testprogrammemory.cpp \
+ testinstruction.cpp
HEADERS += tst_machine.h
diff --git a/qtmips_machine/tests/tst_machine.h b/qtmips_machine/tests/tst_machine.h
index 50915f5..c05e8ad 100644
--- a/qtmips_machine/tests/tst_machine.h
+++ b/qtmips_machine/tests/tst_machine.h
@@ -20,6 +20,11 @@ private Q_SLOTS:
// ProgramMemory
void program_memory();
void program_memory_data();
+ // Instruction
+ void instruction_arithmetic();
+ void instruction_arithmetic_data();
+ void instruction_arithmetic_immediate();
+ void instruction_arithmetic_immediate_data();
};
#endif // TST_MACHINE_H