From dce00ea47fd4100df97349fd2bf998169b05b74a Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Tue, 2 Jul 2019 15:00:17 +0200 Subject: Change instruction parsing to allow multiple words pseudo-operations. Signed-off-by: Pavel Pisa --- qtmips_gui/mainwindow.cpp | 15 +++-- qtmips_gui/programmodel.cpp | 3 +- qtmips_machine/instruction.cpp | 144 ++++++++++++++++++++++------------------- qtmips_machine/instruction.h | 13 +++- 4 files changed, 99 insertions(+), 76 deletions(-) diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index c9d89d9..3301367 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -606,16 +606,21 @@ void MainWindow::compile_source() { } if (line.isEmpty()) continue; - machine::Instruction inst; - inst = machine::Instruction::from_string(line, &ok, address, &reloc, ln); - if (!ok) { + std::uint32_t inst[2] = {0, 0}; + ssize_t size = machine::Instruction::code_from_string(inst, 8, line, + address, &reloc, ln, true); + if (size < 0) { QMessageBox::critical(this, "QtMips Error", tr("line %1 instruction %2 parse error.") .arg(QString::number(ln), line)); + ok = false; break; } - mem->write_word(address, inst.data()); - address += 4; + std::uint32_t *p = inst; + for (ssize_t l = 0; l < size; l += 4) { + mem->write_word(address, *(p++)); + address += 4; + } } SymbolTableDb symtab(machine->symbol_table()); foreach(machine::RelocExpression *r, reloc) { diff --git a/qtmips_gui/programmodel.cpp b/qtmips_gui/programmodel.cpp index 64dffb8..0f3341f 100644 --- a/qtmips_gui/programmodel.cpp +++ b/qtmips_gui/programmodel.cpp @@ -274,8 +274,7 @@ bool ProgramModel::setData(const QModelIndex & index, const QVariant & value, in mem->write_word(address, data); break; case 3: - data = machine::Instruction::from_string(value.toString(), &ok, address).data(); - if (!ok) + if (machine::Instruction::code_from_string(&data, 4, value.toString(), address) < 0) return false; mem->write_word(address, data); break; diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index 99ca26b..1d32f17 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -1066,71 +1066,21 @@ static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_a } } -Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr, - RelocExpressionList *reloc, int line) { - std::uint32_t code; - bool ok = false; - - if (str_to_instruction_code_map.isEmpty()) - instruction_from_string_build_base(); - - QString inst_base = ""; - QVector inst_fields(0); - bool prev_white = true; - bool act_white; - bool comma = false; - bool next_comma = false; +ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, + QString inst_base, QVector &inst_fields, + std::uint32_t inst_addr, RelocExpressionList *reloc, + int line, bool pseudo_opt) +{ 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).toUpper(); - } 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); - } - + std::uint32_t inst_code = 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); + inst_code = i.value(); + const InstructionMap &im = InstructionMapFind(inst_code); field = 0; foreach (const QString &arg, im.args) { @@ -1241,7 +1191,7 @@ Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr, } } val = (val & ((1 << bits) - 1)) << shift; - code += val; + inst_code += val; fl = fl.mid(chars_taken); } if (field == -1) @@ -1250,17 +1200,77 @@ Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr, if (field != inst_fields.count()) continue; - if (pok != nullptr) - *pok = true; + if (buffsize >= 4) + *code = inst_code; + return 4; + } + + ssize_t ret = -1; + inst_code = 0; + if ((inst_base == "NOP") && (inst_fields.size() == 0)) { + inst_code = 0; + ret = 4; + } + if (buffsize >= 4) + *code = inst_code; + return ret; +} + +ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, + QString str, std::uint32_t inst_addr, + RelocExpressionList *reloc, int line, bool pseudo_opt) +{ + if (str_to_instruction_code_map.isEmpty()) + instruction_from_string_build_base(); + + QString inst_base = ""; + QVector 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; + } - return Instruction(code); + 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).toUpper(); + } else { + if ((field && !comma) || (!field && comma)) { + error = true; + break; + } + inst_fields.append(str.mid(l, k - l)); + comma = false; + field++; + } + l = k; + } } - if (str.toUpper() == "NOP") - ok = true; - if (pok != nullptr) - *pok = ok; - return Instruction(0); + if (error) + return -1; + + return code_from_string(code, buffsize, inst_base, inst_fields, inst_addr, + reloc, line, pseudo_opt); } bool Instruction::update(std::int64_t val, RelocExpression *relocexp) { diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index d55b079..3e48fc2 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -144,8 +144,17 @@ public: QString to_str(std::int32_t inst_addr = 0) const; - static Instruction from_string(QString str, bool *pok = nullptr, - std::uint32_t inst_addr = 0, RelocExpressionList *reloc = nullptr, int line = 0); + static ssize_t code_from_string(std::uint32_t *code, size_t buffsize, + QString inst_base, QVector &inst_fields, + std::uint32_t inst_addr = 0, + RelocExpressionList *reloc = nullptr, + int line = 0, bool pseudo_opt = false); + + static ssize_t code_from_string(std::uint32_t *code, size_t buffsize, + QString str, std::uint32_t inst_addr = 0, + RelocExpressionList *reloc = nullptr, + int line = 0, bool pseudo_opt = false); + bool update(std::int64_t val, RelocExpression *relocexp); private: std::uint32_t dt; -- cgit v1.2.3