[Assembler] Implement assembling of immediate values
MODIFY
src/assembler/assembler.h
src/assembler/assembler.h
@@ -200,7 +200,7 @@ private:
runOperation(directiveBytes, std::optional<QByteArray>, assembleDirective, line);
if (!directiveBytes) {
runOperation(machineCode, uint32_t, assembleInstruction, line);
- program.append(QByteArray::number(machineCode));
+ program.append(QByteArray(reinterpret_cast<char*>(&machineCode), sizeof(machineCode)));
} else {
program.append(directiveBytes.value());
}

MODIFY
src/assembler/instruction.h
src/assembler/instruction.h
#include <memory>
#include <type_traits>
#include <vector>
+#include "binutils.h"
#include "math.h"
namespace Ripes {
@@ -145,7 +146,32 @@ struct Imm : public Field {
std::optional<AssemblerTmp::Error> apply(const AssemblerTmp::TokenizedSrcLine& line,
uint32_t& instruction) const override {
- // @Todo: decode immediate from token (appropriate bit width!), apply each ImmPart with immediate to instruction
+ bool success;
+ const QString& immToken = line.tokens[tokenIndex];
+
+ // Accept base 10, 16 and 2
+ uint32_t value;
+ value = immToken.toUInt(&success, 10);
+ if (!success && immToken.toUpper().startsWith(QStringLiteral("0X"))) {
+ value = immToken.toUInt(&success, 16);
+ }
+ if (!success && immToken.toUpper().startsWith(QStringLiteral("0B"))) {
+ value = immToken.toUInt(&success, 2);
+ }
+
+ if (!success) {
+ return AssemblerTmp::Error(line.sourceLine, "Malformed immediate value '" + immToken + "'");
+ }
+
+ if (!valueFitsInBitWidth(width, static_cast<int32_t>(value))) {
+ return AssemblerTmp::Error(line.sourceLine, "Immediate value '" + immToken + "' does not fit in " +
+ QString::number(width) + " bits");
+ }
+
+ for (const auto& part : parts) {
+ part.apply(value, instruction);
+ }
+ return {};
}
std::optional<AssemblerTmp::Error> decode(const uint32_t instruction, const uint32_t address,
const ReverseSymbolMap* symbolMap,
@@ -188,9 +214,13 @@ public:
m_assembler = [](const Instruction& _this, const AssemblerTmp::TokenizedSrcLine& line) {
uint32_t instruction = 0;
_this.m_opcode.apply(line, instruction);
- for (const auto& field : _this.m_fields)
- field->apply(line, instruction);
- return instruction;
+ for (const auto& field : _this.m_fields) {
+ auto err = field->apply(line, instruction);
+ if (err) {
+ return AssembleRes(err.value());
+ }
+ }
+ return AssembleRes(instruction);
};
m_disassembler = [](const Instruction& _this, const uint32_t instruction, const uint32_t address,
const ReverseSymbolMap* symbolMap) {

MODIFY
test/tst_assembler.cpp
test/tst_assembler.cpp
@@ -19,6 +19,7 @@ private slots:
void tst_matcher();
void tst_label();
void tst_labelWithPseudo();
+ void tst_weirdImmediates();
private:
std::vector<std::shared_ptr<Instruction<RVISA>>> createInstructions();
@@ -26,12 +27,29 @@ private:
void tst_Assembler::tst_simpleprogram() {
auto assembler = RV32I_Assembler({});
- QStringList program = QStringList() << "addi a0 a0 2"
+ QStringList program = QStringList() << "addi a0 a0 123"
<< "nop";
auto res = assembler.assemble(program);
if (res.errors.size() != 0) {
res.errors.print();
+ QFAIL("Errors during assembly");
}
+
+ return;
+}
+
+void tst_Assembler::tst_weirdImmediates() {
+ auto assembler = RV32I_Assembler({});
+ QStringList program = QStringList() << "addi a0 a0 0q1234"
+ << "addi a0 a0 -abcd"
+ << "addi a0 a0 100000000"
+ << "addi a0 a0 4096"
+ << "addi a0 a0 0xabcdabcdabcd";
+ auto res = assembler.assemble(program);
+ if (res.errors.size() != 0) {
+ res.errors.print();
+ }
+
return;
}

[Assembler] Implement assembling of immediate values