aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/programmemory.cpp236
-rw-r--r--qtmips_machine/qtmips_machine.pro6
-rw-r--r--qtmips_machine/tests/testprogrammemory.cpp127
3 files changed, 0 insertions, 369 deletions
diff --git a/qtmips_machine/programmemory.cpp b/qtmips_machine/programmemory.cpp
deleted file mode 100644
index 2f0e19e..0000000
--- a/qtmips_machine/programmemory.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-#include "programmemory.h"
-#include <sstream>
-#include "qtmipsexception.h"
-#include "instructions/arithmetic.h"
-#include "instructions/loadstore.h"
-#include "instructions/nop.h"
-#include "instructions/shift.h"
-#include <iostream>
-
-ProgramMemory::ProgramMemory(MemoryAccess *memory) {
- this->memory = memory;
-}
-
-void ProgramMemory::load(ProgramLoader *loader) {
- // Load program to memory (just dump it byte by byte, decode is done on demand)
- 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++) {
- memory->write_byte(base_address + i, *it);
- }
- }
-}
-
-#define MASKSUB(VAR, LEN, OFFSET) (((VAR) >> (OFFSET)) & ((1 << (LEN)) - 1))
-
-Instruction *ProgramMemory::at(std::uint32_t address) {
- if (address % 4)
- // TODO different exception (unaligned address)
- throw std::exception();
- // Read instruction from memory
- std::uint32_t dt = this->memory->read_word(address);
-
- // Decode instruction
- 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, opcode);
- } else {
- return decode_i(dt, opcode);
- }
-}
-
-#define I_UNKNOWN(DATA) throw QTMIPS_EXCEPTION(UnsupportedInstruction, "Unknown instruction, can't decode", QString::number(DATA, 16))
-#define I_UNSUPPORTED(INST) throw QTMIPS_EXCEPTION(UnsupportedInstruction, "Decoded unsupported unstruction", #INST)
-
-Instruction *ProgramMemory::decode_r(std::uint32_t dt) {
- std::uint8_t func = MASKSUB(dt, 6, 0);
-
- std::uint8_t rs, rt, rd, sa;
- rs = MASKSUB(dt, 5, 21);
- rt = MASKSUB(dt, 5, 16);
- rd = MASKSUB(dt, 5, 11);
- sa = MASKSUB(dt, 5, 6);
-
- if (func < 8) { // Shift instructions
- bool variable = false;
- enum InstructionShiftT t;
- switch (func) {
- case 0:
- t = IST_LL;
- break;
- case 2:
- t = IST_RL;
- break;
- case 3:
- t = IST_RA;
- break;
- case 4:
- t = IST_LL;
- variable = true;
- break;
- case 6:
- t = IST_RL;
- variable = true;
- break;
- case 7:
- t = IST_RA;
- variable = true;
- break;
- default:
- I_UNKNOWN(dt);
- }
- if (variable)
- return new InstructionShiftVariable(t, rs, rt, rd);
- else
- return new InstructionShift(t, rt, rd, sa);
- } 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, std::uint8_t opcode) {
- std::uint32_t address = MASKSUB(dt, 26, 0);
- // TODO
- I_UNKNOWN(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);
-
- 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/qtmips_machine.pro b/qtmips_machine/qtmips_machine.pro
index a1edcaa..ff5cc3f 100644
--- a/qtmips_machine/qtmips_machine.pro
+++ b/qtmips_machine/qtmips_machine.pro
@@ -32,12 +32,6 @@ HEADERS += \
instruction.h \
registers.h \
programloader.h \
- programmemory.h \
- instructions/arithmetic.h \
- instructions/loadstore.h \
- instructions/shift.h \
- instructions/nop.h \
- instructions/jumpbranch.h \
cache.h \
alu.h \
machineconfig.h
diff --git a/qtmips_machine/tests/testprogrammemory.cpp b/qtmips_machine/tests/testprogrammemory.cpp
deleted file mode 100644
index 220b463..0000000
--- a/qtmips_machine/tests/testprogrammemory.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-#include "tst_machine.h"
-#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;
- ret << inst;
- if (rs)
- ret << rs;
- if (rd)
- ret << rd;
- if (rt)
- ret << rt;
- if (sa)
- ret << sa;
- 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");
-
- /* 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
-}
-
-void MachineTests::program_memory() {
- Memory m;
- ProgramMemory pm(&m);
-
- QFETCH(std::uint32_t, bin);
- QFETCH(QVector<QString>, 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);
-}