diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-02-12 16:18:58 +0100 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-02-12 16:18:58 +0100 |
commit | df292aade4d174a7a5824f463b3a1dccf20e6c54 (patch) | |
tree | 85d26d5a0d5101f5caae6dcde20b515f98bcbb06 /qtmips_machine | |
parent | fc27072b451dd8385401fadf198db69b0e87c72c (diff) | |
download | qtmips-df292aade4d174a7a5824f463b3a1dccf20e6c54.tar.gz qtmips-df292aade4d174a7a5824f463b3a1dccf20e6c54.tar.bz2 qtmips-df292aade4d174a7a5824f463b3a1dccf20e6c54.zip |
Make memory and program listing editable.
Instruction parsing is rough and does not support branch offset computation.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
Diffstat (limited to 'qtmips_machine')
-rw-r--r-- | qtmips_machine/instruction.cpp | 258 | ||||
-rw-r--r-- | qtmips_machine/instruction.h | 1 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.cpp | 8 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.h | 2 |
4 files changed, 265 insertions, 4 deletions
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index 70247bd..90a6ca1 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -33,6 +33,8 @@ * ******************************************************************************/ +#include <QMultiMap> +#include <QVector> #include "instruction.h" #include "alu.h" #include "memory.h" @@ -440,24 +442,29 @@ Instruction::Instruction(const Instruction &i) { #define MASK(LEN,OFF) ((this->dt >> (OFF)) & ((1 << (LEN)) - 1)) +#define RS_SHIFT 21 +#define RT_SHIFT 16 +#define RD_SHIFT 11 +#define SHAMT_SHIFT 6 + std::uint8_t Instruction::opcode() const { return (std::uint8_t) MASK(6, 26); } std::uint8_t Instruction::rs() const { - return (std::uint8_t) MASK(5, 21); + return (std::uint8_t) MASK(5, RS_SHIFT); } std::uint8_t Instruction::rt() const { - return (std::uint8_t) MASK(5, 16); + return (std::uint8_t) MASK(5, RT_SHIFT); } std::uint8_t Instruction::rd() const { - return (std::uint8_t) MASK(5, 11); + return (std::uint8_t) MASK(5, RD_SHIFT); } std::uint8_t Instruction::shamt() const { - return (std::uint8_t) MASK(5, 6); + return (std::uint8_t) MASK(5, SHAMT_SHIFT); } @@ -617,3 +624,246 @@ QString Instruction::to_str(std::int32_t inst_addr) const { } return res; } + +QMultiMap<QString, std::uint32_t> str_to_instruction_code_map; + +void instruction_from_string_build_base(const InstructionMap *im = nullptr, + unsigned int flags = 0, std::uint32_t base_code = 0) { + std::uint32_t code; + + if (im == nullptr) { + im = instruction_map; + flags = instruction_map_opcode_field; + base_code = 0; + } + unsigned int bits = IMF_SUB_GET_BITS(flags); + unsigned int shift = IMF_SUB_GET_SHIFT(flags); + + for (unsigned int i = 0; i < 1U << bits; i++, im++) { + code = base_code | (i << shift); + if (im->subclass) { + instruction_from_string_build_base(im->subclass, im->flags, code); + continue; + } + if (!(im->flags & IMF_SUPPORTED)) + continue; + str_to_instruction_code_map.insert(im->name, code); + } +} + +static int parse_reg_from_string(QString str) +{ + bool ok; + int res; + if (str.count() < 2 || str.at(0) != '$') + return -1; + str = str.mid(1, str.count() - 1); + res = str.toULong(&ok, 10); + if (!ok) + return -1; + if (res > 31) + return -1; + return res; +} + +Instruction Instruction::from_string(QString str, bool *pok) { + std::uint32_t code; + int val; + bool ok = false; + + if (str_to_instruction_code_map.isEmpty()) + instruction_from_string_build_base(); + + str = str.toUpper(); + + QString inst_base = ""; + QVector<QString> inst_fields(0); + bool prev_white = true; + bool act_white; + bool comma = false; + bool next_comma = false; + int field = 0; + bool error = false; + + for (int k = 0, l = 0; k < str.count() + 1; k++, prev_white = act_white) { + if (next_comma) + comma = true; + next_comma = false; + if (k >= str.count()) { + act_white = true; + } else { + act_white = str.at(k).isSpace(); + if (str.at(k) == ',') + next_comma = act_white = true; + } + + if (prev_white and !act_white) + l = k; + if (!prev_white and act_white) { + if (inst_base.count() == 0) { + if (comma) { + error = true; + break; + } + inst_base = str.mid(l, k - l); + } else { + if ((field && !comma) || (!field && comma)) { + error = true; + break; + } + inst_fields.append(str.mid(l, k - l)); + comma = false; + field++; + } + l = k; + } + } + + if (error) { + if (pok != nullptr) + *pok = true; + return Instruction(0); + } + + auto i = str_to_instruction_code_map.lowerBound(inst_base); + for (; ; i++) { + if (i == str_to_instruction_code_map.end()) + break; + if (i.key() != inst_base) + break; + code = i.value(); + const InstructionMap &im = InstructionMapFind(code); + + field = 0; + switch (im.type) { + case T_I: + if (im.flags & IMF_MEM) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RT_SHIFT; + if (field >= inst_fields.count()) + continue; + int lpar = inst_fields.at(field).indexOf('('); + int rpar = inst_fields.at(field).indexOf(')'); + if (lpar == -1 || rpar == -1) + continue; + if ((val = parse_reg_from_string(inst_fields. + at(field).mid(lpar+1, rpar - lpar - 1))) < 0) + continue; + code |= val << RS_SHIFT; + + val = inst_fields.at(field).mid(0, lpar).toLong(&ok, 0); + if (!ok) + continue; + ok = false; + code |= val & 0xffff; + field ++; + } else { + if (im.flags & IMF_REGWRITE) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RT_SHIFT; + } + if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RS_SHIFT; + } + if (im.flags & (IMF_BJR_REQ_RT | IMF_ALU_REQ_RT) && !(im.flags & IMF_REGWRITE)) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RT_SHIFT; + } + if (field >= inst_fields.count()) + continue; + val = inst_fields.at(field++).toLong(&ok, 0); + if (!ok) + continue; + ok = false; + code |= val & 0xffff; + } + break; + case T_J: + if (field >= inst_fields.count()) + continue; + val = inst_fields.at(field++).toLong(&ok, 0); + code |= (val >> 2) & ~0xF0000000; + break; + case T_R: + if (im.flags & IMF_REGD) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RD_SHIFT; + } + if (!(im.flags & IMF_ALU_SHIFT)) { + if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RS_SHIFT; + } + } + if (im.flags & (IMF_BJR_REQ_RT | IMF_ALU_REQ_RT)) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RT_SHIFT; + } + if (im.flags & IMF_ALU_SHIFT) { + if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RS_SHIFT; + } else { + if (field >= inst_fields.count()) + continue; + val = inst_fields.at(field++).toLong(&ok, 0); + if (!ok) + continue; + ok = false; + code |= val << (SHAMT_SHIFT & 0x1f); + } + } + if ((im.flags & IMF_REGWRITE) && !(im.flags & IMF_REGD)) { + if (field >= inst_fields.count()) + continue; + if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) + continue; + code |= val << RD_SHIFT; + } + break; + case T_UNKNOWN: + break; + } + + if (field != inst_fields.count()) + continue; + + if (pok != nullptr) + *pok = true; + + return Instruction(code); + } + + printf("not found\n"); + + if (str == "NOP") + ok = true; + if (pok != nullptr) + *pok = ok; + return Instruction(0); +} diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index bb6f410..0d76eeb 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -115,6 +115,7 @@ public: QString to_str(std::int32_t inst_addr = 0) const; + static Instruction from_string(QString str, bool *pok = nullptr); private: std::uint32_t dt; }; diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index 382a9f2..69deeb1 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -114,6 +114,10 @@ const Memory *QtMipsMachine::memory() { return mem; } +Memory *QtMipsMachine::memory_rw() { + return mem; +} + const Cache *QtMipsMachine::cache_program() { return cch_program; } @@ -122,6 +126,10 @@ const Cache *QtMipsMachine::cache_data() { return cch_data; } +Cache *QtMipsMachine::cache_data_rw() { + return cch_data; +} + const Core *QtMipsMachine::core() { return cr; } diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index 22ba0f9..4ad39c5 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -61,8 +61,10 @@ public: const Registers *registers(); const Memory *memory(); + Memory *memory_rw(); const Cache *cache_program(); const Cache *cache_data(); + Cache *cache_data_rw(); const Core *core(); const CoreSingle *core_singe(); const CorePipelined *core_pipelined(); |