diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-07-17 19:48:43 +0200 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-07-17 19:48:43 +0200 |
commit | 139dcf818566f9f2a48d95cdab9ad9e2ac7c7978 (patch) | |
tree | 2003660ee71cd5df7e830ca8084c8e3ea8f6ab96 | |
parent | da53e0174a90636c2a9469ef63b0aaa981f7bae3 (diff) | |
download | qtmips-139dcf818566f9f2a48d95cdab9ad9e2ac7c7978.tar.gz qtmips-139dcf818566f9f2a48d95cdab9ad9e2ac7c7978.tar.bz2 qtmips-139dcf818566f9f2a48d95cdab9ad9e2ac7c7978.zip |
Simple assembler moved to separate class which is independent on Qt GUI API.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r-- | qtmips_asm/qtmips_asm.pro | 9 | ||||
-rw-r--r-- | qtmips_asm/simpleasm.cpp | 285 | ||||
-rw-r--r-- | qtmips_asm/simpleasm.h | 83 | ||||
-rw-r--r-- | qtmips_gui/mainwindow.cpp | 208 | ||||
-rw-r--r-- | qtmips_machine/instruction.cpp | 19 | ||||
-rw-r--r-- | qtmips_machine/instruction.h | 10 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.cpp | 10 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.h | 1 | ||||
-rw-r--r-- | qtmips_machine/symboltable.cpp | 6 | ||||
-rw-r--r-- | qtmips_machine/symboltable.h | 2 |
10 files changed, 420 insertions, 213 deletions
diff --git a/qtmips_asm/qtmips_asm.pro b/qtmips_asm/qtmips_asm.pro index d096961..ed42c10 100644 --- a/qtmips_asm/qtmips_asm.pro +++ b/qtmips_asm/qtmips_asm.pro @@ -6,6 +6,9 @@ CONFIG += c++11 TEMPLATE = lib CONFIG += staticlib +INCLUDEPATH += $$PWD/../qtmips_machine $$PWD/../qtmips_osemu +DEPENDPATH += $$PWD/../qtmips_machine + LIBS += -lelf QMAKE_CXXFLAGS += -std=c++0x QMAKE_CXXFLAGS_DEBUG += -ggdb @@ -14,8 +17,10 @@ DEFINES += QTMIPS_MACHINE_LIBRARY DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ - fixmatheval.cpp + fixmatheval.cpp \ + simpleasm.cpp HEADERS += \ fixmatheval.h \ - messagetype.h + messagetype.h \ + simpleasm.h diff --git a/qtmips_asm/simpleasm.cpp b/qtmips_asm/simpleasm.cpp new file mode 100644 index 0000000..15d50b2 --- /dev/null +++ b/qtmips_asm/simpleasm.cpp @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz> + * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#include <QObject> + +#include "simpleasm.h" + +using namespace fixmatheval; + + +SymbolTableDb::SymbolTableDb(machine::SymbolTable *symtab) { + this->symtab = symtab; +} + +bool SymbolTableDb::getValue(fixmatheval::FmeValue &value, QString name) { + std::uint32_t val; + if (!symtab->name_to_value(val, name)) + return false; + value = val; + return true; +} + +void SymbolTableDb::setSymbol(QString name, std::uint32_t value, std::uint32_t size, + unsigned char info, unsigned char other) { + symtab->set_symbol(name, value, size, info, other); +} + + +std::uint64_t SimpleAsm::string_to_uint64(QString str, int base, + int *chars_taken) { + int i; + std::int64_t val; + char *p, *r; + char cstr[str.count() + 1]; + for (i = 0; i < str.count(); i++) + cstr[i] = str.at(i).toLatin1(); + cstr[i] = 0; + p = cstr; + val = std::strtoll(p, &r, base); + if (chars_taken != nullptr) + *chars_taken = r - p; + return val; +} + +SimpleAsm::SimpleAsm(QObject *parent) : Super(parent) { + clear(); +} + +SimpleAsm::~SimpleAsm() { + clear(); +} + +void SimpleAsm::clear() { + symtab = nullptr; + mem = nullptr; + while (!reloc.isEmpty()) { + delete reloc.takeFirst(); + } + error_occured = false; + fatal_occured = false; +} + +void SimpleAsm::setup(machine::MemoryAccess *mem, SymbolTableDb *symtab, + std::uint32_t address) { + this->mem = mem; + this->symtab = symtab; + this->address = address; +} + +bool SimpleAsm::process_line(QString line, QString filename, + int line_number, QString *error_ptr) { + QString error; + int pos; + QString label = ""; + pos = line.indexOf("#"); + if (pos >= 0) + line.truncate(pos); + pos = line.indexOf(";"); + if (pos >= 0) + line.truncate(pos); + pos = line.indexOf("//"); + if (pos >= 0) + line.truncate(pos); + line = line.simplified(); + pos = line.indexOf(":"); + if (pos >= 0) { + label = line.mid(0, pos); + line = line.mid(pos + 1).trimmed(); + symtab->setSymbol(label, address, 4); + } + if (line.isEmpty()) + return true; + int k = 0, l; + while (k < line.count()) { + if (!line.at(k).isSpace()) + break; + k++; + } + l = k; + while (l < line.count()) { + if (!line.at(l).isLetterOrNumber() && !(line.at(l) == '.')) + break; + l++; + } + QString op = line.mid(k, l - k).toUpper(); + if ((op == ".DATA") || (op == ".TEXT") || + (op == ".GLOBL") || (op == ".END") || + (op == ".ENT")) { + return true; + } + if (op == ".ORG") { + bool ok; + fixmatheval::FmeExpression expression; + fixmatheval::FmeValue value; + ok = expression.parse(line.mid(op.size()), error); + if (ok) + ok = expression.eval(value, symtab, error); + if (!ok) { + error = tr("line %1 .orig %2 parse error.") + .arg(QString::number(line_number), line); + emit report_message(messagetype::ERROR, filename, line_number, 0, error, ""); + error_occured = true; + fatal_occured = true; + if (error_ptr != nullptr) + *error_ptr = error; + return false; + } + address = value; + return true; + } + if ((op == ".EQU") || (op == ".SET")) { + QStringList operands = line.mid(op.size()).split(","); + if ((operands.count() > 2) || (operands.count() < 1)) { + error = tr("line %1 .set or .equ incorrect arguments number.") + .arg(QString::number(line_number)); + emit report_message(messagetype::ERROR, filename, line_number, 0, error, ""); + error_occured = true; + if (error_ptr != nullptr) + *error_ptr = error; + return false; + } + QString name = operands.at(0).trimmed(); + if ((name == "noat") || (name == "noreored")) + return true; + bool ok; + fixmatheval::FmeValue value = 1; + if (operands.count() > 1) { + fixmatheval::FmeExpression expression; + ok = expression.parse(operands.at(1), error); + if (ok) + ok = expression.eval(value, symtab, error); + if (!ok) { + error = tr("line %1 .set or .equ %2 parse error.") + .arg(QString::number(line_number), operands.at(1)); + emit report_message(messagetype::ERROR, filename, line_number, 0, error, ""); + error_occured = true; + if (error_ptr != nullptr) + *error_ptr = error; + return false; + } + } + symtab->setSymbol(name, value, 0); + return true; + } + if (op == ".WORD") { + foreach (QString s, line.mid(op.size()).split(",")) { + s = s.simplified(); + std::uint32_t val = 0; + int chars_taken; + val = string_to_uint64(s, 0, &chars_taken); + if (chars_taken != s.size()) { + val = 0; + reloc.append(new machine::RelocExpression(address, s, 0, + -0xffffffff, 0xffffffff, 0, 32, 0, filename, line_number, 0)); + } + if (fatal_occured) + mem->write_word(address, val); + address += 4; + } + return true; + } + + std::uint32_t inst[2] = {0, 0}; + ssize_t size = machine::Instruction::code_from_string(inst, 8, line, error, + address, &reloc, filename, line_number, true); + if (size < 0) { + error = tr("line %1 instruction %2 parse error - %3.") + .arg(QString::number(line_number), line, error); + emit report_message(messagetype::ERROR, filename, line_number, 0, error, ""); + error_occured = true; + if (error_ptr != nullptr) + *error_ptr = error; + return false; + } + std::uint32_t *p = inst; + for (ssize_t l = 0; l < size; l += 4) { + if (!fatal_occured) + mem->write_word(address, *(p++)); + address += 4; + } + return true; +} + +bool SimpleAsm::finish(QString *error_ptr) { + bool error_reported = false; + foreach(machine::RelocExpression *r, reloc) { + QString error; + fixmatheval::FmeExpression expression; + if (!expression.parse(r->expression, error)) { + error = tr("expression parse error %1 at line %2, expression %3.") + .arg(error, QString::number(r->line), expression.dump()); + emit report_message(messagetype::ERROR, r->filename, r->line, 0, error, ""); + if (error_ptr != nullptr && !error_reported) + *error_ptr = error; + error_occured = true; + error_reported = true; + } else { + fixmatheval::FmeValue value; + if (!expression.eval(value, symtab, error)) { + error = tr("expression evalution error %1 at line %2 , expression %3.") + .arg(error, QString::number(r->line), expression.dump()); + emit report_message(messagetype::ERROR, r->filename, r->line, 0, error, ""); + if (error_ptr != nullptr && !error_reported) + *error_ptr = error; + error_occured = true; + error_reported = true; + } else { + if (false) + emit report_message(messagetype::INFO, r->filename, r->line, 0, + expression.dump() + " -> " + QString::number(value), ""); + machine::Instruction inst(mem->read_word(r->location, true)); + if (!inst.update(value, r)) { + error = tr("instruction update error %1 at line %2, expression %3 -> value %4.") + .arg(error, QString::number(r->line), expression.dump(), QString::number(value)); + emit report_message(messagetype::ERROR, r->filename, r->line, 0, error, ""); + if (error_ptr != nullptr && !error_reported) + *error_ptr = error; + error_occured = true; + error_reported = true; + } + if (!fatal_occured) + mem->write_word(r->location, inst.data()); + } + } + } + while (!reloc.isEmpty()) { + delete reloc.takeFirst(); + } + + emit mem->external_change_notify(mem, 0, 0xffffffff, true); + + return !error_occured; +} diff --git a/qtmips_asm/simpleasm.h b/qtmips_asm/simpleasm.h new file mode 100644 index 0000000..773aa39 --- /dev/null +++ b/qtmips_asm/simpleasm.h @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz> + * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#ifndef SIMPLEASM_H +#define SIMPLEASM_H + +#include <QString> +#include "fixmatheval.h" +#include "qtmipsmachine.h" +#include "messagetype.h" + +class SymbolTableDb : public fixmatheval::FmeSymbolDb { +public: + SymbolTableDb(machine::SymbolTable *symtab); + virtual bool getValue(fixmatheval::FmeValue &value, QString name) override; + void setSymbol(QString name, std::uint32_t value, std::uint32_t size, + unsigned char info = 0, unsigned char other = 0); +private: + machine::SymbolTable *symtab; +}; + +class SimpleAsm : public QObject { + Q_OBJECT + + using Super = QObject; + +signals: + void report_message(messagetype::Type type, QString file, int line, + int column, QString text, QString hint); + +public: + SimpleAsm(QObject *parent = nullptr); + ~SimpleAsm(); +public: + static std::uint64_t string_to_uint64(QString str, int base, + int *chars_taken = nullptr); + void clear(); + void setup(machine::MemoryAccess *mem, SymbolTableDb *symtab, std::uint32_t address); + bool process_line(QString line, QString filename = "", + int line_number = 0, QString *error_ptr = nullptr); + bool finish(QString *error_ptr = nullptr); +private: + bool error_occured; + bool fatal_occured; + SymbolTableDb *symtab; + machine::MemoryAccess *mem; + machine::RelocExpressionList reloc; + std::uint32_t address; +}; + +#endif /*SIMPLEASM_H*/ diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index 0498ff3..87549d2 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -50,6 +50,7 @@ #include "fontsize.h" #include "gotosymboldialog.h" #include "fixmatheval.h" +#include "simpleasm.h" #ifdef __EMSCRIPTEN__ #include <QFileInfo> @@ -691,45 +692,9 @@ void MainWindow::message_selected(messagetype::Type type, QString file, int line central_window->setCurrentWidget(editor); } -class SymbolTableDb : public fixmatheval::FmeSymbolDb { -public: - SymbolTableDb(const machine::SymbolTable *symtab); - virtual bool getValue(fixmatheval::FmeValue &value, QString name) override; -private: - const machine::SymbolTable *symtab; -}; - -SymbolTableDb::SymbolTableDb(const machine::SymbolTable *symtab) { - this->symtab = symtab; -} - -bool SymbolTableDb::getValue(fixmatheval::FmeValue &value, QString name) { - std::uint32_t val; - if (!symtab->name_to_value(val, name)) - return false; - value = val; - return true; -} - -static std::uint64_t string_to_uint64(QString str, int base, - int *chars_taken = nullptr) { - int i; - std::int64_t val; - char *p, *r; - char cstr[str.count() + 1]; - for (i = 0; i < str.count(); i++) - cstr[i] = str.at(i).toLatin1(); - cstr[i] = 0; - p = cstr; - val = std::strtoll(p, &r, base); - if (chars_taken != nullptr) - *chars_taken = r - p; - return val; -} - void MainWindow::compile_source() { - SymbolTableDb symtab(machine->symbol_table(true)); - int error_line = 0; + SymbolTableDb symtab(machine->symbol_table_rw(true)); + bool error_occured; if (current_srceditor == nullptr) return; if (machine == nullptr) { @@ -745,169 +710,24 @@ void MainWindow::compile_source() { machine->cache_sync(); SrcEditor *editor = current_srceditor; QTextDocument *doc = editor->document(); - std::uint32_t address = 0x80020000; - machine::RelocExpressionList reloc; emit clear_messages(); + SimpleAsm sasm; + + connect(&sasm, SIGNAL(report_message(messagetype::Type,QString,int,int,QString,QString)), + this, SIGNAL(report_message(messagetype::Type,QString,int,int,QString,QString))); + + sasm.setup(mem, &symtab, 0x80020000); int ln = 1; for ( QTextBlock block = doc->begin(); block.isValid(); block = block.next(), ln++) { - QString error; - int pos; - QString label = ""; QString line = block.text(); - pos = line.indexOf("#"); - if (pos >= 0) - line.truncate(pos); - pos = line.indexOf(";"); - if (pos >= 0) - line.truncate(pos); - pos = line.indexOf("//"); - if (pos >= 0) - line.truncate(pos); - line = line.simplified(); - pos = line.indexOf(":"); - if (pos >= 0) { - label = line.mid(0, pos); - line = line.mid(pos + 1).trimmed(); - machine->set_symbol(label, address, 4); - } - if (line.isEmpty()) - continue; - int k = 0, l; - while (k < line.count()) { - if (!line.at(k).isSpace()) - break; - k++; - } - l = k; - while (l < line.count()) { - if (!line.at(l).isLetterOrNumber() && !(line.at(l) == '.')) - break; - l++; - } - QString op = line.mid(k, l - k).toUpper(); - if ((op == ".DATA") || (op == ".TEXT") || - (op == ".GLOBL") || (op == ".END") || - (op == ".ENT")) { - continue; - } - if (op == ".ORG") { - bool ok; - fixmatheval::FmeExpression expression; - fixmatheval::FmeValue value; - ok = expression.parse(line.mid(op.size()), error); - if (ok) - ok = expression.eval(value, &symtab, error); - if (!ok) { - error_line = ln; - emit report_message(messagetype::ERROR, filename, ln, 0, - tr("line %1 .orig %2 parse error.") - .arg(QString::number(ln), line), ""); - break; - } - address = value; - continue; - } - if ((op == ".EQU") || (op == ".SET")) { - QStringList operands = line.mid(op.size()).split(","); - if ((operands.count() > 2) || (operands.count() < 1)) { - error_line = ln; - emit report_message(messagetype::ERROR, filename, ln, 0, - tr("line %1 .set or .equ incorrect arguments number.") - .arg(QString::number(ln)), ""); - continue; - } - QString name = operands.at(0).trimmed(); - if ((name == "noat") || (name == "noreored")) - continue; - bool ok; - fixmatheval::FmeValue value = 1; - if (operands.count() > 1) { - fixmatheval::FmeExpression expression; - ok = expression.parse(operands.at(1), error); - if (ok) - ok = expression.eval(value, &symtab, error); - if (!ok) { - error_line = ln; - emit report_message(messagetype::ERROR, filename, ln, 0, - tr("line %1 .set or .equ %2 parse error.") - .arg(QString::number(ln), operands.at(1)), ""); - continue; - } - } - machine->set_symbol(name, value, 0); - continue; - } - if (op == ".WORD") { - foreach (QString s, line.mid(op.size()).split(",")) { - s = s.simplified(); - std::uint32_t val = 0; - int chars_taken; - val = string_to_uint64(s, 0, &chars_taken); - if (chars_taken != s.size()) { - val = 0; - reloc.append(new machine::RelocExpression(address, s, 0, - -0xffffffff, 0xffffffff, 0, 32, 0, ln, 0)); - } - mem->write_word(address, val); - address += 4; - } - continue; - } - - std::uint32_t inst[2] = {0, 0}; - ssize_t size = machine::Instruction::code_from_string(inst, 8, line, error, - address, &reloc, ln, true); - if (size < 0) { - error_line = ln; - emit report_message(messagetype::ERROR, filename, ln, 0, - tr("line %1 instruction %2 parse error - %3.") - .arg(QString::number(ln), line, error), ""); - continue; - } - std::uint32_t *p = inst; - for (ssize_t l = 0; l < size; l += 4) { - mem->write_word(address, *(p++)); - address += 4; - } + if (!sasm.process_line(line, filename, ln)) + error_occured = true; } - foreach(machine::RelocExpression *r, reloc) { - QString error; - fixmatheval::FmeExpression expression; - if (!expression.parse(r->expression, error)) { - error_line = r->line; - emit report_message(messagetype::ERROR, filename, ln, 0, - tr("expression parse error %1 at line %2, expression %3.") - .arg(error, QString::number(r->line), expression.dump()), ""); - } else { - fixmatheval::FmeValue value; - if (!expression.eval(value, &symtab, error)) { - error_line = r->line; - emit report_message(messagetype::ERROR, filename, ln, 0, - tr("expression evalution error %1 at line %2 , expression %3.") - .arg(error, QString::number(r->line), expression.dump()), ""); - } else { - if (false) - emit report_message(messagetype::INFO, filename, ln, 0, - expression.dump() + " -> " + QString::number(value), ""); - machine::Instruction inst(mem->read_word(r->location, true)); - if (!inst.update(value, r)) { - error_line = r->line; - emit report_message(messagetype::ERROR, filename, ln, 0, - tr("instruction update error %1 at line %2, expression %3 -> value %4.") - .arg(error, QString::number(r->line), expression.dump(), QString::number(value)), ""); - } - mem->write_word(r->location, inst.data()); - } - } - } - while (!reloc.isEmpty()) { - delete reloc.takeFirst(); - } - - emit mem->external_change_notify(mem, 0, 0xffffffff, true); + if (!sasm.finish()) + error_occured = true; - if (error_line != 0) + if (error_occured) show_messages(); } diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index b30901f..547c666 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -1111,7 +1111,7 @@ static int parse_reg_from_string(QString str, uint *chars_taken = nullptr) static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_addr, std::int64_t offset, const ArgumentDesc *adesc, uint *chars_taken = nullptr, - int line = 0, int options = 0) { + QString filename = "", int line = 0, int options = 0) { uint bits = IMF_SUB_GET_BITS(adesc->loc); uint shift = IMF_SUB_GET_SHIFT(adesc->loc); QString expression = ""; @@ -1130,7 +1130,7 @@ static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_a } reloc->append(new RelocExpression(inst_addr, expression, offset, - adesc->min, adesc->max, shift, bits, adesc->shift, line, options)); + adesc->min, adesc->max, shift, bits, adesc->shift, filename, line, options)); if (chars_taken != nullptr) { *chars_taken = i; } @@ -1141,7 +1141,7 @@ static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_a ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, QString inst_base, QStringList &inst_fields, QString &error, std::uint32_t inst_addr, RelocExpressionList *reloc, - int line, bool pseudo_opt, int options) + QString filename, int line, bool pseudo_opt, int options) { const char *err = "unknown instruction"; if (str_to_instruction_code_map.isEmpty()) @@ -1236,7 +1236,7 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, need_reloc = true; } if (need_reloc && (reloc != nullptr)) { - reloc_append(reloc, fl, inst_addr, val, adesc, &chars_taken, line, options); + reloc_append(reloc, fl, inst_addr, val, adesc, &chars_taken, filename, line, options); val = 0; } break; @@ -1263,7 +1263,7 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, need_reloc = true; } if (need_reloc && (reloc != nullptr)) { - reloc_append(reloc, fl, inst_addr, val, adesc, &chars_taken, line, options); + reloc_append(reloc, fl, inst_addr, val, adesc, &chars_taken, filename, line, options); val = 0; } break; @@ -1328,14 +1328,14 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, } else if (pseudo_opt) { if (((inst_base == "LA") || (inst_base == "LI")) && (inst_fields.size() == 2)) { if(code_from_string(code, buffsize, "LUI", inst_fields, error, - inst_addr, reloc, line, false, + inst_addr, reloc, filename, line, false, CFS_OPTION_SILENT_MASK + 16) < 0) { error = QString("error in LUI element of " + inst_base); return -1; } inst_fields.insert(1, inst_fields.at(0)); if (code_from_string(code + 1, buffsize - 4, "ORI", inst_fields, error, - inst_addr + 4, reloc, line, false, + inst_addr + 4, reloc, filename, line, false, CFS_OPTION_SILENT_MASK + 0) < 0) { error = QString("error in ORI element of " + inst_base); return -1; @@ -1353,7 +1353,8 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, QString str, QString &error, std::uint32_t inst_addr, - RelocExpressionList *reloc, int line, bool pseudo_opt, int options) + RelocExpressionList *reloc, QString filename, int line, + bool pseudo_opt, int options) { int k = 0, l; while (k < str.count()) { @@ -1379,7 +1380,7 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize, } return code_from_string(code, buffsize, inst_base, inst_fields, error, inst_addr, - reloc, line, pseudo_opt, options); + reloc, filename, line, pseudo_opt, options); } bool Instruction::update(std::int64_t val, RelocExpression *relocexp) { diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index b07a0e8..2ecd0c4 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -78,8 +78,8 @@ enum InstructionFlags { struct RelocExpression { inline RelocExpression(std::int32_t location, QString expression, std::int64_t offset, std::int64_t min, - std::int64_t max, unsigned lsb_bit, unsigned bits, unsigned shift, int line, - int options) { + std::int64_t max, unsigned lsb_bit, unsigned bits, unsigned shift, + QString filename, int line, int options) { this->location = location; this->expression = expression; this->offset = offset; @@ -88,6 +88,7 @@ struct RelocExpression { this->lsb_bit = lsb_bit; this->bits = bits; this->shift = shift; + this->filename = filename; this->line = line; this->options = options; } @@ -99,6 +100,7 @@ struct RelocExpression { unsigned lsb_bit; unsigned bits; unsigned shift; + QString filename; int line; int options; }; @@ -152,11 +154,11 @@ public: 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); + QString filename = "", 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, QString &error, std::uint32_t inst_addr = 0, - RelocExpressionList *reloc = nullptr, + RelocExpressionList *reloc = nullptr, QString filename = "", int line = 0, bool pseudo_opt = false, int options = 0); bool update(std::int64_t val, RelocExpression *relocexp); diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index e838429..b726bba 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -193,7 +193,6 @@ void QtMipsMachine::cache_sync() { cch_data->sync(); } - const PhysAddrSpace *QtMipsMachine::physical_address_space() { return physaddrspace; } @@ -214,19 +213,22 @@ LcdDisplay *QtMipsMachine::peripheral_lcd_display() { return perip_lcd_display; } -const SymbolTable *QtMipsMachine::symbol_table(bool create) { +SymbolTable *QtMipsMachine::symbol_table_rw(bool create) { if (create && (symtab == nullptr)) symtab = new SymbolTable; return symtab; } +const SymbolTable *QtMipsMachine::symbol_table(bool create) { + return symbol_table_rw(create); +} + void QtMipsMachine::set_symbol(QString name, std::uint32_t value, std::uint32_t size, unsigned char info, unsigned char other) { if (symtab == nullptr) symtab = new SymbolTable; - symtab->remove_symbol(name); - symtab->add_symbol(name, value, size, info, other); + symtab->set_symbol(name, value, size, info, other); } const Core *QtMipsMachine::core() { diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index e5bbdb3..7092ec3 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -77,6 +77,7 @@ public: PeripSpiLed *peripheral_spi_led(); LcdDisplay *peripheral_lcd_display(); const SymbolTable *symbol_table(bool create = false); + SymbolTable *symbol_table_rw(bool create = false); void set_symbol(QString name, std::uint32_t value, std::uint32_t size, unsigned char info = 0, unsigned char other = 0); const Core *core(); diff --git a/qtmips_machine/symboltable.cpp b/qtmips_machine/symboltable.cpp index d26491f..987b35f 100644 --- a/qtmips_machine/symboltable.cpp +++ b/qtmips_machine/symboltable.cpp @@ -75,6 +75,12 @@ void SymbolTable::remove_symbol(QString name) { delete p_ste; } +void SymbolTable::set_symbol(QString name, std::uint32_t value, std::uint32_t size, + unsigned char info, unsigned char other) { + remove_symbol(name); + add_symbol(name, value, size, info, other); +} + bool SymbolTable::name_to_value(std::uint32_t &value, QString name) const { SymbolTableEntry *p_ste = map_name_to_symbol.value(name); if (p_ste == nullptr) { diff --git a/qtmips_machine/symboltable.h b/qtmips_machine/symboltable.h index 0c33ac3..ece92a9 100644 --- a/qtmips_machine/symboltable.h +++ b/qtmips_machine/symboltable.h @@ -65,6 +65,8 @@ public: void add_symbol(QString name, std::uint32_t value, std::uint32_t size, unsigned char info = 0, unsigned char other = 0); + void set_symbol(QString name, std::uint32_t value, std::uint32_t size, + unsigned char info = 0, unsigned char other = 0); void remove_symbol(QString name); QStringList *names() const; public slots: |