diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-07-01 18:37:54 +0200 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-07-01 18:37:54 +0200 |
commit | b62686b24fbb65d0810475e24aba7a5c4ee3e05e (patch) | |
tree | 1071883f7f678d112126e6c934a4b9af4709619e | |
parent | 2db0208ed333e0bf232e396c1789085781f50d66 (diff) | |
download | qtmips-b62686b24fbb65d0810475e24aba7a5c4ee3e05e.tar.gz qtmips-b62686b24fbb65d0810475e24aba7a5c4ee3e05e.tar.bz2 qtmips-b62686b24fbb65d0810475e24aba7a5c4ee3e05e.zip |
Minimal prototype of integrated assembler.
The labels are parsed and stored into symbol table
but expressions dependent on symbols values are not evaluated.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r-- | qtmips_gui/MainWindow.ui | 15 | ||||
-rw-r--r-- | qtmips_gui/mainwindow.cpp | 57 | ||||
-rw-r--r-- | qtmips_gui/mainwindow.h | 2 | ||||
-rw-r--r-- | qtmips_gui/programmodel.cpp | 3 | ||||
-rw-r--r-- | qtmips_machine/instruction.cpp | 41 | ||||
-rw-r--r-- | qtmips_machine/instruction.h | 28 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.cpp | 19 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.h | 3 | ||||
-rw-r--r-- | qtmips_machine/symboltable.cpp | 9 | ||||
-rw-r--r-- | qtmips_machine/symboltable.h | 1 |
10 files changed, 171 insertions, 7 deletions
diff --git a/qtmips_gui/MainWindow.ui b/qtmips_gui/MainWindow.ui index 3202726..92fa695 100644 --- a/qtmips_gui/MainWindow.ui +++ b/qtmips_gui/MainWindow.ui @@ -101,6 +101,7 @@ <addaction name="separator"/> <addaction name="actionRestart"/> <addaction name="actionShow_Symbol"/> + <addaction name="actionCompileSource"/> </widget> <widget class="QMenu" name="menuHelp"> <property name="title"> @@ -239,6 +240,20 @@ <string>Ctrl+C</string> </property> </action> + <action name="actionCompileSource"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Compile Source</string> + </property> + <property name="toolTip"> + <string>Compile source and update memory</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + </action> <action name="actionExit"> <property name="icon"> <iconset resource="icons.qrc"> diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index 241a623..8a7956f 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -41,6 +41,8 @@ #include <QFile> #include <QFileInfo> #include <QMessageBox> +#include <QTextDocument> +#include <iostream> #include "mainwindow.h" #include "aboutdialog.h" @@ -107,6 +109,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { connect(ui->actionSave, SIGNAL(triggered(bool)), this, SLOT(save_source())); connect(ui->actionSaveAs, SIGNAL(triggered(bool)), this, SLOT(save_source_as())); connect(ui->actionClose, SIGNAL(triggered(bool)), this, SLOT(close_source())); + connect(ui->actionCompileSource, SIGNAL(triggered(bool)), this, SLOT(compile_source())); connect(ui->actionShow_Symbol, SIGNAL(triggered(bool)), this, SLOT(show_symbol_dialog())); connect(ui->actionRegisters, SIGNAL(triggered(bool)), this, SLOT(show_registers())); connect(ui->actionProgram_memory, SIGNAL(triggered(bool)), this, SLOT(show_program())); @@ -458,10 +461,12 @@ void MainWindow::setCurrentSrcEditor(SrcEditor *srceditor) { ui->actionSave->setEnabled(false); ui->actionSaveAs->setEnabled(false); ui->actionClose->setEnabled(false); + ui->actionCompileSource->setEnabled(false); } else { ui->actionSave->setEnabled(true); ui->actionSaveAs->setEnabled(true); ui->actionClose->setEnabled(true); + ui->actionCompileSource->setEnabled(true); } } @@ -540,3 +545,55 @@ void MainWindow::close_source() { central_window->removeTab(idx); delete editor; } + +void MainWindow::compile_source() { + if (current_srceditor == nullptr) + return; + if (machine == nullptr) { + QMessageBox::critical(this, "QtMips Error", tr("No machine to store program.")); + return; + } + machine::MemoryAccess *mem = machine->physical_address_space_rw(); + if (mem == nullptr) { + QMessageBox::critical(this, "QtMips Error", tr("No physical addresspace to store program.")); + return; + } + machine->cache_sync(); + SrcEditor *editor = current_srceditor; + QTextDocument *doc = editor->document(); + std::uint32_t address = 0x80020000; + machine::RelocExpressionList reloc; + + int ln = 1; + bool ok; + for ( QTextBlock block = doc->begin(); block.isValid(); block = block.next(), ln++) { + 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); + 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); + } + machine::Instruction inst; + inst = machine::Instruction::from_string(line, &ok, address, &reloc); + mem->write_word(address, inst.data()); + address += 4; + } + foreach(machine::RelocExpression *r, reloc) { + QString e = r->expression; + + + delete r; + } + + emit mem->external_change_notify(mem, 0, 0xffffffff, true); +} diff --git a/qtmips_gui/mainwindow.h b/qtmips_gui/mainwindow.h index b051309..f75d31e 100644 --- a/qtmips_gui/mainwindow.h +++ b/qtmips_gui/mainwindow.h @@ -77,6 +77,7 @@ public slots: void save_source(); void save_source_as(); void close_source(); + void compile_source(); void show_registers(); void show_program(); void show_memory(); @@ -124,7 +125,6 @@ private: bool coreview_shown; SrcEditor *current_srceditor; - QActionGroup *speed_group; QSettings *settings; diff --git a/qtmips_gui/programmodel.cpp b/qtmips_gui/programmodel.cpp index 9098ab1..64dffb8 100644 --- a/qtmips_gui/programmodel.cpp +++ b/qtmips_gui/programmodel.cpp @@ -176,6 +176,9 @@ void ProgramModel::setup(machine::QtMipsMachine *machine) { stage_addr[i] = machine::STAGEADDR_NONE; if (machine != nullptr) connect(machine, SIGNAL(post_tick()), this, SLOT(check_for_updates())); + if (mem_access() != nullptr) + connect(mem_access(), SIGNAL(external_change_notify(const MemoryAccess*,std::uint32_t,std::uint32_t,bool)), + this, SLOT(check_for_updates())); emit update_all(); } diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index d210ad9..d7ff37a 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -1039,7 +1039,34 @@ static int parse_reg_from_string(QString str, uint *chars_taken = nullptr) return res; } -Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr) { +static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_addr, + std::int64_t offset, const ArgumentDesc *adesc, uint *chars_taken = nullptr) { + uint bits = IMF_SUB_GET_BITS(adesc->loc); + uint shift = IMF_SUB_GET_SHIFT(adesc->loc); + QString expression = ""; + QString allowed_operators = "+-/*"; + int i = 0; + for (; i < fl.size(); i++) { + QChar ch = fl.at(i); + if (ch.isSpace()) + continue; + if (ch.isLetterOrNumber()) + expression.append(ch); + else if (allowed_operators.indexOf(ch) >= 0) + expression.append(ch); + else + break; + } + + reloc->append(new RelocExpression(inst_addr, expression, offset, + adesc->min, adesc->max, shift, bits, adesc->shift)); + if (chars_taken != nullptr) { + *chars_taken = i; + } +} + +Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr, + RelocExpressionList *reloc) { std::uint32_t code; bool ok = false; @@ -1151,7 +1178,7 @@ Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr) FALLTROUGH case 'o': case 'n': - { + if(fl.at(0).isDigit() || (reloc == nullptr)) { int i; // Qt functions are limited, toLongLong would be usable // but does not return information how many characters @@ -1167,20 +1194,26 @@ Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr) else val += std::strtoull(p, &r, 0); chars_taken = r - p; + } else { + reloc_append(reloc, fl, val, inst_addr, adesc, &chars_taken); + val = 0; } break; case 'a': - { + val -= (inst_addr + 4) & 0xf0000000; + if(fl.at(0).isDigit() || (reloc == nullptr)) { int i; char cstr[fl.count() + 1]; for (i = 0; i < fl.count(); i++) cstr[i] = fl.at(i).toLatin1(); cstr[i] = 0; p = cstr; - val -= (inst_addr + 4) & 0xf0000000; val += std::strtoull(p, &r, 0); chars_taken = r - p; break; + } else { + reloc_append(reloc, fl, val, inst_addr, adesc, &chars_taken); + val = 0; } } if (chars_taken <= 0) { diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index f86d10c..f721835 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -38,6 +38,7 @@ #include <QObject> #include <QString> +#include <QVector> #include "machinedefs.h" @@ -74,6 +75,30 @@ enum InstructionFlags { IMF_STOP_IF = 1L<<23, /**< Stop instruction fetch until instruction processed */ }; +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) { + this->location = location; + this->expression = expression; + this->offset = offset; + this->min = min; + this->max = max; + this->lsb_bit = lsb_bit; + this->bits = bits; + this->shift = shift; + } + 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; +}; + +typedef QVector<RelocExpression *> RelocExpressionList; + class Instruction { public: Instruction(); @@ -117,7 +142,8 @@ 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); + static Instruction from_string(QString str, bool *pok = nullptr, + std::uint32_t inst_addr = 0, RelocExpressionList *reloc = nullptr); private: std::uint32_t dt; }; diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index 8299ddf..68eeeca 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -186,7 +186,15 @@ Cache *QtMipsMachine::cache_data_rw() { return cch_data; } -const PhysAddrSpace *QtMipsMachine::physical_address_space() { +void QtMipsMachine::cache_sync() { + if (cch_program != nullptr) + cch_program->sync(); + if (cch_data != nullptr) + cch_data->sync(); +} + + +const PhysAddrSpace *QtMipsMachine::physical_address_space() { return physaddrspace; } @@ -210,6 +218,15 @@ const SymbolTable *QtMipsMachine::symbol_table() { return symtab; } +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); +} + const Core *QtMipsMachine::core() { return cr; } diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index 03cdad9..ef96e09 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -70,12 +70,15 @@ public: const Cache *cache_program(); const Cache *cache_data(); Cache *cache_data_rw(); + void cache_sync(); const PhysAddrSpace *physical_address_space(); PhysAddrSpace *physical_address_space_rw(); SerialPort *serial_port(); PeripSpiLed *peripheral_spi_led(); LcdDisplay *peripheral_lcd_display(); const SymbolTable *symbol_table(); + void set_symbol(QString name, std::uint32_t value, std::uint32_t size, + unsigned char info = 0, unsigned char other = 0); const Core *core(); const CoreSingle *core_singe(); const CorePipelined *core_pipelined(); diff --git a/qtmips_machine/symboltable.cpp b/qtmips_machine/symboltable.cpp index f22acaa..d26491f 100644 --- a/qtmips_machine/symboltable.cpp +++ b/qtmips_machine/symboltable.cpp @@ -66,6 +66,15 @@ void SymbolTable::add_symbol(QString name, std::uint32_t value, std::uint32_t si map_name_to_symbol.insert(name, p_ste); } +void SymbolTable::remove_symbol(QString name) { + SymbolTableEntry *p_ste = map_name_to_symbol.value(name); + if (p_ste == nullptr) + return; + map_name_to_symbol.remove(name); + map_value_to_symbol.remove(p_ste->value, p_ste); + delete p_ste; +} + 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 174917c..0c33ac3 100644 --- a/qtmips_machine/symboltable.h +++ b/qtmips_machine/symboltable.h @@ -65,6 +65,7 @@ public: void add_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: bool name_to_value(std::uint32_t &value, QString name) const; |