diff options
author | Karel Kočí <cynerd@email.cz> | 2017-08-30 21:37:53 +0200 |
---|---|---|
committer | Karel Kočí <cynerd@email.cz> | 2017-08-30 21:42:02 +0200 |
commit | 9cf92379d5fcf0076c25dae0935daab446c992cd (patch) | |
tree | dd09a2e996db1e5a8117f01bec76f1e93eaca6e1 /qtmips_machine/programmemory.cpp | |
download | qtmips-9cf92379d5fcf0076c25dae0935daab446c992cd.tar.gz qtmips-9cf92379d5fcf0076c25dae0935daab446c992cd.tar.bz2 qtmips-9cf92379d5fcf0076c25dae0935daab446c992cd.zip |
Initial commit
Adding work done so far.
Diffstat (limited to 'qtmips_machine/programmemory.cpp')
-rw-r--r-- | qtmips_machine/programmemory.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/qtmips_machine/programmemory.cpp b/qtmips_machine/programmemory.cpp new file mode 100644 index 0000000..c5ef53a --- /dev/null +++ b/qtmips_machine/programmemory.cpp @@ -0,0 +1,111 @@ +#include "programmemory.h" +#include <sstream> +#include "qtmipsexception.h" +#include "instructions/arithmetic.h" +#include "instructions/loadstore.h" +#include "instructions/nop.h" +#include "instructions/shift.h" + +ProgramMemory::ProgramMemory(ProgramLoader *loader, MemoryAccess *memory) { + this->memory = memory; + // Load program to memory (just dump it byte by byte, decode is done on demand) + for (int i = 0; i < loader->get_nsec(); i++) { + std::uint32_t base_address = loader->get_address(i); + std::vector<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 & ~((1 << (LEN+OFFSET+1)) - 1)) >> OFFSET) + +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 + Instruction *inst; + 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); + } else { + return decode_i(dt); + } +} + +// TODO implement +#define I_UNKNOWN(DATA) do { std::stringstream ss; ss << std::hex << DATA; throw QTMIPS_EXCEPTION(UnsupportedInstruction, "Unknown instruction, can't decode", ss.str()); } while(false); +#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); + if (!func) + return new InstructionNop(); + + 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 { // TODO filter rest + I_UNKNOWN(dt); + } +} + +Instruction *ProgramMemory::decode_j(std::uint32_t dt) { + std::uint32_t address = MASKSUB(dt, 26, 0); + // TODO + I_UNKNOWN(dt); +} + +Instruction *ProgramMemory::decode_i(std::uint32_t dt) { + // 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); +} |