[Assembler] Add 'li' pseudoinstruction
MODIFY
src/assembler/gnudirectives.cpp
src/assembler/gnudirectives.cpp
@@ -5,30 +5,6 @@ namespace Ripes {
namespace AssemblerTmp {
#define add_directive(container, directive) container.push_back(std::make_shared<Directive>(directive));
-namespace {
-int getImmediate(QString string, bool& canConvert) {
- string = string.toUpper();
- 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").toUInt(&canConvert, 16);
- } else if (string.startsWith(QLatin1String("0B"))) {
- immediate = string.remove("0B").toUInt(&canConvert, 2);
- } else {
- canConvert = false;
- }
- }
- return sign * immediate;
-}
-} // namespace
DirectiveVec gnuDirectives() {
DirectiveVec directives;

MODIFY
src/assembler/lexerutilities.h
src/assembler/lexerutilities.h
@@ -28,4 +28,28 @@ static QStringList splitQuotes(const QStringList& list) {
ret.removeAll("");
return ret;
}
+
+inline int getImmediate(QString string, bool& canConvert) {
+ string = string.toUpper();
+ 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").toUInt(&canConvert, 16);
+ } else if (string.startsWith(QLatin1String("0B"))) {
+ immediate = string.remove("0B").toUInt(&canConvert, 2);
+ } else {
+ canConvert = false;
+ }
+ }
+ return sign * immediate;
+}
+
} // namespace Ripes

MODIFY
src/assembler/rv32i_assembler.cpp
src/assembler/rv32i_assembler.cpp
@@ -116,6 +116,32 @@ void RV32I_Assembler::enableExtI(RVInstrVec& instructions, RVPseudoInstrVec& pse
return v;
})));
+ pseudoInstructions.push_back(std::shared_ptr<RVPseudoInstr>(new RVPseudoInstr(
+ "li", {RVPseudoInstr::reg(), RVPseudoInstr::imm()},
+ [](const RVPseudoInstr&, const AssemblerTmp::TokenizedSrcLine& line) {
+ std::vector<AssemblerTmp::LineTokens> v;
+ // Determine whether an ADDI or LUI instruction is sufficient, or if both LUI and ADDI is needed, by
+ // analysing the immediate size
+ bool canConvert;
+ int immediate = getImmediate(line.tokens.at(2), canConvert);
+
+ // Generate offset required for discerning between positive and negative immediates
+ if (isInt<12>(immediate)) {
+ // immediate can be represented by 12 bits, ADDI is sufficient
+ v.push_back(QStringList() << "addi" << line.tokens.at(1) << "x0" << QString::number(immediate));
+ } else {
+ const int lower12Signed = signextend<int32_t, 12>(immediate & 0xFFF);
+ int signOffset = lower12Signed < 0 ? 1 : 0;
+ v.push_back(QStringList() << "lui" << line.tokens.at(1)
+ << QString::number((static_cast<uint32_t>(immediate) >> 12) + signOffset));
+ if ((immediate & 0xFFF) != 0) {
+ v.push_back(QStringList()
+ << "addi" << line.tokens.at(1) << line.tokens.at(1) << QString::number(lower12Signed));
+ }
+ }
+ return v;
+ })));
+
pseudoInstructions.push_back(std::shared_ptr<RVPseudoInstr>(
new RVPseudoInstr("nop", {}, [](const RVPseudoInstr&, const AssemblerTmp::TokenizedSrcLine&) {
return std::vector<AssemblerTmp::LineTokens>{QString("addi x0 x0 0").split(' ')};

[Assembler] Add 'li' pseudoinstruction