aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-07-03 08:44:32 +0200
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-07-03 08:44:32 +0200
commitb2d8910f3f60b50bf3fc359dfa37a4da2414cd2f (patch)
treef7771569179b78ead87386601024923f5ad22de2
parent7e10c3ff8149a8d25431807fe15a73fe40cfdc5b (diff)
downloadqtmips-b2d8910f3f60b50bf3fc359dfa37a4da2414cd2f.tar.gz
qtmips-b2d8910f3f60b50bf3fc359dfa37a4da2414cd2f.tar.bz2
qtmips-b2d8910f3f60b50bf3fc359dfa37a4da2414cd2f.zip
Allow spaces in middle of assembler arguments and report errors.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r--qtmips_gui/mainwindow.cpp9
-rw-r--r--qtmips_gui/programdock.cpp7
-rw-r--r--qtmips_gui/programdock.h1
-rw-r--r--qtmips_gui/programmodel.cpp7
-rw-r--r--qtmips_gui/programmodel.h2
-rw-r--r--qtmips_machine/instruction.cpp102
-rw-r--r--qtmips_machine/instruction.h4
7 files changed, 70 insertions, 62 deletions
diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp
index e3ad8dd..766a28c 100644
--- a/qtmips_gui/mainwindow.cpp
+++ b/qtmips_gui/mainwindow.cpp
@@ -620,6 +620,7 @@ void MainWindow::compile_source() {
int ln = 1;
for ( QTextBlock block = doc->begin(); block.isValid(); block = block.next(), ln++) {
+ QString error;
int pos;
QString label = "";
QString line = block.text();
@@ -641,7 +642,6 @@ void MainWindow::compile_source() {
QString op = line.split(" ").at(0).toUpper();
if (op == ".ORG") {
bool ok;
- QString error;
fixmatheval::FmeExpression expression;
fixmatheval::FmeValue value;
ok = expression.parse(line.mid(op.size()), error);
@@ -659,7 +659,6 @@ void MainWindow::compile_source() {
continue;
}
if (op == ".WORD") {
- QString error;
foreach (QString s, line.mid(op.size()).split(",")) {
s = s.simplified();
std::uint32_t val = 0;
@@ -677,14 +676,14 @@ void MainWindow::compile_source() {
}
std::uint32_t inst[2] = {0, 0};
- ssize_t size = machine::Instruction::code_from_string(inst, 8, line,
+ ssize_t size = machine::Instruction::code_from_string(inst, 8, line, error,
address, &reloc, ln, true);
if (size < 0) {
error_line = ln;
editor->setCursorToLine(error_line);
QMessageBox::critical(this, "QtMips Error",
- tr("line %1 instruction %2 parse error.")
- .arg(QString::number(ln), line));
+ tr("line %1 instruction %2 parse error - %3.")
+ .arg(QString::number(ln), line, error));
break;
}
std::uint32_t *p = inst;
diff --git a/qtmips_gui/programdock.cpp b/qtmips_gui/programdock.cpp
index c5f40d8..bcdbd23 100644
--- a/qtmips_gui/programdock.cpp
+++ b/qtmips_gui/programdock.cpp
@@ -39,6 +39,8 @@
#include <QTableView>
#include <QComboBox>
#include <QHeaderView>
+#include <QMessageBox>
+
#include "programdock.h"
#include "programmodel.h"
#include "programtableview.h"
@@ -103,6 +105,7 @@ ProgramDock::ProgramDock(QWidget *parent, QSettings *settings) : Super(parent) {
program_model, SLOT(toggle_hw_break(QModelIndex)));
connect(this, SIGNAL(stage_addr_changed(uint,std::uint32_t)),
program_model, SLOT(update_stage_addr(uint,std::uint32_t)));
+ connect(program_model, SIGNAL(report_error(QString)), this, SLOT(report_error(QString)));
}
void ProgramDock::setup(machine::QtMipsMachine *machine) {
@@ -166,3 +169,7 @@ void ProgramDock::update_follow_position() {
if (follow_source != FOLLOWSRC_NONE)
emit focus_addr(follow_addr[follow_source]);
}
+
+void ProgramDock::report_error(QString error) {
+ QMessageBox::critical(this, "QtMips Error", error);
+}
diff --git a/qtmips_gui/programdock.h b/qtmips_gui/programdock.h
index 0dec65d..50baa50 100644
--- a/qtmips_gui/programdock.h
+++ b/qtmips_gui/programdock.h
@@ -65,6 +65,7 @@ public slots:
void execute_inst_addr(std::uint32_t addr);
void memory_inst_addr(std::uint32_t addr);
void writeback_inst_addr(std::uint32_t addr);
+ void report_error(QString error);
private:
enum FollowSource {
FOLLOWSRC_NONE,
diff --git a/qtmips_gui/programmodel.cpp b/qtmips_gui/programmodel.cpp
index 0f3341f..b70ed34 100644
--- a/qtmips_gui/programmodel.cpp
+++ b/qtmips_gui/programmodel.cpp
@@ -256,6 +256,7 @@ bool ProgramModel::setData(const QModelIndex & index, const QVariant & value, in
if (role == Qt::EditRole)
{
bool ok;
+ QString error;
std::uint32_t address;
std::uint32_t data;
machine::MemoryAccess *mem;
@@ -274,8 +275,12 @@ bool ProgramModel::setData(const QModelIndex & index, const QVariant & value, in
mem->write_word(address, data);
break;
case 3:
- if (machine::Instruction::code_from_string(&data, 4, value.toString(), address) < 0)
+ if (machine::Instruction::code_from_string(&data, 4, value.toString(),
+ error, address) < 0) {
+ emit report_error(tr("instruction 1 parse error - %2.").arg(error));
+
return false;
+ }
mem->write_word(address, data);
break;
default:
diff --git a/qtmips_gui/programmodel.h b/qtmips_gui/programmodel.h
index a2eff4b..95d0e3f 100644
--- a/qtmips_gui/programmodel.h
+++ b/qtmips_gui/programmodel.h
@@ -93,6 +93,8 @@ public:
STAGEADDR_COUNT,
};
+signals:
+ void report_error(QString error);
public slots:
void setup(machine::QtMipsMachine *machine);
void check_for_updates();
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp
index b851461..49604ca 100644
--- a/qtmips_machine/instruction.cpp
+++ b/qtmips_machine/instruction.cpp
@@ -1071,10 +1071,11 @@ static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_a
#define CFS_OPTION_SILENT_MASK 0x100
ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
- QString inst_base, QVector<QString> &inst_fields,
+ QString inst_base, QStringList &inst_fields, QString &error,
std::uint32_t inst_addr, RelocExpressionList *reloc,
int line, bool pseudo_opt, int options)
{
+ const char *err = "unknown instruction";
if (str_to_instruction_code_map.isEmpty())
instruction_from_string_build_base();
@@ -1092,6 +1093,7 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
field = 0;
foreach (const QString &arg, im.args) {
if (field >= inst_fields.count()) {
+ err = "number of arguments does not match";
field = -1;
break;
}
@@ -1107,10 +1109,12 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
const ArgumentDesc *adesc = argdesbycode[a];
if (adesc == nullptr) {
if (!fl.count()) {
+ err = "empty argument encountered";
field = -1;
break;
}
if (fl.at(0) != ao) {
+ err = "argument does not match instruction template";
field = -1;
break;
}
@@ -1197,11 +1201,13 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
break;
}
if (chars_taken <= 0) {
+ err = "argument parse error";
field = -1;
break;
}
if ((val & ((1 << adesc->shift) - 1)) &&
!(options & CFS_OPTION_SILENT_MASK)) {
+ err = "low bits of argument has to be zero";
field = -1;
break;
}
@@ -1213,12 +1219,14 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
if (adesc->min < 0) {
if (((std::int64_t)val < adesc->min) ||
((std::int64_t)val > adesc->max)) {
+ err = "argument range exceed";
field = -1;
break;
}
} else {
if ((val < (std::uint64_t)adesc->min) ||
(val > (std::uint64_t)adesc->max)) {
+ err = "argument range exceed";
field = -1;
break;
}
@@ -1230,6 +1238,11 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
}
if (field == -1)
break;
+ if (fl.trimmed() != "") {
+ err = "excessive characters in argument";
+ field = -1;
+ break;
+ }
}
if (field != inst_fields.count())
continue;
@@ -1246,77 +1259,58 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
ret = 4;
} else if (pseudo_opt) {
if (((inst_base == "LA") || (inst_base == "LI")) && (inst_fields.size() == 2)) {
- if(code_from_string(code, buffsize, "LUI", inst_fields,
+ if(code_from_string(code, buffsize, "LUI", inst_fields, error,
inst_addr, reloc, line, false,
- CFS_OPTION_SILENT_MASK + 16) < 0)
+ CFS_OPTION_SILENT_MASK + 16) < 0) {
+ error = QString("error in LUI element of " + inst_base);
return -1;
+ }
inst_fields.insert(1, "$0");
- if (code_from_string(code + 1, buffsize - 4, "ORI", inst_fields,
+ if (code_from_string(code + 1, buffsize - 4, "ORI", inst_fields, error,
inst_addr + 4, reloc, line, false,
- CFS_OPTION_SILENT_MASK + 0) < 0)
+ CFS_OPTION_SILENT_MASK + 0) < 0) {
+ error = QString("error in ORI element of " + inst_base);
return -1;
+ }
return 8;
}
}
if (buffsize >= 4)
*code = inst_code;
+ if (ret < 0) {
+ error = err;
+ }
return ret;
}
ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
- QString str, std::uint32_t inst_addr,
+ QString str, QString &error, std::uint32_t inst_addr,
RelocExpressionList *reloc, int line, bool pseudo_opt, int options)
{
- 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;
- }
-
- 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;
- }
+ int k = 0, l;
+ while (k < str.count()) {
+ if (!str.at(k).isSpace())
+ break;
+ k++;
+ }
+ l = k;
+ while (l < str.count()) {
+ if (!str.at(l).isLetterOrNumber())
+ break;
+ l++;
+ }
+ QString inst_base = str.mid(k, l - k).toUpper();
+ str = str.mid(l + 1).trimmed();
+ QStringList inst_fields;
+ if (str.count())
+ inst_fields = str.split(",");
+
+ if (!inst_base.count()) {
+ error = "empty instruction field";
+ return -1;
}
- if (error)
- return -1;
-
- return code_from_string(code, buffsize, inst_base, inst_fields, inst_addr,
+ return code_from_string(code, buffsize, inst_base, inst_fields, error, inst_addr,
reloc, line, pseudo_opt, options);
}
diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h
index 101d82f..03b8f65 100644
--- a/qtmips_machine/instruction.h
+++ b/qtmips_machine/instruction.h
@@ -149,13 +149,13 @@ public:
QString to_str(std::int32_t inst_addr = 0) const;
static ssize_t code_from_string(std::uint32_t *code, size_t buffsize,
- QString inst_base, QVector<QString> &inst_fields,
+ QString inst_base, QStringList &inst_fields, QString &error,
std::uint32_t inst_addr = 0,
RelocExpressionList *reloc = nullptr,
int line = 0, bool pseudo_opt = false, int options = 0);
static ssize_t code_from_string(std::uint32_t *code, size_t buffsize,
- QString str, std::uint32_t inst_addr = 0,
+ QString str, QString &error, std::uint32_t inst_addr = 0,
RelocExpressionList *reloc = nullptr,
int line = 0, bool pseudo_opt = false, int options = 0);