[llvm] [Mips] Split memory operands into base registers and offsets (PR #228738)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 09:40:44 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-mips
Author: Jiaxun Yang (FlyGoat)
<details>
<summary>Changes</summary>
Mips memory instructions have accumulated many custom decoders to unpack base registers and offsets, handle scaling, and account for instruction variants. Treating the address as one compound operand duplicates work that TableGen can generate from separate fields and spreads special cases across the parser, encoder, decoder, and printer.
Parse memory offsets and parenthesized base registers as separate operands and describe their encoding fields independently in TableGen. Replace packed memory encoders, decoders, and printers with operand-level helpers, including support for scaled offsets and variable register lists.
Keep compound address operands for la/dla and use the common expression parser for memory offsets. This is largely NFC, with fixes to expression evaluation order reflected in the updated tests and slightly improved error messages.
Assisted-by: OpenAI Codex
---
Patch is 185.68 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/228738.diff
41 Files Affected:
- (modified) llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (+113-218)
- (modified) llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp (+37-523)
- (modified) llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp (+7-25)
- (modified) llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h (+3-2)
- (modified) llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp (+13-176)
- (modified) llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h (+6-32)
- (modified) llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp (+2-1)
- (modified) llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td (+28-33)
- (modified) llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td (+53-58)
- (modified) llvm/lib/Target/Mips/MicroMipsInstrFPU.td (+4-4)
- (modified) llvm/lib/Target/Mips/MicroMipsInstrFormats.td (+36-36)
- (modified) llvm/lib/Target/Mips/MicroMipsInstrInfo.td (+211-229)
- (modified) llvm/lib/Target/Mips/Mips16InstrInfo.td (+36-53)
- (modified) llvm/lib/Target/Mips/Mips32r6InstrFormats.td (+6-11)
- (modified) llvm/lib/Target/Mips/Mips32r6InstrInfo.td (+10-13)
- (modified) llvm/lib/Target/Mips/Mips64InstrInfo.td (+35-24)
- (modified) llvm/lib/Target/Mips/MipsAsmPrinter.cpp (-32)
- (modified) llvm/lib/Target/Mips/MipsAsmPrinter.h (-2)
- (modified) llvm/lib/Target/Mips/MipsDSPInstrInfo.td (+8-8)
- (modified) llvm/lib/Target/Mips/MipsEVAInstrFormats.td (+2-3)
- (modified) llvm/lib/Target/Mips/MipsEVAInstrInfo.td (+14-21)
- (modified) llvm/lib/Target/Mips/MipsInstrFPU.td (+33-17)
- (modified) llvm/lib/Target/Mips/MipsInstrFormats.td (+10-11)
- (modified) llvm/lib/Target/Mips/MipsInstrInfo.td (+177-141)
- (modified) llvm/lib/Target/Mips/MipsMSAInstrFormats.td (+4-3)
- (modified) llvm/lib/Target/Mips/MipsMSAInstrInfo.td (+27-18)
- (modified) llvm/test/MC/Disassembler/Mips/marked-up.txt (+1-1)
- (modified) llvm/test/MC/Disassembler/Mips/micromips32r3/valid-el.txt (+1)
- (modified) llvm/test/MC/Mips/cnmipsp/invalid.s (+2-2)
- (modified) llvm/test/MC/Mips/expr1.s (+8-8)
- (modified) llvm/test/MC/Mips/macro-dla-32bit.s (+21)
- (modified) llvm/test/MC/Mips/macro-dla-bad.s (+5)
- (modified) llvm/test/MC/Mips/macro-dla.s (+27)
- (modified) llvm/test/MC/Mips/macro-la-bad.s (+7-4)
- (modified) llvm/test/MC/Mips/macro-la.s (+19)
- (modified) llvm/test/MC/Mips/memory-offsets.s (+5-5)
- (modified) llvm/test/MC/Mips/micromips-16-bit-instructions.s (+18-2)
- (modified) llvm/test/MC/Mips/micromips-invalid.s (+10)
- (modified) llvm/test/MC/Mips/micromips32r6/invalid.s (+12-2)
- (modified) llvm/test/MC/Mips/micromips32r6/valid.s (+6)
- (modified) llvm/test/MC/Mips/mips-memory-instructions.s (+19)
``````````diff
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 48163a54f48374..fa82ae8be060fa 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -198,6 +198,8 @@ class MipsAsmParser : public MCTargetAsmParser {
bool ParseDirective(AsmToken DirectiveID) override;
ParseStatus parseMemOperand(OperandVector &Operands);
+ ParseStatus parseMemOffsetOperand(OperandVector &Operands);
+ const MCExpr *parseMemOffset();
ParseStatus matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
StringRef Identifier, SMLoc S);
ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands,
@@ -208,6 +210,7 @@ class MipsAsmParser : public MCTargetAsmParser {
ParseStatus parseInvNum(OperandVector &Operands);
ParseStatus parseRegisterList(OperandVector &Operands);
const MCExpr *parseRelocExpr();
+ bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
bool searchSymbolAlias(OperandVector &Operands);
@@ -1208,24 +1211,24 @@ class MipsOperand : public MCParsedAsmOperand {
addExpr(Inst, Expr);
}
- void addMemOperands(MCInst &Inst, unsigned N) const {
- assert(N == 2 && "Invalid number of operands!");
-
- Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
- ? getMemBase()->getGPR64Reg()
- : getMemBase()->getGPR32Reg()));
-
- const MCExpr *Expr = getMemOff();
- addExpr(Inst, Expr);
+ void addPtrRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(
+ AsmParser.getABI().ArePtrs64bit() ? getGPR64Reg() : getGPR32Reg()));
}
- void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
+ void addMemOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
+ getMemBase()->addPtrRegOperands(Inst, 1);
+ addExpr(Inst, getMemOff());
+ }
- Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
+ bool isSPAsmReg() const { return isGPRAsmReg() && RegIdx.Index == 29; }
+ bool isGPAsmReg() const { return isGPRAsmReg() && RegIdx.Index == 28; }
- const MCExpr *Expr = getMemOff();
- addExpr(Inst, Expr);
+ bool isSImmPtr() const {
+ return AsmParser.getABI().ArePtrs64bit() ? isScaledSImm<64, 0>()
+ : isScaledSImm<32, 0>();
}
void addRegListOperands(MCInst &Inst, unsigned N) const {
@@ -1300,65 +1303,13 @@ class MipsOperand : public MCParsedAsmOperand {
bool isMem() const override { return Kind == k_Memory; }
- bool isConstantMemOff() const {
- return isMem() && isa<MCConstantExpr>(getMemOff());
- }
+ bool isMemOperand() const { return isMem() && getMemBase()->isGPRAsmReg(); }
// Allow relocation operators.
- template <unsigned Bits, unsigned ShiftAmount = 0>
- bool isMemWithSimmOffset() const {
- if (!isMem())
- return false;
- if (!getMemBase()->isGPRAsmReg())
- return false;
- if (isa<MCSpecifierExpr>(getMemOff()) ||
- (isConstantMemOff() &&
- isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
- return true;
- MCValue Res;
- bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr);
- return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
- }
-
- bool isMemWithPtrSizeOffset() const {
- if (!isMem())
- return false;
- if (!getMemBase()->isGPRAsmReg())
- return false;
- const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
- if (isa<MCSpecifierExpr>(getMemOff()) ||
- (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
- return true;
- MCValue Res;
- bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr);
- return IsReloc && isIntN(PtrBits, Res.getConstant());
- }
-
- bool isMemWithGRPMM16Base() const {
- return isMem() && getMemBase()->isMM16AsmReg();
- }
-
- template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
- return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
- && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
- }
-
- template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
- return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
- && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
- && (getMemBase()->getGPR32Reg() == Mips::SP);
- }
-
- template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
- return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
- && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
- && (getMemBase()->getGPR32Reg() == Mips::GP);
- }
-
- template <unsigned Bits, unsigned ShiftLeftAmount>
+ template <unsigned Bits, unsigned ShiftLeftAmount, int Bias = 0>
bool isScaledUImm() const {
- return isConstantImm() &&
- isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
+ return isConstantImm() && isShiftedUInt<Bits, ShiftLeftAmount>(
+ uint64_t(getConstantImm()) - Bias);
}
template <unsigned Bits, unsigned ShiftLeftAmount>
@@ -1370,6 +1321,8 @@ class MipsOperand : public MCParsedAsmOperand {
// offset in case of relocations.
if (Kind != k_Immediate)
return false;
+ if (isa<MCSpecifierExpr>(getImm()))
+ return true;
MCValue Res;
bool Success = getImm()->evaluateAsRelocatable(Res, nullptr);
return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
@@ -1449,10 +1402,6 @@ class MipsOperand : public MCParsedAsmOperand {
return Mem.Off;
}
- int64_t getConstantMemOff() const {
- return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
- }
-
const SmallVectorImpl<MCRegister> &getRegList() const {
assert((Kind == k_RegList) && "Invalid access!");
return *(RegList.List);
@@ -1580,14 +1529,14 @@ class MipsOperand : public MCParsedAsmOperand {
}
bool isMM16AsmReg() const {
- if (!(isRegIdx() && RegIdx.Kind))
+ if (!isGPRAsmReg())
return false;
return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
|| RegIdx.Index == 16 || RegIdx.Index == 17);
}
bool isMM16AsmRegZero() const {
- if (!(isRegIdx() && RegIdx.Kind))
+ if (!isGPRAsmReg())
return false;
return (RegIdx.Index == 0 ||
(RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
@@ -5939,6 +5888,10 @@ bool MipsAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "too few operands for instruction");
ErrorLoc = Operands[ErrorInfo]->getStartLoc();
+ if (Operands[ErrorInfo]->isMem())
+ ErrorLoc = static_cast<MipsOperand &>(*Operands[ErrorInfo])
+ .getMemBase()
+ ->getStartLoc();
if (ErrorLoc == SMLoc())
ErrorLoc = IDLoc;
}
@@ -6003,6 +5956,13 @@ bool MipsAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
// operand to avoid confusing the user.
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit unsigned immediate");
+ case Match_ConstantMemOffset:
+ if (ErrorInfo < Operands.size() &&
+ !static_cast<MipsOperand &>(*Operands[ErrorInfo]).isConstantImm())
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate operand kind");
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "immediate operand value out of range");
case Match_UImm5_Lsl2:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected both 7-bit unsigned immediate and multiple of 4");
@@ -6136,7 +6096,8 @@ void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
MCRegister NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
Inst.addOperand(MCOperand::createReg(NextReg));
- ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
+ static_cast<MipsOperand &>(*Operands[4]).addPtrRegOperands(Inst, 1);
+ static_cast<MipsOperand &>(*Operands[2]).addImmOperands(Inst, 1);
}
void
@@ -6249,9 +6210,18 @@ MCRegister MipsAsmParser::getReg(int RC, int RegNo) {
return getContext().getRegisterInfo()->getRegClass(RC).getRegister(RegNo);
}
-// Parse an expression with optional relocation operator prefixes (e.g. %lo).
-// Some weird expressions allowed by gas are not supported for simplicity,
-// e.g. "%lo foo", "(%lo(foo))", "%lo(foo)+1".
+// Recognize relocation specifiers so the common parser can handle arithmetic
+// around them, such as %lo(8) + symbol.
+bool MipsAsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (getLexer().isNot(AsmToken::Percent))
+ return getParser().parsePrimaryExpr(Res, EndLoc);
+ Res = parseRelocExpr();
+ EndLoc = getLexer().getLoc();
+ return !Res;
+}
+
+// Parse an expression with optional, possibly nested relocation specifiers.
+// The opening parentheses are required, unlike the GAS form "%lo foo".
const MCExpr *MipsAsmParser::parseRelocExpr() {
auto getOp = [](StringRef Op) {
return StringSwitch<Mips::Specifier>(Op)
@@ -6399,138 +6369,72 @@ ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
}
-ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
- MCAsmParser &Parser = getParser();
- LLVM_DEBUG(dbgs() << "parseMemOperand\n");
- const MCExpr *IdVal = nullptr;
- SMLoc S;
- bool isParenExpr = false;
- ParseStatus Res = ParseStatus::NoMatch;
- // First operand is the offset.
- S = Parser.getTok().getLoc();
-
- if (getLexer().getKind() == AsmToken::LParen) {
- Parser.Lex();
- isParenExpr = true;
- }
-
- if (getLexer().getKind() != AsmToken::Dollar) {
- IdVal = parseRelocExpr();
- if (!IdVal)
- return ParseStatus::Failure;
- if (isParenExpr && Parser.parseRParen())
- return ParseStatus::Failure;
-
- const AsmToken &Tok = Parser.getTok(); // Get the next token.
- if (Tok.isNot(AsmToken::LParen)) {
- MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
- if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
- SMLoc E =
- SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
- return ParseStatus::Success;
- }
- if (Tok.is(AsmToken::EndOfStatement)) {
- SMLoc E =
- SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-
- // Zero register assumed, add a memory operand with ZERO as its base.
- // "Base" will be managed by k_Memory.
- auto Base = MipsOperand::createGPRReg(
- 0, "0", getContext().getRegisterInfo(), S, E, *this);
- Operands.push_back(
- MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
- return ParseStatus::Success;
- }
- MCBinaryExpr::Opcode Opcode;
- // GAS and LLVM treat comparison operators different. GAS will generate -1
- // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
- // highly unlikely to be found in a memory offset expression, we don't
- // handle them.
- switch (Tok.getKind()) {
- case AsmToken::Plus:
- Opcode = MCBinaryExpr::Add;
- Parser.Lex();
- break;
- case AsmToken::Minus:
- Opcode = MCBinaryExpr::Sub;
- Parser.Lex();
- break;
- case AsmToken::Star:
- Opcode = MCBinaryExpr::Mul;
- Parser.Lex();
- break;
- case AsmToken::Pipe:
- Opcode = MCBinaryExpr::Or;
- Parser.Lex();
- break;
- case AsmToken::Amp:
- Opcode = MCBinaryExpr::And;
- Parser.Lex();
- break;
- case AsmToken::LessLess:
- Opcode = MCBinaryExpr::Shl;
- Parser.Lex();
- break;
- case AsmToken::GreaterGreater:
- Opcode = MCBinaryExpr::LShr;
- Parser.Lex();
- break;
- case AsmToken::Caret:
- Opcode = MCBinaryExpr::Xor;
- Parser.Lex();
- break;
- case AsmToken::Slash:
- Opcode = MCBinaryExpr::Div;
- Parser.Lex();
- break;
- case AsmToken::Percent:
- Opcode = MCBinaryExpr::Mod;
- Parser.Lex();
- break;
- default:
- return Error(Parser.getTok().getLoc(), "'(' or expression expected");
- }
- const MCExpr * NextExpr;
- if (getParser().parseExpression(NextExpr))
- return ParseStatus::Failure;
- IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
- }
+const MCExpr *MipsAsmParser::parseMemOffset() {
+ // An omitted expression, as in ($sp), denotes zero.
+ if (getLexer().is(AsmToken::LParen) &&
+ getLexer().peekTok().is(AsmToken::Dollar))
+ return MCConstantExpr::create(0, getContext());
- Parser.Lex(); // Eat the '(' token.
- }
+ const MCExpr *Offset;
+ if (getParser().parseExpression(Offset))
+ return nullptr;
+ int64_t Value;
+ if (Offset->evaluateAsAbsolute(Value))
+ return MCConstantExpr::create(Value, getContext());
+ return Offset;
+}
- Res = parseAnyRegister(Operands);
- if (!Res.isSuccess())
- return Res;
+ParseStatus MipsAsmParser::parseMemOffsetOperand(OperandVector &Operands) {
+ SMLoc S = getLexer().getLoc();
+ const MCExpr *Offset = parseMemOffset();
+ if (!Offset)
+ return ParseStatus::Failure;
- if (Parser.getTok().isNot(AsmToken::RParen))
- return Error(Parser.getTok().getLoc(), "')' expected");
+ SMLoc E = getLexer().getLoc();
+ Operands.push_back(MipsOperand::CreateImm(Offset, S, E, *this));
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ if (getLexer().is(AsmToken::LParen)) {
+ StringRef Mnemonic = static_cast<MipsOperand &>(*Operands[0]).getToken();
+ return parseParenSuffix(Mnemonic, Operands) ? ParseStatus::Failure
+ : ParseStatus::Success;
+ }
+
+ // A memory address without an explicit base uses $zero.
+ // FIXME: GAS can expand arbitrary symbolic addresses. Ideally, a pseudo
+ // instruction should handle these instead of supplying a default $zero base.
+ Operands.push_back(MipsOperand::CreateToken("(", E, *this));
+ Operands.push_back(MipsOperand::createGPRReg(
+ 0, "0", getContext().getRegisterInfo(), E, E, *this));
+ Operands.push_back(MipsOperand::CreateToken(")", E, *this));
+ return ParseStatus::Success;
+}
- Parser.Lex(); // Eat the ')' token.
+ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
+ MCAsmParser &Parser = getParser();
+ SMLoc S = Parser.getTok().getLoc();
+ const MCExpr *Address = parseMemOffset();
+ if (!Address)
+ return ParseStatus::Failure;
+
+ SMLoc E = Parser.getTok().getLoc();
+ if (getLexer().isNot(AsmToken::LParen)) {
+ Operands.push_back(MipsOperand::CreateImm(Address, S, E, *this));
+ return ParseStatus::Success;
+ }
- if (!IdVal)
- IdVal = MCConstantExpr::create(0, getContext());
+ Parser.Lex(); // Eat '('.
+ ParseStatus Result = parseAnyRegister(Operands);
+ if (!Result.isSuccess())
+ return Result;
+ if (Parser.parseRParen())
+ return ParseStatus::Failure;
- // Replace the register operand with the memory operand.
- std::unique_ptr<MipsOperand> op(
+ std::unique_ptr<MipsOperand> Base(
static_cast<MipsOperand *>(Operands.back().release()));
- // Remove the register from the operands.
- // "op" will be managed by k_Memory.
Operands.pop_back();
- // Add the memory operand.
- if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
- int64_t Imm;
- if (IdVal->evaluateAsAbsolute(Imm))
- IdVal = MCConstantExpr::create(Imm, getContext());
- else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
- IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
- getContext());
- }
-
- Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
+ E = Base->getEndLoc();
+ Operands.push_back(
+ MipsOperand::CreateMem(std::move(Base), Address, S, E, *this));
return ParseStatus::Success;
}
@@ -6817,8 +6721,7 @@ ParseStatus MipsAsmParser::parseRegisterList(OperandVector &Operands) {
SMLoc E = Parser.getTok().getLoc();
Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
- parseMemOperand(Operands);
- return ParseStatus::Success;
+ return parseMemOffsetOperand(Operands);
}
/// Sometimes (i.e. load/stores) the operand may be followed immediately by
@@ -6910,30 +6813,22 @@ bool MipsAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
// Read the remaining operands.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
- // Read the first operand.
- if (parseOperand(Operands, Name)) {
- SMLoc Loc = getLexer().getLoc();
- return Error(Loc, "unexpected token in argument list");
- }
- if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
- return true;
- // AFAIK, parenthesis suffixes are never on the first operand
-
- while (getLexer().is(AsmToken::Comma)) {
- Parser.Lex(); // Eat the comma.
+ do {
+ bool IsFirstOperand = Operands.size() == 1;
// Parse and remember the operand.
if (parseOperand(Operands, Name)) {
SMLoc Loc = getLexer().getLoc();
return Error(Loc, "unexpected token in argument list");
}
- // Parse bracket and parenthesis suffixes before we iterate
+ // Parse suffixes before we iterate. First operands handle parentheses
+ // through their custom parser.
if (getLexer().is(AsmToken::LBrac)) {
if (parseBracketSuffix(Name, Operands))
return true;
- } else if (getLexer().is(AsmToken::LParen) &&
+ } else if (!IsFirstOperand && getLexer().is(AsmToken::LParen) &&
parseParenSuffix(Name, Operands))
return true;
- }
+ } while (parseOptionalToken(AsmToken::Comma));
}
if (getLexer().isNot(AsmToken::EndOfStatement)) {
SMLoc Loc = getLexer().getLoc();
diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index bbd614fc644236..0e89c4de7eb6d5 100644
--- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -238,14 +238,24 @@ static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst, unsigned RegNo,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
+static DecodeStatus DecodeCOP3RegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+ Inst.addOperand(
+ MCOperand::createReg(getReg(Decoder, Mips::COP3RegClassID, RegNo)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned RegListEncoding,
uint64_t Address,
const MCDisassembler *Decoder) {
unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4,
Mips::S5, Mips::S6, Mips::S7, Mips::FP};
unsigned RegNum;
- unsigned RegLst = fieldFromInstruction(Insn, 21, 5);
+ unsigned RegLst = RegListEncoding;
// Empty register lists are not allowed.
if (RegLst == 0)
@@ -266,20 +276,12 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
+static DecodeStatus DecodeRegListOperand16(MCInst &Inst,
+ unsigned RegListEncoding,
uint64_t Address,
const MCDisassembler *Decoder) {
unsigned Regs[] = {Mips::S0...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/228738
More information about the llvm-commits
mailing list