Optimize li pseudo-instruction expansion
MODIFY
src/assembler.cpp
src/assembler.cpp
@@ -423,21 +423,33 @@ void Assembler::unpackPseudoOp(const QStringList& fields, int& pos) {
<< "0";
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
+ // 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(fields[2], canConvert);
- if (immediate > 2047 || immediate < -2048) {
+
+ // Generate offset required for discerning between positive and negative immediates
int posOffset = 1;
if (immediate < 0) {
posOffset = 0;
}
- m_instructionsMap[pos] = QStringList()
- << "lui" << fields[1] << QString::number(((uint32_t)immediate >> 12) + posOffset);
- m_instructionsMap[pos + 1] = QStringList() << "addi" << fields[1] << fields[1]
+ if (!isInt<12>(immediate)) {
+ if ((immediate & 0xFFF) == 0) {
+ // Only a LUI is required
+ m_instructionsMap[pos] = QStringList() << "lui" << fields[1]
+ << QString::number(((uint32_t)immediate >> 12) + posOffset);
+ pos++;
+ } else {
+ // both ADDI and LUI is required
+ m_instructionsMap[pos] = QStringList() << "lui" << fields[1]
+ << QString::number(((uint32_t)immediate >> 12) + posOffset);
+ m_instructionsMap[pos + 1] = QStringList()
+ << "addi" << fields[1] << fields[1]
<< QString::number(signextend<int32_t, 12>(immediate & 0xfff));
pos += 2;
+ }
} else {
+ // ADDI is sufficient
m_instructionsMap[pos] = QStringList() << "addi" << fields[1] << "x0" << QString::number(immediate);
pos++;
}

Optimize li pseudo-instruction expansion #19