diff options
-rw-r--r-- | qtmips_machine/programmemory.cpp | 236 | ||||
-rw-r--r-- | qtmips_machine/qtmips_machine.pro | 6 | ||||
-rw-r--r-- | qtmips_machine/tests/testprogrammemory.cpp | 127 |
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); -} |