diff options
Diffstat (limited to 'qtmips_machine/programmemory.cpp')
-rw-r--r-- | qtmips_machine/programmemory.cpp | 145 |
1 files changed, 134 insertions, 11 deletions
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); } |