aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-07-02 15:00:17 +0200
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-07-02 15:00:17 +0200
commitdce00ea47fd4100df97349fd2bf998169b05b74a (patch)
treec493de54f5f0309b5af893e4b9e8fa8c34cdf9a6
parentcf97513e757cdd25e6b1dd1fd584e4ec13d93cb1 (diff)
downloadqtmips-dce00ea47fd4100df97349fd2bf998169b05b74a.tar.gz
qtmips-dce00ea47fd4100df97349fd2bf998169b05b74a.tar.bz2
qtmips-dce00ea47fd4100df97349fd2bf998169b05b74a.zip
Change instruction parsing to allow multiple words pseudo-operations.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r--qtmips_gui/mainwindow.cpp15
-rw-r--r--qtmips_gui/programmodel.cpp3
-rw-r--r--qtmips_machine/instruction.cpp144
-rw-r--r--qtmips_machine/instruction.h13
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<QString> 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<QString> &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<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;
+ }
- 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<QString> &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;