Add support for hex and binary immediate values
MODIFY
src/asmhighlighter.cpp
src/asmhighlighter.cpp
@@ -16,14 +16,32 @@ FieldType::FieldType(Type type, int lowerBound, int upperBound, AsmHighlighter*
QString FieldType::validateField(const QString& field) const {
switch (m_type) {
case Type::Immediate: {
- // Check that immediate can be converted
+ // Check that immediate can be converted to int from either base 10, hex or binary
bool ok = false;
auto immediate = field.toInt(&ok, 10);
+ int sign = 1;
if (!ok) {
+ // Could not convert directly to integer - try hex or bin. Here, extra care is taken to account for a
+ // potential sign, and include this is the range validation
+ QString field_ = field;
+ if (field_[0] == '-' || field_[0] == '+') {
+ sign = field_[0] == '-' ? -1 : 1;
+ field_.remove(0, 1);
+ }
+ if (field_.startsWith(QLatin1String("0x"))) {
+ immediate = field_.remove("0x").toInt(&ok, 16);
+ if (!ok)
+ return QString("Invalid immediate field - got %1").arg(field);
+ } else if (field_.startsWith(QLatin1String("0b"))) {
+ immediate = field_.remove("0b").toInt(&ok, 2);
+ if (!ok)
+ return QString("Invalid immediate field - got %1").arg(field);
+ } else {
return QString("Invalid immediate field - got %1").arg(field);
}
+ }
// Check that immediate is within range
- if (immediate >= m_lowerBound && immediate <= m_upperBound) {
+ if ((sign * immediate) >= m_lowerBound && (sign * immediate) <= m_upperBound) {
return QString();
} else {
return QString(
@@ -63,7 +81,7 @@ AsmHighlighter::AsmHighlighter(QTextDocument* parent) : QSyntaxHighlighter(paren
HighlightingRule rule;
// Create rules for name-specific registers
- regFormat.setForeground(QColor(Colors::FoundersRock));
+ regFormat.setForeground(QColor(0x800000));
QStringList registerPatterns;
registerPatterns << "\\bzero\\b"
<< "\\bra\\b"
@@ -147,6 +165,9 @@ AsmHighlighter::AsmHighlighter(QTextDocument* parent) : QSyntaxHighlighter(paren
<< "\\bsrli\\b"
<< "\\bslli\\b"
<< "\\bor\\b"
+ << "\\bori\\b"
+ << "\\band\\b"
+ << "\\bandi\\b"
<< "\\badd\\b"
<< "\\becall\\b";
instrFormat.setForeground(QColor(Colors::BerkeleyBlue));
@@ -168,11 +189,23 @@ AsmHighlighter::AsmHighlighter(QTextDocument* parent) : QSyntaxHighlighter(paren
rule.format = immFormat;
m_highlightingRules.append(rule);
+ // Create immediate highlighting rule for prefixed numbers (0x, 0b)
+ immFormat.setForeground(QColor(Qt::darkGreen));
+ rule.pattern = QRegularExpression("([-+]?0[xX][0-9a-fA-F]+|[-+]?0[bB][0-1]+)");
+ rule.format = immFormat;
+ m_highlightingRules.append(rule);
+
// Create comment highlighting rule
commentFormat.setForeground(QColor(Colors::Medalist));
rule.pattern = QRegularExpression("[#]+.*");
rule.format = commentFormat;
m_highlightingRules.append(rule);
+
+ // Create label highlighting rule
+ commentFormat.setForeground(QColor(Colors::Medalist));
+ rule.pattern = QRegularExpression("(.*?[:])");
+ rule.format = commentFormat;
+ m_highlightingRules.append(rule);
}
void AsmHighlighter::highlightBlock(const QString& text) {

MODIFY
src/assembler.cpp
src/assembler.cpp
@@ -109,11 +109,34 @@ uint32_t Assembler::getRegisterNumber(const QString& reg) {
}
}
+int Assembler::getImmediate(QString string, bool& canConvert) {
+ // Extracts an immediate number from a string, being base 10, 16 or 2
+ canConvert = false;
+ int immediate = string.toInt(&canConvert, 10);
+ int sign = 1;
+ if (!canConvert) {
+ // Could not convert directly to integer - try hex or bin. Here, extra care is taken to account for a
+ // potential sign, and include this is the range validation
+ if (string[0] == '-' || string[0] == '+') {
+ sign = string[0] == '-' ? -1 : 1;
+ string.remove(0, 1);
+ }
+ if (string.startsWith(QLatin1String("0x"))) {
+ immediate = string.remove("0x").toInt(&canConvert, 16);
+ } else if (string.startsWith(QLatin1String("0b"))) {
+ immediate = string.remove("0b").toInt(&canConvert, 2);
+ } else {
+ canConvert = false;
+ }
+ }
+ return sign * immediate;
+}
+
QByteArray Assembler::assembleOpImmInstruction(const QStringList& fields, int row) {
Q_UNUSED(row);
uint32_t funct3 = 0;
bool canConvert;
- int imm = fields[3].toInt(&canConvert, 10);
+ int imm = getImmediate(fields[3], canConvert);
if (fields[0] == "addi") {
// Requires assembler-level support for labels (for pseudo-op 'la')
if (canConvert) {
@@ -360,7 +383,8 @@ void Assembler::unpackPseudoOp(const QStringList& fields, int& pos) {
} else if (fields.first() == "li") {
// Determine whether an ADDI instruction is sufficient, or if both LUI and ADDI is needed, by analysing the
// immediate size
- int immediate = fields[2].toInt();
+ bool canConvert;
+ int immediate = getImmediate(fields[2], canConvert);
if (immediate > 2047 || immediate < -2048) {
int posOffset = 1;
if (immediate < 0) {
@@ -372,7 +396,7 @@ void Assembler::unpackPseudoOp(const QStringList& fields, int& pos) {
<< QString::number(signextend<int32_t, 12>(immediate & 0xfff));
pos += 2;
} else {
- m_instructionsMap[pos] = QStringList() << "addi" << fields[1] << "x0" << fields[2];
+ m_instructionsMap[pos] = QStringList() << "addi" << fields[1] << "x0" << QString::number(immediate);
pos++;
}
} else if (fields.first() == "mv") {

MODIFY
src/assembler.h
src/assembler.h
@@ -17,6 +17,7 @@ private:
void unpackPseudoOp(const QStringList& fields, int& pos);
void unpackOp(const QStringList& fields, int& pos);
void restart();
+ int getImmediate(QString string, bool& canConvert);
QByteArray uintToByteArr(uint32_t);
QMap<QString, int> m_labelPosMap; // Map storing unpacked label

Add support for hex and binary immediate values