aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/programmemory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qtmips_machine/programmemory.cpp')
-rw-r--r--qtmips_machine/programmemory.cpp145
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);
}