(wip) Generate string representation of binary instructions
MODIFY
src/binutils.h
src/binutils.h
-#ifndef BINUTILS_H
-#define BINUTILS_H
+#pragma once
-#endif // BINUTILS_H
+#include <cstdint>
+
+// Sign extension of arbitrary bitfield size.
+// Courtesy of http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
+template <typename T, unsigned B>
+inline T signextend(const T x) {
+ struct {
+ T x : B;
+ } s;
+ return s.x = x;
+}
+
+inline uint32_t generateBitmask(int n) {
+ // Generate bitmask. There might be a smarter way to do this
+ uint32_t mask = 0;
+ for (int i = 0; i < n - 1; i++) {
+ mask |= 0b1;
+ mask <<= 1;
+ }
+ mask |= 0b1;
+ return mask;
+}
+
+inline uint32_t bitcount(int n) {
+ int count = 0;
+ while (n > 0) {
+ count += 1;
+ n = n & (n - 1);
+ }
+ return count;
+}

MODIFY
src/parser.cpp
src/parser.cpp
#include <assert.h>
#include <iostream>
+#include "binutils.h"
+
Parser::Parser() {
// generate word parser functors
m_decodeRInstr = generateWordParser(vector<int>{5, 3, 5, 5, 7}); // from LSB to MSB
@@ -44,28 +46,6 @@ void Parser::parseFile(memory* memoryPtr) {
}
}
-namespace {
-uint32_t generateBitmask(int n) {
- // Generate bitmask. There might be a smarter way to do this
- uint32_t mask = 0;
- for (int i = 0; i < n - 1; i++) {
- mask |= 0b1;
- mask <<= 1;
- }
- mask |= 0b1;
- return mask;
-}
-
-uint32_t bitcount(int n) {
- int count = 0;
- while (n > 0) {
- count += 1;
- n = n & (n - 1);
- }
- return count;
-}
-}
-
decode_functor Parser::generateWordParser(std::vector<int> bitFields) {
// Generates functors that can decode a binary number based on the input
// vector which is supplied upon generation
@@ -98,3 +78,87 @@ decode_functor Parser::generateWordParser(std::vector<int> bitFields) {
return wordParser;
}
+
+QString Parser::genStringRepr(uint32_t instr) const {
+ switch (instr & 0x7f) {
+ case LUI:
+ return generateLuiString(instr);
+ case AUIPC:
+ return generateAuipcString(instr);
+ case JAL:
+ return generateJalString(instr);
+ case JALR:
+ return generateJalrString(instr);
+ case BRANCH:
+ return generateBranchString(instr);
+ case LOAD:
+ return generateLoadString(instr);
+ case STORE:
+ return generateStoreString(instr);
+ case OP_IMM:
+ return generateOpImmString(instr);
+ case OP:
+ return generateOpInstrString(instr);
+ case ECALL:
+ return generateEcallString(instr);
+ default:
+ return QString("Invalid instruction");
+ break;
+ }
+}
+QString Parser::generateEcallString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateOpInstrString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateOpImmString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateStoreString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateLoadString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateBranchString(uint32_t instr) const {
+ std::vector<uint32_t> fields = decodeBInstr(instr);
+ int offset = signextend<int32_t, 13>((fields[0] << 12) | (fields[1] << 5) | (fields[5] << 1) | (fields[6] << 11));
+ switch (fields[4]) {
+ case 0b000: // BEQ
+ return QString("beq x%1 x%2 %3").arg(fields[2]).arg(fields[3]).arg(offset);
+ case 0b001: // BNE
+ return QString("bne x%1 x%2 %3").arg(fields[2]).arg(fields[3]).arg(offset);
+ case 0b100: // BLT - signed comparison
+ return QString("blt x%1 x%2 %3").arg(fields[2]).arg(fields[3]).arg(offset);
+ case 0b101: // BGE - signed comparison
+ return QString("bge x%1 x%2 %3").arg(fields[2]).arg(fields[3]).arg(offset);
+ case 0b110: // BLTU
+ return QString("bltu x%1 x%2 %3").arg(fields[2]).arg(fields[3]).arg(offset);
+ case 0b111: // BGEU
+ return QString("bgeu x%1 x%2 %3").arg(fields[2]).arg(fields[3]).arg(offset);
+ default:
+ return QString();
+ }
+}
+
+QString Parser::generateJalrString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateLuiString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateAuipcString(uint32_t instr) const {
+ return QString();
+}
+
+QString Parser::generateJalString(uint32_t instr) const {
+ return QString();
+}

MODIFY
src/parser.h
src/parser.h
@@ -16,6 +16,7 @@ public:
~Parser();
int getFileSize() { return m_fileSize; }
+ QString genStringRepr(uint32_t instr) const;
// Const interfaces to intstruction decode lamdas
std::vector<uint32_t> decodeUInstr(uint32_t instr) const { return m_decodeUInstr(instr); }
@@ -42,6 +43,18 @@ private:
decode_functor m_decodeSInstr;
decode_functor m_decodeRInstr;
decode_functor m_decodeBInstr;
+
+ // String generating functions
+ QString generateBranchString(uint32_t instr) const;
+ QString generateLuiString(uint32_t instr) const;
+ QString generateAuipcString(uint32_t instr) const;
+ QString generateJalString(uint32_t instr) const;
+ QString generateJalrString(uint32_t instr) const;
+ QString generateLoadString(uint32_t instr) const;
+ QString generateStoreString(uint32_t instr) const;
+ QString generateOpImmString(uint32_t instr) const;
+ QString generateOpInstrString(uint32_t instr) const;
+ QString generateEcallString(uint32_t instr) const;
};
#endif // PARSER_H

MODIFY
src/runner.cpp
src/runner.cpp
#include "assert.h"
#include "parser.h"
-namespace {
-// Sign extension of arbitrary bitfield size.
-// Courtesy of http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
-template <typename T, unsigned B>
-inline T signextend(const T x) {
- struct {
- T x : B;
- } s;
- return s.x = x;
-}
-} // namespace
+#include "binutils.h"
Runner::Runner(Parser* parser) {
m_parser = parser;

(wip) Generate string representation of binary instructions