[llvm] [Mips] Split memory operands into base registers and offsets (PR #228738)
Jiaxun Yang via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 09:39:58 PDT 2026
https://github.com/FlyGoat created https://github.com/llvm/llvm-project/pull/228738
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
>From 26f4365f650da82311fe92519632d0322630cc15 Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.yang at flygoat.com>
Date: Sat, 3 Oct 2026 16:39:47 +0100
Subject: [PATCH] [Mips] Split memory operands into base registers and offsets
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
---
.../Target/Mips/AsmParser/MipsAsmParser.cpp | 331 ++++-------
.../Mips/Disassembler/MipsDisassembler.cpp | 560 ++----------------
.../Mips/MCTargetDesc/MipsInstPrinter.cpp | 32 +-
.../Mips/MCTargetDesc/MipsInstPrinter.h | 5 +-
.../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 189 +-----
.../Mips/MCTargetDesc/MipsMCCodeEmitter.h | 38 +-
.../Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 3 +-
.../Target/Mips/MicroMips32r6InstrFormats.td | 61 +-
.../lib/Target/Mips/MicroMips32r6InstrInfo.td | 111 ++--
llvm/lib/Target/Mips/MicroMipsInstrFPU.td | 8 +-
llvm/lib/Target/Mips/MicroMipsInstrFormats.td | 72 +--
llvm/lib/Target/Mips/MicroMipsInstrInfo.td | 440 +++++++-------
llvm/lib/Target/Mips/Mips16InstrInfo.td | 89 ++-
llvm/lib/Target/Mips/Mips32r6InstrFormats.td | 17 +-
llvm/lib/Target/Mips/Mips32r6InstrInfo.td | 23 +-
llvm/lib/Target/Mips/Mips64InstrInfo.td | 59 +-
llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 32 -
llvm/lib/Target/Mips/MipsAsmPrinter.h | 2 -
llvm/lib/Target/Mips/MipsDSPInstrInfo.td | 16 +-
llvm/lib/Target/Mips/MipsEVAInstrFormats.td | 5 +-
llvm/lib/Target/Mips/MipsEVAInstrInfo.td | 35 +-
llvm/lib/Target/Mips/MipsInstrFPU.td | 50 +-
llvm/lib/Target/Mips/MipsInstrFormats.td | 21 +-
llvm/lib/Target/Mips/MipsInstrInfo.td | 318 +++++-----
llvm/lib/Target/Mips/MipsMSAInstrFormats.td | 7 +-
llvm/lib/Target/Mips/MipsMSAInstrInfo.td | 45 +-
llvm/test/MC/Disassembler/Mips/marked-up.txt | 2 +-
.../Mips/micromips32r3/valid-el.txt | 1 +
llvm/test/MC/Mips/cnmipsp/invalid.s | 4 +-
llvm/test/MC/Mips/expr1.s | 16 +-
llvm/test/MC/Mips/macro-dla-32bit.s | 21 +
llvm/test/MC/Mips/macro-dla-bad.s | 5 +
llvm/test/MC/Mips/macro-dla.s | 27 +
llvm/test/MC/Mips/macro-la-bad.s | 11 +-
llvm/test/MC/Mips/macro-la.s | 19 +
llvm/test/MC/Mips/memory-offsets.s | 10 +-
.../MC/Mips/micromips-16-bit-instructions.s | 20 +-
llvm/test/MC/Mips/micromips-invalid.s | 10 +
llvm/test/MC/Mips/micromips32r6/invalid.s | 14 +-
llvm/test/MC/Mips/micromips32r6/valid.s | 6 +
llvm/test/MC/Mips/mips-memory-instructions.s | 19 +
41 files changed, 1036 insertions(+), 1718 deletions(-)
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, Mips::S1, Mips::S2, Mips::S3};
- unsigned RegLst;
- switch (Inst.getOpcode()) {
- default:
- RegLst = fieldFromInstruction(Insn, 4, 2);
- break;
- case Mips::LWM16_MMR6:
- case Mips::SWM16_MMR6:
- RegLst = fieldFromInstruction(Insn, 8, 2);
- break;
- }
+ unsigned RegLst = RegListEncoding;
unsigned RegNum = RegLst & 0x3;
for (unsigned i = 0; i <= RegNum; i++)
@@ -947,6 +949,28 @@ static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, unsigned RegNo,
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
}
+template <unsigned RegNo>
+static DecodeStatus DecodeFixedPtrRegister(MCInst &Inst,
+ const MCDisassembler *Decoder) {
+ return DecodePtrRegisterClass(Inst, RegNo, 0, Decoder);
+}
+
+static DecodeStatus DecodeLBU16Offset(MCInst &Inst, unsigned Value,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ Inst.addOperand(MCOperand::createImm(Value == 15 ? -1 : int64_t(Value)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeGPR32Pair(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ if (RegNo >= 31)
+ return MCDisassembler::Fail;
+ DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
+ return DecodeGPR32RegisterClass(Inst, RegNo + 1, Address, Decoder);
+}
+
static DecodeStatus DecodeDSPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -1017,516 +1041,6 @@ static DecodeStatus DecodeFGR64CCRegisterClass(MCInst &Inst, unsigned RegNo,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeMem(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned RegNo = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- if (Inst.getOpcode() == Mips::SC || Inst.getOpcode() == Mips::SC64 ||
- Inst.getOpcode() == Mips::SCD)
- Inst.addOperand(MCOperand::createReg(Reg));
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemEVA(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<9>(Insn >> 7);
- unsigned RegNo = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- if (Inst.getOpcode() == Mips::SCE)
- Inst.addOperand(MCOperand::createReg(Reg));
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeLoadByte15(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
- unsigned RegNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeCacheOp(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned Hint = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
- Inst.addOperand(MCOperand::createImm(Hint));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeCacheOpMM(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<12>(Insn & 0xfff);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
- unsigned Hint = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
- Inst.addOperand(MCOperand::createImm(Hint));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodePrefeOpMM(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<9>(Insn & 0x1ff);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
- unsigned Hint = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
- Inst.addOperand(MCOperand::createImm(Hint));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<9>(Insn >> 7);
- unsigned Hint = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
- Inst.addOperand(MCOperand::createImm(Hint));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeSyncI(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeSyncI_MM(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeSynciR6(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Immediate = SignExtend32<16>(Insn & 0xffff);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
-
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Immediate));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 16, 10));
- unsigned RegNo = fieldFromInstruction(Insn, 6, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 11, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::MSA128BRegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
-
- // The immediate field of an LD/ST instruction is scaled which means it must
- // be multiplied (when decoding) by the size (in bytes) of the instructions'
- // data format.
- // .b - 1 byte
- // .h - 2 bytes
- // .w - 4 bytes
- // .d - 8 bytes
- switch(Inst.getOpcode())
- {
- default:
- assert(false && "Unexpected instruction");
- return MCDisassembler::Fail;
- break;
- case Mips::LD_B:
- case Mips::ST_B:
- Inst.addOperand(MCOperand::createImm(Offset));
- break;
- case Mips::LD_H:
- case Mips::ST_H:
- Inst.addOperand(MCOperand::createImm(Offset * 2));
- break;
- case Mips::LD_W:
- case Mips::ST_W:
- Inst.addOperand(MCOperand::createImm(Offset * 4));
- break;
- case Mips::LD_D:
- case Mips::ST_D:
- Inst.addOperand(MCOperand::createImm(Offset * 8));
- break;
- }
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemMMImm4(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- unsigned Offset = Insn & 0xf;
- unsigned Reg = fieldFromInstruction(Insn, 7, 3);
- unsigned Base = fieldFromInstruction(Insn, 4, 3);
-
- switch (Inst.getOpcode()) {
- case Mips::LBU16_MM:
- case Mips::LHU16_MM:
- case Mips::LW16_MM:
- if (DecodeGPRMM16RegisterClass(Inst, Reg, Address, Decoder)
- == MCDisassembler::Fail)
- return MCDisassembler::Fail;
- break;
- case Mips::SB16_MM:
- case Mips::SB16_MMR6:
- case Mips::SH16_MM:
- case Mips::SH16_MMR6:
- case Mips::SW16_MM:
- case Mips::SW16_MMR6:
- if (DecodeGPRMM16ZeroRegisterClass(Inst, Reg, Address, Decoder)
- == MCDisassembler::Fail)
- return MCDisassembler::Fail;
- break;
- }
-
- if (DecodeGPRMM16RegisterClass(Inst, Base, Address, Decoder)
- == MCDisassembler::Fail)
- return MCDisassembler::Fail;
-
- switch (Inst.getOpcode()) {
- case Mips::LBU16_MM:
- if (Offset == 0xf)
- Inst.addOperand(MCOperand::createImm(-1));
- else
- Inst.addOperand(MCOperand::createImm(Offset));
- break;
- case Mips::SB16_MM:
- case Mips::SB16_MMR6:
- Inst.addOperand(MCOperand::createImm(Offset));
- break;
- case Mips::LHU16_MM:
- case Mips::SH16_MM:
- case Mips::SH16_MMR6:
- Inst.addOperand(MCOperand::createImm(Offset << 1));
- break;
- case Mips::LW16_MM:
- case Mips::SW16_MM:
- case Mips::SW16_MMR6:
- Inst.addOperand(MCOperand::createImm(Offset << 2));
- break;
- }
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- unsigned Offset = Insn & 0x1F;
- unsigned RegNo = fieldFromInstruction(Insn, 5, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Mips::SP));
- Inst.addOperand(MCOperand::createImm(Offset << 2));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- unsigned Offset = Insn & 0x7F;
- unsigned RegNo = fieldFromInstruction(Insn, 7, 3);
-
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createImm(Offset << 2));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset;
- switch (Inst.getOpcode()) {
- case Mips::LWM16_MMR6:
- case Mips::SWM16_MMR6:
- Offset = fieldFromInstruction(Insn, 4, 4);
- break;
- default:
- Offset = SignExtend32<4>(Insn & 0xf);
- break;
- }
-
- if (DecodeRegListOperand16(Inst, Insn, Address, Decoder)
- == MCDisassembler::Fail)
- return MCDisassembler::Fail;
-
- Inst.addOperand(MCOperand::createReg(Mips::SP));
- Inst.addOperand(MCOperand::createImm(Offset << 2));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemMMImm9(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<9>(Insn & 0x1ff);
- unsigned RegNo = fieldFromInstruction(Insn, 21, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- if (Inst.getOpcode() == Mips::SCE_MM || Inst.getOpcode() == Mips::SC_MMR6)
- Inst.addOperand(MCOperand::createReg(Reg));
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemMMImm12(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<12>(Insn & 0x0fff);
- unsigned RegNo = fieldFromInstruction(Insn, 21, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- switch (Inst.getOpcode()) {
- case Mips::SWM32_MM:
- case Mips::LWM32_MM:
- if (DecodeRegListOperand(Inst, Insn, Address, Decoder)
- == MCDisassembler::Fail)
- return MCDisassembler::Fail;
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
- break;
- case Mips::SC_MM:
- Inst.addOperand(MCOperand::createReg(Reg));
- [[fallthrough]];
- default:
- Inst.addOperand(MCOperand::createReg(Reg));
- if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM)
- Inst.addOperand(MCOperand::createReg(Reg+1));
-
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
- }
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeMemMMImm16(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned RegNo = fieldFromInstruction(Insn, 21, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned RegNo = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- // This function is the same as DecodeFMem but with the Reg and Base fields
- // swapped according to microMIPS spec.
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
- unsigned RegNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned RegNo = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::COP2RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeFMem3(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<16>(Insn & 0xffff);
- unsigned RegNo = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::COP3RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<11>(Insn & 0x07ff);
- unsigned RegNo = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 11, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::COP2RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int Offset = SignExtend32<11>(Insn & 0x07ff);
- unsigned RegNo = fieldFromInstruction(Insn, 21, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 16, 5);
-
- MCRegister Reg = getReg(Decoder, Mips::COP2RegClassID, RegNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- Inst.addOperand(MCOperand::createReg(Reg));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int64_t Offset = SignExtend64<9>((Insn >> 7) & 0x1ff);
- unsigned RtNo = fieldFromInstruction(Insn, 16, 5);
- unsigned BaseNo = fieldFromInstruction(Insn, 21, 5);
-
- MCRegister Rt = getReg(Decoder, Mips::GPR32RegClassID, RtNo);
- MCRegister Base = getReg(Decoder, Mips::GPR32RegClassID, BaseNo);
-
- if(Inst.getOpcode() == Mips::SC_R6 || Inst.getOpcode() == Mips::SCD_R6){
- Inst.addOperand(MCOperand::createReg(Rt));
- }
-
- Inst.addOperand(MCOperand::createReg(Rt));
- Inst.addOperand(MCOperand::createReg(Base));
- Inst.addOperand(MCOperand::createImm(Offset));
-
- return MCDisassembler::Success;
-}
-
static DecodeStatus DecodeBranchTarget(MCInst &Inst, unsigned Offset,
uint64_t Address,
const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
index f67356c105a4d8..5be025dfbd5c36 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
@@ -142,6 +142,13 @@ void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
MAI.printExpr(O, *Op.getExpr());
}
+template <unsigned FromEnd>
+void MipsInstPrinter::printOperandFromEnd(const MCInst *MI, int OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ printOperand(MI, MI->getNumOperands() - FromEnd, STI, O);
+}
+
void MipsInstPrinter::printJumpOperand(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
@@ -198,21 +205,6 @@ void MipsInstPrinter::printMemOperand(const MCInst *MI, int opNum,
// If PIC target the target is loaded as the
// pattern lw $25,%call16($28)
- // opNum can be invalid if instruction had reglist as operand.
- // MemOperand is always last operand of instruction (base + offset).
- switch (MI->getOpcode()) {
- default:
- break;
- case Mips::SWM32_MM:
- case Mips::LWM32_MM:
- case Mips::SWM16_MM:
- case Mips::SWM16_MMR6:
- case Mips::LWM16_MM:
- case Mips::LWM16_MMR6:
- opNum = MI->getNumOperands() - 2;
- break;
- }
-
WithMarkup M = markup(O, Markup::Memory);
printOperand(MI, opNum + 1, STI, O);
O << "(";
@@ -220,16 +212,6 @@ void MipsInstPrinter::printMemOperand(const MCInst *MI, int opNum,
O << ")";
}
-void MipsInstPrinter::printMemOperandEA(const MCInst *MI, int opNum,
- const MCSubtargetInfo &STI,
- raw_ostream &O) {
- // when using stack locations for not load/store instructions
- // print the same way as all normal 3 operand instructions.
- printOperand(MI, opNum, STI, O);
- O << ", ";
- printOperand(MI, opNum + 1, STI, O);
-}
-
void MipsInstPrinter::printFCCOperand(const MCInst *MI, int opNum,
const MCSubtargetInfo & /* STI */,
raw_ostream &O) {
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
index df540ddf280514..a581b735163969 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
@@ -100,6 +100,9 @@ class MipsInstPrinter : public MCInstPrinter {
private:
void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
+ template <unsigned FromEnd>
+ void printOperandFromEnd(const MCInst *MI, int OpNo,
+ const MCSubtargetInfo &STI, raw_ostream &O);
void printJumpOperand(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printBranchOperand(const MCInst *MI, uint64_t Address, unsigned OpNo,
@@ -109,8 +112,6 @@ class MipsInstPrinter : public MCInstPrinter {
raw_ostream &O);
void printMemOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &O);
- void printMemOperandEA(const MCInst *MI, int opNum,
- const MCSubtargetInfo &STI, raw_ostream &O);
void printFCCOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &O);
void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O);
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index bbfd0872cc4cda..9e095263d6c215 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -749,184 +749,21 @@ unsigned MipsMCCodeEmitter::getImmOpValue(const MCInst &MI, const MCOperand &MO,
return getExprOpValue(Expr, Fixups, STI);
}
-/// Return binary encoding of memory related operand.
-/// If the offset operand requires relocation, record the relocation.
-template <unsigned ShiftAmount>
-unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)
- << 16;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
-
- // Apply the scale factor if there is one.
- OffBits >>= ShiftAmount;
-
- return (OffBits & 0xFFFF) | RegBits;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
- Fixups, STI) << 4;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
- Fixups, STI);
-
- return (OffBits & 0xF) | RegBits;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
- Fixups, STI) << 4;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
- Fixups, STI) >> 1;
-
- return (OffBits & 0xF) | RegBits;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
- Fixups, STI) << 4;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
- Fixups, STI) >> 2;
-
- return (OffBits & 0xF) | RegBits;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Register is encoded in bits 9-5, offset is encoded in bits 4-0.
- assert(MI.getOperand(OpNo).isReg() &&
- (MI.getOperand(OpNo).getReg() == Mips::SP ||
- MI.getOperand(OpNo).getReg() == Mips::SP_64) &&
- "Unexpected base register!");
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
- Fixups, STI) >> 2;
-
- return OffBits & 0x1F;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Register is encoded in bits 9-7, offset is encoded in bits 6-0.
- assert(MI.getOperand(OpNo).isReg() &&
- MI.getOperand(OpNo).getReg() == Mips::GP &&
- "Unexpected base register!");
-
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
- Fixups, STI) >> 2;
-
- return OffBits & 0x7F;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 20-16, offset is encoded in bits 8-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
- STI) << 16;
- unsigned OffBits =
- getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI);
-
- return (OffBits & 0x1FF) | RegBits;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 20-16, offset is encoded in bits 10-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
- STI) << 16;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
-
- return (OffBits & 0x07FF) | RegBits;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // opNum can be invalid if instruction had reglist as operand.
- // MemOperand is always last operand of instruction (base + offset).
- switch (MI.getOpcode()) {
- default:
- break;
- case Mips::SWM32_MM:
- case Mips::LWM32_MM:
- OpNo = MI.getNumOperands() - 2;
- break;
- }
-
- // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)
- << 16;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
-
- return (OffBits & 0x0FFF) | RegBits;
-}
-
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
- STI) << 16;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
-
- return (OffBits & 0xFFFF) | RegBits;
+template <unsigned Shift>
+unsigned
+MipsMCCodeEmitter::getScaledImmOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) >> Shift;
}
-unsigned MipsMCCodeEmitter::
-getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // opNum can be invalid if instruction had reglist as operand
- // MemOperand is always last operand of instruction (base + offset)
- switch (MI.getOpcode()) {
- default:
- break;
- case Mips::SWM16_MM:
- case Mips::SWM16_MMR6:
- case Mips::LWM16_MM:
- case Mips::LWM16_MMR6:
- OpNo = MI.getNumOperands() - 2;
- break;
- }
-
- // Offset is encoded in bits 4-0.
- assert(MI.getOperand(OpNo).isReg());
- // Base register is always SP - thus it is not encoded.
- assert(MI.getOperand(OpNo+1).isImm());
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
-
- return ((OffBits >> 2) & 0x0F);
+template <unsigned FromEnd, unsigned Shift>
+unsigned
+MipsMCCodeEmitter::getOperandFromEndValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ return getScaledImmOpValue<Shift>(MI, MI.getNumOperands() - FromEnd, Fixups,
+ STI);
}
// FIXME: should be called getMSBEncoding
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
index d1503d492ef0fc..ba92ea45643fbe 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
@@ -181,38 +181,12 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
- template <unsigned ShiftAmount = 0>
- unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
- unsigned getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
+ template <unsigned Shift>
+ unsigned getScaledImmOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+ template <unsigned FromEnd, unsigned Shift = 0>
+ unsigned getOperandFromEndValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index fb4cff6b25a1bb..6633c1a2cd6d8a 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -300,7 +300,8 @@ class MipsMCInstrAnalysis : public MCInstrAnalysis {
bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
unsigned NumOps = Inst.getNumOperands();
- if (NumOps == 0)
+ // Register-list transfers have more MC operands than descriptor entries.
+ if (NumOps == 0 || NumOps > Info->get(Inst.getOpcode()).getNumOperands())
return false;
switch (Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType) {
case MCOI::OPERAND_UNKNOWN:
diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td
index 2770ccb410f515..b3492ff3f42117 100644
--- a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td
+++ b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td
@@ -102,13 +102,14 @@ class POOL16C_JRCADDIUSP_FM_MM16R6<bits<5> op> {
class POOL16C_LWM_SWM_FM_MM16R6<bits<4> funct> {
bits<2> rt;
- bits<4> addr;
+ bits<0> base;
+ bits<4> offset;
bits<16> Inst;
let Inst{15-10} = 0x11;
let Inst{9-8} = rt;
- let Inst{7-4} = addr;
+ let Inst{7-4} = offset;
let Inst{3-0} = funct;
}
@@ -127,16 +128,17 @@ class POOL32A_BITSWAP_FM_MMR6<bits<6> funct> : MipsR6Inst {
}
class CACHE_PREF_FM_MMR6<bits<6> opgroup, bits<4> funct> : MipsR6Inst {
- bits<21> addr;
+ bits<12> offset;
+ bits<5> base;
bits<5> hint;
bits<32> Inst;
let Inst{31-26} = opgroup;
let Inst{25-21} = hint;
- let Inst{20-16} = addr{20-16};
+ let Inst{20-16} = base;
let Inst{15-12} = funct;
- let Inst{11-0} = addr{11-0};
+ let Inst{11-0} = offset;
}
class ARITH_FM_MMR6<string instr_asm, bits<10> funct> : MMR6Arch<instr_asm> {
@@ -168,10 +170,9 @@ class ADDI_FM_MMR6<string instr_asm, bits<6> op> : MMR6Arch<instr_asm> {
}
class LB32_FM_MMR6 : MipsR6Inst {
- bits<21> addr;
bits<5> rt;
- bits<5> base = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
@@ -182,10 +183,9 @@ class LB32_FM_MMR6 : MipsR6Inst {
}
class LBU32_FM_MMR6 : MipsR6Inst {
- bits<21> addr;
bits<5> rt;
- bits<5> base = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
@@ -286,16 +286,15 @@ class POOL32A_SYNC_FM_MMR6 {
}
class POOL32I_SYNCI_FM_MMR6 {
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<16> immediate = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
let Inst{31-26} = 0b010000;
let Inst{25-21} = 0b01100;
let Inst{20-16} = base;
- let Inst{15-0} = immediate;
+ let Inst{15-0} = offset;
}
class POOL32A_2R_FM_MMR6<bits<10> funct> : MipsR6Inst {
@@ -374,9 +373,8 @@ class POOL32A_LSA_FM<bits<6> funct> : MipsR6Inst {
class SB32_SH32_STORE_FM_MMR6<bits<6> op> {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
@@ -388,9 +386,8 @@ class SB32_SH32_STORE_FM_MMR6<bits<6> op> {
class LOAD_WORD_FM_MMR6 {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
@@ -540,15 +537,16 @@ class SHIFT_MMR6_ENC<string instr_asm, bits<10> funct, bit rotate>
}
class SW32_FM_MMR6<string instr_asm, bits<6> op> : MMR6Arch<instr_asm> {
+ bits<16> offset;
+ bits<5> base;
bits<5> rt;
- bits<21> addr;
bits<32> Inst;
let Inst{31-26} = op;
let Inst{25-21} = rt;
- let Inst{20-16} = addr{20-16};
- let Inst{15-0} = addr{15-0};
+ let Inst{20-16} = base;
+ let Inst{15-0} = offset;
}
class POOL32F_ARITH_FM_MMR6<string instr_asm, bits<2> fmt, bits<8> funct>
@@ -986,9 +984,8 @@ class POOL32I_BRANCH_COP_1_2_FM_MMR6<string instr_asm, bits<5> funct>
class LDWC1_SDWC1_FM_MMR6<string instr_asm, bits<6> funct>
: MMR6Arch<instr_asm> {
bits<5> ft;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
@@ -1001,9 +998,8 @@ class LDWC1_SDWC1_FM_MMR6<string instr_asm, bits<6> funct>
class POOL32B_LDWC2_SDWC2_FM_MMR6<string instr_asm, bits<4> funct>
: MMR6Arch<instr_asm>, MipsR6Inst {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<11> offset = addr{10-0};
+ bits<5> base;
+ bits<11> offset;
bits<32> Inst;
@@ -1019,9 +1015,8 @@ class POOL32C_LL_E_SC_E_FM_MMR6<string instr_asm, bits<4> majorFunc,
bits<3> minorFunc> : MMR6Arch<instr_asm>,
MipsR6Inst {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
index 5487254c14ab3f..262f75f42e4325 100644
--- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
@@ -408,10 +408,9 @@ class BRK_MMR6_DESC : BRK_FT<"break">;
class CACHE_HINT_MMR6_DESC<string instr_asm, Operand MemOpnd>
: MMR6Arch<instr_asm> {
dag OutOperandList = (outs);
- dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint);
- string AsmString = !strconcat(instr_asm, "\t$hint, $addr");
+ dag InOperandList = (ins MemBase:$base, MemOpnd:$offset, uimm5:$hint);
+ string AsmString = !strconcat(instr_asm, "\t$hint, ${offset}(${base})");
list<dag> Pattern = [];
- string DecoderMethod = "DecodeCacheOpMM";
}
class CACHE_MMR6_DESC : CACHE_HINT_MMR6_DESC<"cache", mem_mm_12>;
@@ -421,9 +420,8 @@ class LB_LBU_MMR6_DESC_BASE<string instr_asm, Operand MemOpnd,
RegisterOperand GPROpnd>
: MMR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rt);
- dag InOperandList = (ins MemOpnd:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
- string DecoderMethod = "DecodeLoadByte15";
+ dag InOperandList = (ins MemBase:$base, MemOpnd:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
bit mayLoad = 1;
}
class LB_MMR6_DESC : LB_LBU_MMR6_DESC_BASE<"lb", mem_mm_16, GPR32Opnd>;
@@ -713,49 +711,49 @@ class MFHC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfhc0", GPR32Opnd, COP0Opnd>;
class MFHC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfhc2", GPR32Opnd, COP2Opnd>;
class LDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 {
- dag InOperandList = (ins mem_mm_16:$addr);
+ dag InOperandList = (ins MemBase:$base, mem_mm_16:$offset);
dag OutOperandList = (outs FGR64Opnd:$ft);
- string AsmString = !strconcat("ldc1", "\t$ft, $addr");
- list<dag> Pattern = [(set FGR64Opnd:$ft, (load addrimm16:$addr))];
+ string AsmString = !strconcat("ldc1", "\t$ft, ${offset}(${base})");
+ list<dag> Pattern =
+ [(set FGR64Opnd:$ft, (load (addrimm16 MemBase:$base, iPTR:$offset)))];
Format f = FrmFI;
string BaseOpcode = "ldc1";
bit mayLoad = 1;
- let DecoderMethod = "DecodeFMemMMR2";
}
class SDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 {
- dag InOperandList = (ins FGR64Opnd:$ft, mem_mm_16:$addr);
+ dag InOperandList = (ins FGR64Opnd:$ft, MemBase:$base, mem_mm_16:$offset);
dag OutOperandList = (outs);
- string AsmString = !strconcat("sdc1", "\t$ft, $addr");
- list<dag> Pattern = [(store FGR64Opnd:$ft, addrimm16:$addr)];
+ string AsmString = !strconcat("sdc1", "\t$ft, ${offset}(${base})");
+ list<dag> Pattern =
+ [(store FGR64Opnd:$ft, (addrimm16 MemBase:$base, iPTR:$offset))];
Format f = FrmFI;
string BaseOpcode = "sdc1";
bit mayStore = 1;
- let DecoderMethod = "DecodeFMemMMR2";
}
class LDC2_LWC2_MMR6_DESC_BASE<string opstr> {
dag OutOperandList = (outs COP2Opnd:$rt);
- dag InOperandList = (ins mem_mm_11:$addr);
- string AsmString = !strconcat(opstr, "\t$rt, $addr");
- list<dag> Pattern = [(set COP2Opnd:$rt, (load addrimm11:$addr))];
+ dag InOperandList = (ins MemBase:$base, mem_mm_11:$offset);
+ string AsmString = !strconcat(opstr, "\t$rt, ${offset}(${base})");
+ list<dag> Pattern =
+ [(set COP2Opnd:$rt, (load (addrimm11 MemBase:$base, iPTR:$offset)))];
Format f = FrmFI;
string BaseOpcode = opstr;
bit mayLoad = 1;
- string DecoderMethod = "DecodeFMemCop2MMR6";
}
class LDC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"ldc2">;
class LWC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"lwc2">;
class SDC2_SWC2_MMR6_DESC_BASE<string opstr> {
dag OutOperandList = (outs);
- dag InOperandList = (ins COP2Opnd:$rt, mem_mm_11:$addr);
- string AsmString = !strconcat(opstr, "\t$rt, $addr");
- list<dag> Pattern = [(store COP2Opnd:$rt, addrimm11:$addr)];
+ dag InOperandList = (ins COP2Opnd:$rt, MemBase:$base, mem_mm_11:$offset);
+ string AsmString = !strconcat(opstr, "\t$rt, ${offset}(${base})");
+ list<dag> Pattern =
+ [(store COP2Opnd:$rt, (addrimm11 MemBase:$base, iPTR:$offset))];
Format f = FrmFI;
string BaseOpcode = opstr;
bit mayStore = 1;
- string DecoderMethod = "DecodeFMemCop2MMR6";
}
class SDC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"sdc2">;
class SWC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"swc2">;
@@ -779,21 +777,19 @@ class GINVT_MMR6_DESC : GINV_MMR6_DESC_BASE<"ginvt", GPR32Opnd>;
class SC_MMR6_DESC_BASE<string opstr> {
dag OutOperandList = (outs GPR32Opnd:$dst);
- dag InOperandList = (ins GPR32Opnd:$rt, mem_mm_9:$addr);
- string AsmString = !strconcat(opstr, "\t$rt, $addr");
+ dag InOperandList = (ins GPR32Opnd:$rt, MemBase:$base, mem_mm_9:$offset);
+ string AsmString = !strconcat(opstr, "\t$rt, ${offset}(${base})");
string BaseOpcode = opstr;
bit mayStore = 1;
string Constraints = "$rt = $dst";
- string DecoderMethod = "DecodeMemMMImm9";
}
class LL_MMR6_DESC_BASE<string opstr> {
dag OutOperandList = (outs GPR32Opnd:$rt);
- dag InOperandList = (ins mem_mm_9:$addr);
- string AsmString = !strconcat(opstr, "\t$rt, $addr");
+ dag InOperandList = (ins MemBase:$base, mem_mm_9:$offset);
+ string AsmString = !strconcat(opstr, "\t$rt, ${offset}(${base})");
string BaseOpcode = opstr;
bit mayLoad = 1;
- string DecoderMethod = "DecodeMemMMImm9";
}
class SC_MMR6_DESC : SC_MMR6_DESC_BASE<"sc">;
@@ -1011,9 +1007,7 @@ class CLASS_S_MMR6_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd>;
class CLASS_D_MMR6_DESC : CLASS_RINT_DESC_BASE<"class.d", FGR64Opnd>;
class STORE_MMR6_DESC_BASE<string opstr, DAGOperand RO>
- : Store<opstr, RO>, MMR6Arch<opstr> {
- let DecoderMethod = "DecodeMemMMImm16";
-}
+ : Store<opstr, RO>, MMR6Arch<opstr>;
class SB_MMR6_DESC : STORE_MMR6_DESC_BASE<"sb", GPR32Opnd>;
class SH_MMR6_DESC : STORE_MMR6_DESC_BASE<"sh", GPR32Opnd>;
@@ -1052,12 +1046,12 @@ class XOR16_MMR6_DESC : LogicRMM16<"xor16", GPRMM16Opnd>,
class LW_MMR6_DESC : MMR6Arch<"lw">, MipsR6Inst {
dag OutOperandList = (outs GPR32Opnd:$rt);
- dag InOperandList = (ins mem:$addr);
- string AsmString = "lw\t$rt, $addr";
- let DecoderMethod = "DecodeMemMMImm16";
+ dag InOperandList = (ins MemBase:$base, imm_offset:$offset);
+ string AsmString = "lw\t$rt, ${offset}(${base})";
let canFoldAsLoad = 1;
let mayLoad = 1;
- list<dag> Pattern = [(set GPR32Opnd:$rt, (load addrDefault:$addr))];
+ list<dag> Pattern =
+ [(set GPR32Opnd:$rt, (load (addrDefault MemBase:$base, iPTR:$offset)))];
}
class LUI_MMR6_DESC : IsAsCheapAsAMove, MMR6Arch<"lui">, MipsR6Inst{
@@ -1078,9 +1072,7 @@ class SYNC_MMR6_DESC : MMR6Arch<"sync">, MipsR6Inst {
bit HasSideEffects = 1;
}
-class SYNCI_MMR6_DESC : SYNCI_FT<"synci", mem_mm_16> {
- let DecoderMethod = "DecodeSynciR6";
-}
+class SYNCI_MMR6_DESC : SYNCI_FT<"synci", mem_mm_16>;
class RDPGPR_MMR6_DESC : MMR6Arch<"rdpgpr">, MipsR6Inst {
dag OutOperandList = (outs GPR32Opnd:$rt);
@@ -1103,31 +1095,32 @@ class SIGRIE_MMR6_DESC : MipsR6Inst {
}
class LWM16_MMR6_DESC
- : MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr),
- !strconcat("lwm16", "\t$rt, $addr"), [],
- FrmI>,
+ : MicroMipsInst16<(outs reglist16:$rt),
+ (ins MemBaseSPRegList:$base, mem_mm_4sp_lsl2:$offset),
+ !strconcat("lwm16", "\t$rt, ${offset}(${base})"), [],
+ FrmI>,
MMR6Arch<"lwm16"> {
- let DecoderMethod = "DecodeMemMMReglistImm4Lsl2";
let mayLoad = 1;
ComplexPattern Addr = addr;
}
class SWM16_MMR6_DESC
- : MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr),
- !strconcat("swm16", "\t$rt, $addr"), [],
- FrmI>,
+ : MicroMipsInst16<(outs),
+ (ins reglist16:$rt,
+ MemBaseSPRegList:$base, mem_mm_4sp_lsl2:$offset),
+ !strconcat("swm16", "\t$rt, ${offset}(${base})"), [],
+ FrmI>,
MMR6Arch<"swm16"> {
- let DecoderMethod = "DecodeMemMMReglistImm4Lsl2";
let mayStore = 1;
ComplexPattern Addr = addr;
}
class SB16_MMR6_DESC_BASE<string opstr, DAGOperand RTOpnd,
- Operand MemOpnd>
- : MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI>,
+ Operand MemOpnd>
+ : MicroMipsInst16<(outs),
+ (ins RTOpnd:$rt, GPRMM16Opnd:$base, MemOpnd:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI>,
MMR6Arch<opstr> {
- let DecoderMethod = "DecodeMemMMImm4";
let mayStore = 1;
}
@@ -1139,10 +1132,11 @@ class SW16_MMR6_DESC
: SB16_MMR6_DESC_BASE<"sw16", GPRMM16OpndZero, mem_mm_4_lsl2>;
class SWSP_MMR6_DESC
- : MicroMipsInst16<(outs), (ins GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset),
- !strconcat("sw", "\t$rt, $offset"), [], FrmI>,
+ : MicroMipsInst16<(outs),
+ (ins GPR32Opnd:$rt, MemBaseSP:$base,
+ mem_mm_sp_imm5_lsl2:$offset),
+ !strconcat("sw", "\t$rt, ${offset}(${base})"), [], FrmI>,
MMR6Arch<"swsp"> {
- let DecoderMethod = "DecodeMemMMSPImm5Lsl2";
let mayStore = 1;
}
@@ -1363,9 +1357,8 @@ def SIGRIE_MMR6 : R6MMR6Rel, SIGRIE_MMR6_DESC, SIGRIE_MMR6_ENC,
ISA_MICROMIPS32R6;
def XOR_MMR6 : StdMMR6Rel, XOR_MMR6_DESC, XOR_MMR6_ENC, ISA_MICROMIPS32R6;
def XORI_MMR6 : StdMMR6Rel, XORI_MMR6_DESC, XORI_MMR6_ENC, ISA_MICROMIPS32R6;
-let DecoderMethod = "DecodeMemMMImm16" in {
- def SW_MMR6 : StdMMR6Rel, SW_MMR6_DESC, SW_MMR6_ENC, ISA_MICROMIPS32R6;
-}
+def SW_MMR6 : StdMMR6Rel, SW_MMR6_DESC, SW_MMR6_ENC, ISA_MICROMIPS32R6;
+
/// Floating Point Instructions
let mayRaiseFPException = 1, Uses = [FCR31] in {
def FADD_S_MMR6 : StdMMR6Rel, FADD_S_MMR6_ENC, FADD_S_MMR6_DESC,
@@ -1668,8 +1661,10 @@ def : MipsInstAlias<"b16 $offset", (BC16_MMR6 brtarget10_mm:$offset), 0>,
//
//===----------------------------------------------------------------------===//
-def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr),
- (SW16_MMR6 GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS32R6;
+def : MipsPat<(store GPRMM16:$src,
+ (addrimm4lsl2 MemBase:$addr_base, iPTR:$addr_offset)),
+ (SW16_MMR6 GPRMM16:$src, $addr_base, $addr_offset)>,
+ ISA_MICROMIPS32R6;
def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
(SUBU_MMR6 GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS32R6;
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
index 0c4344dde095e5..4860b3b962cb14 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
@@ -285,12 +285,12 @@ let DecoderNamespace = "MicroMips" in {
}
}
-let DecoderNamespace = "MicroMips", DecoderMethod = "DecodeFMemMMR2" in {
- def LDC1_MM_D32 : MMRel, LW_FT<"ldc1", AFGR64Opnd, mem_mm_16, load>,
+let DecoderNamespace = "MicroMips" in {
+ def LDC1_MM_D32 : MMRel, LW_FT<"ldc1", AFGR64MemOpnd, mem_mm_16, load>,
LW_FM_MM<0x2f>, ISA_MICROMIPS, FGR_32 {
let BaseOpcode = "LDC132";
}
- def SDC1_MM_D32 : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_mm_16, store>,
+ def SDC1_MM_D32 : MMRel, SW_FT<"sdc1", AFGR64MemOpnd, mem_mm_16, store>,
LW_FM_MM<0x2e>, ISA_MICROMIPS, FGR_32 {
let BaseOpcode = "SDC164";
}
@@ -300,7 +300,7 @@ let DecoderNamespace = "MicroMips", DecoderMethod = "DecodeFMemMMR2" in {
LW_FM_MM<0x26>, ISA_MICROMIPS;
}
-let DecoderNamespace = "Mips64", DecoderMethod = "DecodeFMemMMR2" in {
+let DecoderNamespace = "Mips64" in {
def LDC1_MM_D64 : MMRel, LW_FT<"ldc1", FGR64Opnd, mem_mm_16, load>,
LW_FM_MM<0x2f>, ISA_MICROMIPS, FGR_64 {
let BaseOpcode = "LDC164";
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td
index ff2b0ff491a3c0..d621d3bb568a8f 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td
@@ -119,17 +119,19 @@ class ADDIUR2_FM_MM16 {
class LOAD_STORE_FM_MM16<bits<6> op> {
bits<3> rt;
- bits<7> addr;
+ bits<3> base;
+ bits<4> offset;
bits<16> Inst;
let Inst{15-10} = op;
let Inst{9-7} = rt;
- let Inst{6-4} = addr{6-4};
- let Inst{3-0} = addr{3-0};
+ let Inst{6-4} = base;
+ let Inst{3-0} = offset;
}
class LOAD_STORE_SP_FM_MM16<bits<6> op> {
+ bits<0> base;
bits<5> rt;
bits<5> offset;
@@ -141,6 +143,7 @@ class LOAD_STORE_SP_FM_MM16<bits<6> op> {
}
class LOAD_GP_FM_MM16<bits<6> op> {
+ bits<0> base;
bits<3> rt;
bits<7> offset;
@@ -388,9 +391,8 @@ class SRLV_FM_MM<bits<10> funct, bit rotate> : MMArch {
class LW_FM_MM<bits<6> op> : MMArch {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
@@ -402,9 +404,8 @@ class LW_FM_MM<bits<6> op> : MMArch {
class POOL32C_LHUE_FM_MM<bits<6> op, bits<4> fmt, bits<3> funct> : MMArch {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
@@ -417,23 +418,23 @@ class POOL32C_LHUE_FM_MM<bits<6> op, bits<4> fmt, bits<3> funct> : MMArch {
}
class LWL_FM_MM<bits<4> funct> : MMArch {
+ bits<12> offset;
+ bits<5> base;
bits<5> rt;
- bits<21> addr;
bits<32> Inst;
let Inst{31-26} = 0x18;
let Inst{25-21} = rt;
- let Inst{20-16} = addr{20-16};
+ let Inst{20-16} = base;
let Inst{15-12} = funct;
- let Inst{11-0} = addr{11-0};
+ let Inst{11-0} = offset;
}
class POOL32C_STEVA_LDEVA_FM_MM<bits<4> type, bits<3> funct> : MMArch {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
@@ -610,14 +611,13 @@ class SYNC_FM_MM : MMArch {
}
class SYNCI_FM_MM : MMArch {
- bits<21> addr;
- bits<5> rs = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
let Inst{31-26} = 0b010000;
let Inst{25-21} = 0b10000;
- let Inst{20-16} = rs;
+ let Inst{20-16} = base;
let Inst{15-0} = offset;
}
@@ -698,23 +698,23 @@ class TEQI_FM_MM<bits<5> funct> : MMArch {
}
class LL_FM_MM<bits<4> funct> : MMArch {
+ bits<12> offset;
+ bits<5> base;
bits<5> rt;
- bits<21> addr;
bits<32> Inst;
let Inst{31-26} = 0x18;
let Inst{25-21} = rt;
- let Inst{20-16} = addr{20-16};
+ let Inst{20-16} = base;
let Inst{15-12} = funct;
- let Inst{11-0} = addr{11-0};
+ let Inst{11-0} = offset;
}
class LLE_FM_MM<bits<4> funct> : MMArch {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
@@ -970,35 +970,36 @@ class LWXS_FM_MM<bits<10> funct> {
}
class LWM_FM_MM<bits<4> funct> : MMArch {
+ bits<12> offset;
+ bits<5> base;
bits<5> rt;
- bits<21> addr;
bits<32> Inst;
let Inst{31-26} = 0x8;
let Inst{25-21} = rt;
- let Inst{20-16} = addr{20-16};
+ let Inst{20-16} = base;
let Inst{15-12} = funct;
- let Inst{11-0} = addr{11-0};
+ let Inst{11-0} = offset;
}
class LWM_FM_MM16<bits<4> funct> : MMArch {
bits<2> rt;
- bits<4> addr;
+ bits<0> base;
+ bits<4> offset;
bits<16> Inst;
let Inst{15-10} = 0x11;
let Inst{9-6} = funct;
let Inst{5-4} = rt;
- let Inst{3-0} = addr;
+ let Inst{3-0} = offset;
}
class CACHE_PREF_FM_MM<bits<6> op, bits<4> funct> : MMArch {
- bits<21> addr;
bits<5> hint;
- bits<5> base = addr{20-16};
- bits<12> offset = addr{11-0};
+ bits<5> base;
+ bits<12> offset;
bits<32> Inst;
@@ -1010,10 +1011,9 @@ class CACHE_PREF_FM_MM<bits<6> op, bits<4> funct> : MMArch {
}
class CACHE_PREFE_FM_MM<bits<6> op, bits<3> funct> : MMArch {
- bits<21> addr;
bits<5> hint;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
index dff57a5d59dc16..400ee1831745dc 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -50,110 +50,96 @@ def immZExt2Shift : ImmLeaf<i32, [{return Imm >= 1 && Imm <= 8;}]>;
def immLi16 : ImmLeaf<i32, [{return Imm >= -1 && Imm <= 126;}]>;
-def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass {
- let Name = "MicroMipsMem";
- let RenderMethod = "addMicroMipsMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithGRPMM16Base";
-}
-
-class mem_mm_4_generic : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops ptr_gpr16mm_rc, simm4);
+class UImmOffsetAsmOperand<int Bits, int Shift = 0, int Bias = 0>
+ : AsmOperandClass {
+ let ParserMethod = "parseMemOffsetOperand";
+ let Name = "UImmOffset" # Bits # "_" # Shift #
+ !if(!lt(Bias, 0), "Minus", "") #
+ !cast<string>(!if(!lt(Bias, 0), !sub(0, Bias), Bias));
+ let SuperClasses = [SImmPtrAsmOperand];
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod =
+ "isScaledUImm<" # Bits # ", " # Shift # ", " # Bias # ">";
+ let DiagnosticType = "ConstantMemOffset";
+}
+
+class UImmOffset<int Bits, int Shift = 0, int Bias = 0> : Operand<i32> {
+ let EncoderMethod = "getScaledImmOpValue<" # Shift # ">";
+ let DecoderMethod = "DecodeUImmWithOffsetAndScale<" # Bits # ", 0, " #
+ !shl(1, Shift) # ">";
+ let ParserMatchClass = UImmOffsetAsmOperand<Bits, Shift, Bias>;
let OperandType = "OPERAND_MEMORY";
- let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand;
}
-def mem_mm_4 : mem_mm_4_generic {
- let EncoderMethod = "getMemEncodingMMImm4";
+def mem_mm_4 : UImmOffset<4>;
+def mem_mm_4_lsl1 : UImmOffset<4, 1>;
+def mem_mm_4_lsl2 : UImmOffset<4, 2>;
+def mem_mm_4_lbu : UImmOffset<4, 0, -1> {
+ let DecoderMethod = "DecodeLBU16Offset";
}
-def mem_mm_4_lsl1 : mem_mm_4_generic {
- let EncoderMethod = "getMemEncodingMMImm4Lsl1";
+def MemBaseSPAsmOperand : MipsAsmRegOperand {
+ let Name = "MemBaseSP";
+ let SuperClasses = [PtrRegAsmOperand];
+ let PredicateMethod = "isSPAsmReg";
+ let RenderMethod = "addPtrRegOperands";
}
-def mem_mm_4_lsl2 : mem_mm_4_generic {
- let EncoderMethod = "getMemEncodingMMImm4Lsl2";
+def MemBaseGPAsmOperand : MipsAsmRegOperand {
+ let Name = "MemBaseGP";
+ let SuperClasses = [PtrRegAsmOperand];
+ let PredicateMethod = "isGPAsmReg";
+ let RenderMethod = "addPtrRegOperands";
}
-def MicroMipsMemSPAsmOperand : AsmOperandClass {
- let Name = "MicroMipsMemSP";
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>";
+def MemBaseSP : RegisterOperand<ptr_sp_rc> {
+ let ParserMatchClass = MemBaseSPAsmOperand;
+ let DecoderMethod = "DecodeFixedPtrRegister<29>";
}
-def MicroMipsMemGPAsmOperand : AsmOperandClass {
- let Name = "MicroMipsMemGP";
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithSimmWordAlignedOffsetGP<9>";
+def MemBaseGP : RegisterOperand<ptr_gp_rc> {
+ let ParserMatchClass = MemBaseGPAsmOperand;
+ let DecoderMethod = "DecodeFixedPtrRegister<28>";
}
-def mem_mm_sp_imm5_lsl2 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops ptr_sp_rc:$base, simm5:$offset);
- let OperandType = "OPERAND_MEMORY";
- let ParserMatchClass = MicroMipsMemSPAsmOperand;
- let EncoderMethod = "getMemEncodingMMSPImm5Lsl2";
-}
+def mem_mm_sp_imm5_lsl2 : UImmOffset<5, 2>;
+def mem_mm_gp_simm7_lsl2
+ : MemoryOffset<simm7_lsl2, SImmOffsetAsmOperand<7, 2, "SImm7_Lsl2">>;
-def mem_mm_gp_simm7_lsl2 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops ptr_gp_rc:$base, simm7_lsl2:$offset);
- let OperandType = "OPERAND_MEMORY";
- let ParserMatchClass = MicroMipsMemGPAsmOperand;
- let EncoderMethod = "getMemEncodingMMGPImm7Lsl2";
+// A register list expands to a variable number of MC operands. Address
+// operands follow it, so their encoders locate them from the end.
+def MemBaseRegList : RegisterOperand<mips_ptr_rc> {
+ let ParserMatchClass = PtrRegAsmOperand;
+ let DecoderMethod = "DecodePtrRegisterClass";
+ let EncoderMethod = "getOperandFromEndValue<2>";
+ let PrintMethod = "printOperandFromEnd<2>";
}
-def mem_mm_9 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops mips_ptr_rc, simm9);
- let EncoderMethod = "getMemEncodingMMImm9";
- let ParserMatchClass = MipsMemSimmAsmOperand<9>;
- let OperandType = "OPERAND_MEMORY";
+def MemBaseSPRegList : RegisterOperand<ptr_sp_rc> {
+ let ParserMatchClass = MemBaseSPAsmOperand;
+ let DecoderMethod = "DecodeFixedPtrRegister<29>";
+ let PrintMethod = "printOperandFromEnd<2>";
}
-def mem_mm_11 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPR32, simm11);
- let EncoderMethod = "getMemEncodingMMImm11";
- let ParserMatchClass = MipsMemSimmAsmOperand<11>;
- let OperandType = "OPERAND_MEMORY";
+class RegListMemoryOffset<Operand Offset, int Shift = 0>
+ : MemoryOffset<Offset, Offset.ParserMatchClass> {
+ let EncoderMethod = "getOperandFromEndValue<1, " # Shift # ">";
+ let PrintMethod = "printOperandFromEnd<1>";
}
-def mem_mm_12 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops mips_ptr_rc, simm12);
- let EncoderMethod = "getMemEncodingMMImm12";
- let ParserMatchClass = MipsMemAsmOperand;
- let OperandType = "OPERAND_MEMORY";
-}
+def mem_mm_12 : MemoryOffset<simm12, AnyOffsetAsmOperand>;
-def mem_mm_16 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops mips_ptr_rc, simm16);
- let EncoderMethod = "getMemEncodingMMImm16";
- let DecoderMethod = "DecodeMemMMImm16";
- let ParserMatchClass = MipsMemSimmAsmOperand<16>;
- let OperandType = "OPERAND_MEMORY";
+def mem_mm_12_reglist : RegListMemoryOffset<mem_mm_12>;
+def mem_mm_4sp : RegListMemoryOffset<simm6, 2> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<4, 0, 4>";
+ let ParserMatchClass = UImmOffsetAsmOperand<6>;
}
-def MipsMemUimm4AsmOperand : AsmOperandClass {
- let Name = "MemOffsetUimm4";
- let SuperClasses = [MipsMemAsmOperand];
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithUimmOffsetSP<6>";
-}
+def mem_mm_4sp_lsl2 : RegListMemoryOffset<mem_mm_4_lsl2, 2>;
-def mem_mm_4sp : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops ptr_sp_rc, uimm8);
- let EncoderMethod = "getMemEncodingMMImm4sp";
- let ParserMatchClass = MipsMemUimm4AsmOperand;
- let OperandType = "OPERAND_MEMORY";
-}
+def mem_mm_9 : MemoryOffset<simm9, SImmOffsetAsmOperand<9>>;
+def mem_mm_11 : MemoryOffset<simm11, SImmOffsetAsmOperand<11>>;
+def mem_mm_16 : MemoryOffset<simm16, SImmOffsetAsmOperand<16>>;
def jmptarget_mm : Operand<OtherVT> {
let EncoderMethod = "getJumpTargetOpValueMM";
@@ -205,12 +191,12 @@ class CompactBranchMM<string opstr, DAGOperand opnd, RegisterOperand RO> :
let canFoldAsLoad = 1 in
class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
- Operand MemOpnd> :
- InstSE<(outs RO:$rt), (ins MemOpnd:$addr, RO:$src),
- !strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, (OpNode addrimm12:$addr, RO:$src))],
+ Operand MemOpnd> :
+ InstSE<(outs RO:$rt), (ins MemBase:$base, MemOpnd:$offset, RO:$src),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(set RO:$rt,
+ (OpNode (addrimm12 MemBase:$base, iPTR:$offset), RO:$src))],
FrmI> {
- let DecoderMethod = "DecodeMemMMImm12";
string Constraints = "$src = $rt";
let BaseOpcode = opstr;
bit mayLoad = 1;
@@ -218,11 +204,10 @@ class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
}
class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
- Operand MemOpnd>:
- InstSE<(outs), (ins RO:$rt, MemOpnd:$addr),
- !strconcat(opstr, "\t$rt, $addr"),
- [(OpNode RO:$rt, addrimm12:$addr)], FrmI> {
- let DecoderMethod = "DecodeMemMMImm12";
+ Operand MemOpnd> :
+ InstSE<(outs), (ins RO:$rt, MemBase:$base, MemOpnd:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(OpNode RO:$rt, (addrimm12 MemBase:$base, iPTR:$offset))], FrmI> {
let BaseOpcode = opstr;
bit mayLoad = 0;
bit mayStore = 1;
@@ -238,49 +223,51 @@ MicroMipsInst16<(outs RO1:$rd1, RO2:$rd2), (ins RO3:$rs, RO3:$rt),
let DecoderMethod = "DecodeMovePOperands";
}
+// Paired transfers encode the first data register and imply the next one.
+def GPR32PairOpnd : Operand<i32> {
+ let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd);
+ let ParserMatchClass = GPR32AsmOperand;
+ let DecoderMethod = "DecodeGPR32Pair";
+}
+
class StorePairMM<string opstr>
- : InstSE<(outs), (ins GPR32Opnd:$rt, GPR32Opnd:$rt2, mem_simm12:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI, opstr> {
- let DecoderMethod = "DecodeMemMMImm12";
+ : InstSE<(outs), (ins GPR32PairOpnd:$rt,
+ MemBase:$base, mem_simm12:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI, opstr> {
let mayStore = 1;
let AsmMatchConverter = "ConvertXWPOperands";
}
class LoadPairMM<string opstr>
- : InstSE<(outs GPR32Opnd:$rt, GPR32Opnd:$rt2), (ins mem_simm12:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI, opstr> {
- let DecoderMethod = "DecodeMemMMImm12";
+ : InstSE<(outs GPR32PairOpnd:$rt), (ins MemBase:$base, mem_simm12:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI, opstr> {
let mayLoad = 1;
let AsmMatchConverter = "ConvertXWPOperands";
}
class LLBaseMM<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$rt), (ins mem_mm_12:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMImm12";
+ InstSE<(outs RO:$rt), (ins MemBase:$base, mem_mm_12:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let mayLoad = 1;
}
class LLEBaseMM<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$rt), (ins mem_simm9:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMImm9";
+ InstSE<(outs RO:$rt), (ins MemBase:$base, mem_simm9:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
string BaseOpcode = opstr;
let mayLoad = 1;
}
class SCBaseMM<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$dst), (ins RO:$rt, mem_mm_12:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMImm12";
+ InstSE<(outs RO:$dst), (ins RO:$rt, MemBase:$base, mem_mm_12:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let mayStore = 1;
let Constraints = "$rt = $dst";
}
class SCEBaseMM<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$dst), (ins RO:$rt, mem_simm9:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMImm9";
+ InstSE<(outs RO:$dst), (ins RO:$rt, MemBase:$base, mem_simm9:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
string BaseOpcode = opstr;
let mayStore = 1;
let Constraints = "$rt = $dst";
@@ -288,10 +275,10 @@ class SCEBaseMM<string opstr, RegisterOperand RO> :
class LoadMM<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
DAGOperand MO = mem_mm_12> :
- InstSE<(outs RO:$rt), (ins MO:$addr),
- !strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, (OpNode addrimm12:$addr))], FrmI, opstr> {
- let DecoderMethod = "DecodeMemMMImm12";
+ InstSE<(outs RO:$rt), (ins MemBase:$base, MO:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(set RO:$rt, (OpNode (addrimm12 MemBase:$base, iPTR:$offset)))],
+ FrmI, opstr> {
let canFoldAsLoad = 1;
let mayLoad = 1;
}
@@ -327,39 +314,34 @@ class ShiftIMM16<string opstr, Operand ImmOpnd, RegisterOperand RO> :
!strconcat(opstr, "\t$rd, $rt, $shamt"), [], FrmR>;
class LoadMM16<string opstr, DAGOperand RO, Operand MemOpnd> :
- MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMImm4";
+ MicroMipsInst16<(outs RO:$rt), (ins GPRMM16Opnd:$base, MemOpnd:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let canFoldAsLoad = 1;
let mayLoad = 1;
}
class StoreMM16<string opstr, DAGOperand RTOpnd, Operand MemOpnd> :
- MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMImm4";
+ MicroMipsInst16<(outs), (ins RTOpnd:$rt, GPRMM16Opnd:$base, MemOpnd:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let mayStore = 1;
}
class LoadSPMM16<string opstr, DAGOperand RO, Operand MemOpnd> :
- MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset),
- !strconcat(opstr, "\t$rt, $offset"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMSPImm5Lsl2";
+ MicroMipsInst16<(outs RO:$rt), (ins MemBaseSP:$base, MemOpnd:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let canFoldAsLoad = 1;
let mayLoad = 1;
}
class StoreSPMM16<string opstr, DAGOperand RO, Operand MemOpnd> :
- MicroMipsInst16<(outs), (ins RO:$rt, MemOpnd:$offset),
- !strconcat(opstr, "\t$rt, $offset"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMSPImm5Lsl2";
+ MicroMipsInst16<(outs), (ins RO:$rt, MemBaseSP:$base, MemOpnd:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let mayStore = 1;
}
class LoadGPMM16<string opstr, DAGOperand RO, Operand MemOpnd> :
- MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset),
- !strconcat(opstr, "\t$rt, $offset"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMGPImm7Lsl2";
+ MicroMipsInst16<(outs RO:$rt), (ins MemBaseGP:$base, MemOpnd:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let canFoldAsLoad = 1;
let mayLoad = 1;
}
@@ -528,30 +510,30 @@ def reglist16 : Operand<i32> {
}
class StoreMultMM<string opstr> :
- InstSE<(outs), (ins reglist:$rt, mem_mm_12:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI, opstr> {
- let DecoderMethod = "DecodeMemMMImm12";
+ InstSE<(outs), (ins reglist:$rt,
+ MemBaseRegList:$base, mem_mm_12_reglist:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI, opstr> {
let mayStore = 1;
}
class LoadMultMM<string opstr> :
- InstSE<(outs reglist:$rt), (ins mem_mm_12:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI, opstr> {
- let DecoderMethod = "DecodeMemMMImm12";
+ InstSE<(outs reglist:$rt),
+ (ins MemBaseRegList:$base, mem_mm_12_reglist:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI, opstr> {
let mayLoad = 1;
}
class StoreMultMM16<string opstr> :
- MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMReglistImm4Lsl2";
+ MicroMipsInst16<(outs), (ins reglist16:$rt,
+ MemBaseSPRegList:$base, mem_mm_4sp:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let mayStore = 1;
}
class LoadMultMM16<string opstr> :
- MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMemMMReglistImm4Lsl2";
+ MicroMipsInst16<(outs reglist16:$rt),
+ (ins MemBaseSPRegList:$base, mem_mm_4sp:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let mayLoad = 1;
}
@@ -617,7 +599,7 @@ let FastISelShouldIgnore = 1 in {
def XOR16_MM : LogicRMM16<"xor16", GPRMM16Opnd, xor>,
LOGIC_FM_MM16<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6;
}
-def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, mem_mm_4>,
+def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, mem_mm_4_lbu>,
LOAD_STORE_FM_MM16<0x02>, ISA_MICROMIPS;
def LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, mem_mm_4_lsl1>,
LOAD_STORE_FM_MM16<0x0a>, ISA_MICROMIPS;
@@ -784,55 +766,51 @@ let DecoderNamespace = "MicroMips" in {
}
/// Load and Store Instructions - aligned
- let DecoderMethod = "DecodeMemMMImm16" in {
- def LB_MM : LoadMemory<"lb", GPR32Opnd, mem_mm_16, sextloadi8>,
- MMRel, LW_FM_MM<0x7>, ISA_MICROMIPS;
- def LBu_MM : LoadMemory<"lbu", GPR32Opnd, mem_mm_16, zextloadi8>,
- MMRel, LW_FM_MM<0x5>, ISA_MICROMIPS;
- def LH_MM : LoadMemory<"lh", GPR32Opnd, mem_simmptr, sextloadi16,
- addrDefault>, MMRel, LW_FM_MM<0xf>, ISA_MICROMIPS;
- def LHu_MM : LoadMemory<"lhu", GPR32Opnd, mem_simmptr, zextloadi16>,
- MMRel, LW_FM_MM<0xd>, ISA_MICROMIPS;
- def LW_MM : Load<"lw", GPR32Opnd>, MMRel, LW_FM_MM<0x3f>,
- ISA_MICROMIPS;
- def SB_MM : Store<"sb", GPR32Opnd, truncstorei8>, MMRel,
- LW_FM_MM<0x6>, ISA_MICROMIPS;
- def SH_MM : Store<"sh", GPR32Opnd, truncstorei16>, MMRel,
- LW_FM_MM<0xe>, ISA_MICROMIPS;
- def SW_MM : Store<"sw", GPR32Opnd>, MMRel,
- LW_FM_MM<0x3e>, ISA_MICROMIPS;
- }
-
- let DecoderMethod = "DecodeMemMMImm9" in {
- def LBE_MM : MMRel, Load<"lbe", GPR32Opnd>,
- POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>, ISA_MICROMIPS, ASE_EVA;
- def LBuE_MM : MMRel, Load<"lbue", GPR32Opnd>,
- POOL32C_LHUE_FM_MM<0x18, 0x6, 0x0>, ISA_MICROMIPS, ASE_EVA;
- def LHE_MM : MMRel, LoadMemory<"lhe", GPR32Opnd, mem_simm9>,
- POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>, ISA_MICROMIPS, ASE_EVA;
- def LHuE_MM : MMRel, LoadMemory<"lhue", GPR32Opnd, mem_simm9>,
- POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>, ISA_MICROMIPS, ASE_EVA;
- def LWE_MM : MMRel, LoadMemory<"lwe", GPR32Opnd, mem_simm9>,
- POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>, ISA_MICROMIPS, ASE_EVA;
- def SBE_MM : MMRel, StoreMemory<"sbe", GPR32Opnd, mem_simm9>,
- POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>, ISA_MICROMIPS, ASE_EVA;
- def SHE_MM : MMRel, StoreMemory<"she", GPR32Opnd, mem_simm9>,
- POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>, ISA_MICROMIPS, ASE_EVA;
- def SWE_MM : MMRel, StoreMemory<"swe", GPR32Opnd, mem_simm9>,
- POOL32C_LHUE_FM_MM<0x18, 0xa, 0x7>, ISA_MICROMIPS, ASE_EVA;
- def LWLE_MM : MMRel, LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_9>,
- POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x2>,
- ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
- def LWRE_MM : MMRel, LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_9>,
- POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x3>,
- ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
- def SWLE_MM : MMRel, StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_9>,
- POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x0>,
- ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
- def SWRE_MM : MMRel, StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_9>,
- POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x1>,
- ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
- }
+ def LB_MM : LoadMemory<"lb", GPR32Opnd, mem_mm_16, sextloadi8>,
+ MMRel, LW_FM_MM<0x7>, ISA_MICROMIPS;
+ def LBu_MM : LoadMemory<"lbu", GPR32Opnd, mem_mm_16, zextloadi8>,
+ MMRel, LW_FM_MM<0x5>, ISA_MICROMIPS;
+ def LH_MM : LoadMemory<"lh", GPR32Opnd, mem_simmptr, sextloadi16,
+ addrDefault>, MMRel, LW_FM_MM<0xf>, ISA_MICROMIPS;
+ def LHu_MM : LoadMemory<"lhu", GPR32Opnd, mem_simmptr, zextloadi16>,
+ MMRel, LW_FM_MM<0xd>, ISA_MICROMIPS;
+ def LW_MM : Load<"lw", GPR32Opnd>, MMRel, LW_FM_MM<0x3f>,
+ ISA_MICROMIPS;
+ def SB_MM : Store<"sb", GPR32Opnd, truncstorei8>, MMRel,
+ LW_FM_MM<0x6>, ISA_MICROMIPS;
+ def SH_MM : Store<"sh", GPR32Opnd, truncstorei16>, MMRel,
+ LW_FM_MM<0xe>, ISA_MICROMIPS;
+ def SW_MM : Store<"sw", GPR32Opnd>, MMRel,
+ LW_FM_MM<0x3e>, ISA_MICROMIPS;
+
+ def LBE_MM : MMRel, Load<"lbe", GPR32Opnd>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>, ISA_MICROMIPS, ASE_EVA;
+ def LBuE_MM : MMRel, Load<"lbue", GPR32Opnd>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x0>, ISA_MICROMIPS, ASE_EVA;
+ def LHE_MM : MMRel, LoadMemory<"lhe", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>, ISA_MICROMIPS, ASE_EVA;
+ def LHuE_MM : MMRel, LoadMemory<"lhue", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>, ISA_MICROMIPS, ASE_EVA;
+ def LWE_MM : MMRel, LoadMemory<"lwe", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>, ISA_MICROMIPS, ASE_EVA;
+ def SBE_MM : MMRel, StoreMemory<"sbe", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>, ISA_MICROMIPS, ASE_EVA;
+ def SHE_MM : MMRel, StoreMemory<"she", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>, ISA_MICROMIPS, ASE_EVA;
+ def SWE_MM : MMRel, StoreMemory<"swe", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0xa, 0x7>, ISA_MICROMIPS, ASE_EVA;
+ def LWLE_MM : MMRel, LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_9>,
+ POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x2>,
+ ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
+ def LWRE_MM : MMRel, LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_9>,
+ POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x3>,
+ ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
+ def SWLE_MM : MMRel, StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_9>,
+ POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x0>,
+ ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
+ def SWRE_MM : MMRel, StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_9>,
+ POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x1>,
+ ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>,
ISA_MICROMIPS;
@@ -857,12 +835,14 @@ let DecoderNamespace = "MicroMips" in {
/// Load and Store multiple pseudo Instructions
class LoadWordMultMM<string instr_asm > :
- MipsAsmPseudoInst<(outs reglist:$rt), (ins mem_mm_12:$addr),
- !strconcat(instr_asm, "\t$rt, $addr")> ;
+ MipsAsmPseudoInst<(outs reglist:$rt),
+ (ins MemBase:$base, mem_mm_12:$offset),
+ !strconcat(instr_asm, "\t$rt, ${offset}(${base})")>;
class StoreWordMultMM<string instr_asm > :
- MipsAsmPseudoInst<(outs), (ins reglist:$rt, mem_mm_12:$addr),
- !strconcat(instr_asm, "\t$rt, $addr")> ;
+ MipsAsmPseudoInst<(outs),
+ (ins reglist:$rt, MemBase:$base, mem_mm_12:$offset),
+ !strconcat(instr_asm, "\t$rt, ${offset}(${base})")>;
def SWM_MM : StoreWordMultMM<"swm">, ISA_MICROMIPS;
@@ -976,9 +956,8 @@ let DecoderNamespace = "MicroMips" in {
/// Control Instructions
def SYNC_MM : MMRel, SYNC_FT<"sync">, SYNC_FM_MM, ISA_MICROMIPS;
- let DecoderMethod = "DecodeSyncI_MM" in
- def SYNCI_MM : MMRel, SYNCI_FT<"synci", mem_mm_16>, SYNCI_FM_MM,
- ISA_MICROMIPS32_NOT_MIPS32R6;
+ def SYNCI_MM : MMRel, SYNCI_FT<"synci", mem_mm_16>, SYNCI_FM_MM,
+ ISA_MICROMIPS32_NOT_MIPS32R6;
def BREAK_MM : MMRel, BRK_FT<"break">, BRK_FM_MM, ISA_MICROMIPS;
def SYSCALL_MM : MMRel, SYS_FT<"syscall", uimm10>, SYS_FM_MM,
ISA_MICROMIPS;
@@ -1031,19 +1010,16 @@ let DecoderNamespace = "MicroMips" in {
def SCE_MM : MMRel, SCEBaseMM<"sce", GPR32Opnd>, LLE_FM_MM<0xA>,
ISA_MICROMIPS, ASE_EVA;
- let DecoderMethod = "DecodeCacheOpMM" in {
- def CACHE_MM : MMRel, CacheOp<"cache", mem_mm_12>,
- CACHE_PREF_FM_MM<0x08, 0x6>, ISA_MICROMIPS32_NOT_MIPS32R6;
- def PREF_MM : MMRel, CacheOp<"pref", mem_mm_12>,
- CACHE_PREF_FM_MM<0x18, 0x2>, ISA_MICROMIPS32_NOT_MIPS32R6;
- }
+ def CACHE_MM : MMRel, CacheOp<"cache", mem_mm_12>,
+ CACHE_PREF_FM_MM<0x08, 0x6>, ISA_MICROMIPS32_NOT_MIPS32R6;
+ def PREF_MM : MMRel, CacheOp<"pref", mem_mm_12>,
+ CACHE_PREF_FM_MM<0x18, 0x2>, ISA_MICROMIPS32_NOT_MIPS32R6;
+
+ def PREFE_MM : MMRel, CacheOp<"prefe", mem_mm_9>,
+ CACHE_PREFE_FM_MM<0x18, 0x2>, ISA_MICROMIPS, ASE_EVA;
+ def CACHEE_MM : MMRel, CacheOp<"cachee", mem_mm_9>,
+ CACHE_PREFE_FM_MM<0x18, 0x3>, ISA_MICROMIPS, ASE_EVA;
- let DecoderMethod = "DecodePrefeOpMM" in {
- def PREFE_MM : MMRel, CacheOp<"prefe", mem_mm_9>,
- CACHE_PREFE_FM_MM<0x18, 0x2>, ISA_MICROMIPS, ASE_EVA;
- def CACHEE_MM : MMRel, CacheOp<"cachee", mem_mm_9>,
- CACHE_PREFE_FM_MM<0x18, 0x3>, ISA_MICROMIPS, ASE_EVA;
- }
def SSNOP_MM : MMRel, Barrier<"ssnop">, BARRIER_FM_MM<0x1>,
ISA_MICROMIPS;
def EHB_MM : MMRel, Barrier<"ehb">, BARRIER_FM_MM<0x3>,
@@ -1158,9 +1134,12 @@ def : WrapperPat<tblockaddress, ADDiu_MM, GPR32>, ISA_MICROMIPS;
def : WrapperPat<tjumptable, ADDiu_MM, GPR32>, ISA_MICROMIPS;
def : WrapperPat<tglobaltlsaddr, ADDiu_MM, GPR32>, ISA_MICROMIPS;
-def : MipsPat<(atomic_load_asext_8 addr:$a), (LB_MM addr:$a)>, ISA_MICROMIPS;
-def : MipsPat<(atomic_load_asext_16 addr:$a), (LH_MM addr:$a)>, ISA_MICROMIPS;
-def : MipsPat<(atomic_load_nonext_32 addr:$a), (LW_MM addr:$a)>, ISA_MICROMIPS;
+def : MipsPat<(atomic_load_asext_8 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LB_MM $a_base, $a_offset)>, ISA_MICROMIPS;
+def : MipsPat<(atomic_load_asext_16 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LH_MM $a_base, $a_offset)>, ISA_MICROMIPS;
+def : MipsPat<(atomic_load_nonext_32 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LW_MM $a_base, $a_offset)>, ISA_MICROMIPS;
def : MipsPat<(i32 immLi16:$imm),
(LI16_MM immLi16:$imm)>, ISA_MICROMIPS;
@@ -1203,30 +1182,32 @@ def : MipsPat<(sra GPR32:$src, immZExt5:$imm),
def : MipsPat<(sra GPR32:$lhs, GPR32:$rhs),
(SRAV_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS;
-def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr),
- (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS;
-def : MipsPat<(store GPR32:$src, addr:$addr),
- (SW_MM GPR32:$src, addr:$addr)>, ISA_MICROMIPS;
+def : MipsPat<(store GPRMM16:$src,
+ (addrimm4lsl2 MemBase:$addr_base, iPTR:$addr_offset)),
+ (SW16_MM GPRMM16:$src, $addr_base, $addr_offset)>, ISA_MICROMIPS;
+def : MipsPat<(store GPR32:$src, (addr MemBase:$addr_base, iPTR:$addr_offset)),
+ (SW_MM GPR32:$src, $addr_base, $addr_offset)>, ISA_MICROMIPS;
-def : MipsPat<(load addrimm4lsl2:$addr),
- (LW16_MM addrimm4lsl2:$addr)>, ISA_MICROMIPS;
-def : MipsPat<(load addr:$addr),
- (LW_MM addr:$addr)>, ISA_MICROMIPS;
+def : MipsPat<(load (addrimm4lsl2 MemBase:$addr_base, iPTR:$addr_offset)),
+ (LW16_MM $addr_base, $addr_offset)>, ISA_MICROMIPS;
+def : MipsPat<(load (addr MemBase:$addr_base, iPTR:$addr_offset)),
+ (LW_MM $addr_base, $addr_offset)>, ISA_MICROMIPS;
def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
(SUBu_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS;
-def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu_MM addr:$src)>,
- ISA_MICROMIPS;
+def : MipsPat<(i32 (extloadi1 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LBu_MM $src_base, $src_offset)>, ISA_MICROMIPS;
-def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu_MM addr:$src)>,
- ISA_MICROMIPS;
+def : MipsPat<(i32 (extloadi8 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LBu_MM $src_base, $src_offset)>, ISA_MICROMIPS;
-def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu_MM addr:$src)>,
- ISA_MICROMIPS;
+def : MipsPat<(i32 (extloadi16 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LHu_MM $src_base, $src_offset)>, ISA_MICROMIPS;
let AddedComplexity = 40 in
- def : MipsPat<(i32 (sextloadi16 addrRegImm:$a)),
- (LH_MM addrRegImm:$a)>, ISA_MICROMIPS;
+ def : MipsPat<(i32 (sextloadi16
+ (addrRegImm MemBase:$a_base, iPTR:$a_offset))),
+ (LH_MM $a_base, $a_offset)>, ISA_MICROMIPS;
def : MipsPat<(bswap GPR32:$rt), (ROTR_MM (WSBH_MM GPR32:$rt), 16)>,
@@ -1414,6 +1395,7 @@ def : MipsInstAlias<"mtgc0 $rt, $rs",
def : MipsInstAlias<"mthgc0 $rt, $rs",
(MTHGC0_MM COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>,
ISA_MICROMIPS32R5, ASE_VIRT;
-def : MipsInstAlias<"sw $rt, $offset",
- (SWSP_MM GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset), 1>,
+def : MipsInstAlias<"sw $rt, ${offset}(${base})",
+ (SWSP_MM GPR32Opnd:$rt,
+ MemBaseSP:$base, mem_mm_sp_imm5_lsl2:$offset), 1>,
ISA_MICROMIPS;
diff --git a/llvm/lib/Target/Mips/Mips16InstrInfo.td b/llvm/lib/Target/Mips/Mips16InstrInfo.td
index 1505e50de1cf2f..3459cb53a9ce09 100644
--- a/llvm/lib/Target/Mips/Mips16InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips16InstrInfo.td
@@ -16,32 +16,6 @@
def addr16 : ComplexPattern<iPTR, 2, "selectAddr16", [frameindex]>;
def addr16sp : ComplexPattern<iPTR, 2, "selectAddr16SP", [frameindex]>;
-//
-// Address operand
-def mem16 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops CPU16Regs, simm16);
- let EncoderMethod = "getMemEncoding";
-}
-
-def mem16sp : Operand<i32> {
- let PrintMethod = "printMemOperand";
- // This should be CPUSPReg but the MIPS16 subtarget isn't good enough at
- // keeping the sp-relative load and the other varieties separate at the
- // moment. This lie fixes the problem sufficiently well to fix the errors
- // emitted by -verify-machineinstrs and the output ends up correct as long
- // as we use an external assembler (which is already a requirement for MIPS16
- // for several other reasons).
- let MIOperandInfo = (ops CPU16RegsPlusSP, simm16);
- let EncoderMethod = "getMemEncoding";
-}
-
-def mem16_ea : Operand<i32> {
- let PrintMethod = "printMemOperandEA";
- let MIOperandInfo = (ops CPU16RegsPlusSP, simm16);
- let EncoderMethod = "getMemEncoding";
-}
-
def pcrel16 : Operand<i32>;
//
@@ -208,22 +182,22 @@ class FEXT_2RI16_ins<bits<5> _op, string asmstr>:
// EXT-RRI instruction format
//
-class FEXT_RRI16_mem_ins<bits<5> op, string asmstr, Operand MemOpnd>:
- FEXT_RRI16<op, (outs CPU16Regs:$ry), (ins (MemOpnd $rx, $imm16):$addr),
- !strconcat(asmstr, "\t$ry, $addr"), []>;
+class FEXT_RRI16_mem_ins<bits<5> op, string asmstr, RegisterClass BaseRC>:
+ FEXT_RRI16<op, (outs CPU16Regs:$ry), (ins BaseRC:$rx, simm16:$imm16),
+ !strconcat(asmstr, "\t$ry, ${imm16}(${rx})"), []>;
-class FEXT_RRI16_mem2_ins<bits<5> op, string asmstr, Operand MemOpnd>:
- FEXT_RRI16<op, (outs ), (ins CPU16Regs:$ry, (MemOpnd $rx, $imm16):$addr),
- !strconcat(asmstr, "\t$ry, $addr"), []>;
+class FEXT_RRI16_mem2_ins<bits<5> op, string asmstr, RegisterClass BaseRC>:
+ FEXT_RRI16<op, (outs), (ins CPU16Regs:$ry, BaseRC:$rx, simm16:$imm16),
+ !strconcat(asmstr, "\t$ry, ${imm16}(${rx})"), []>;
//
//
// EXT-RRI-A instruction format
//
-class FEXT_RRI_A16_mem_ins<bits<1> op, string asmstr, Operand MemOpnd>:
- FEXT_RRI_A16<op, (outs CPU16Regs:$ry), (ins (MemOpnd $rx, $imm15):$addr),
- !strconcat(asmstr, "\t$ry, $addr"), []>;
+class FEXT_RRI_A16_mem_ins<bits<1> op, string asmstr, RegisterClass BaseRC>:
+ FEXT_RRI_A16<op, (outs CPU16Regs:$ry), (ins BaseRC:$rx, simm16:$imm15),
+ !strconcat(asmstr, "\t$ry, $rx, $imm15"), []>;
//
// EXT-SHIFT instruction format
@@ -511,8 +485,9 @@ def AddiuRxRxImmX16: FEXT_2RI16_ins<0b01001, "addiu">,
}
let DecoderMethod = "DecodeFIXMEInstruction" in
+let FastISelShouldIgnore = 1 in
def AddiuRxRyOffMemX16:
- FEXT_RRI_A16_mem_ins<0, "addiu", mem16_ea>;
+ FEXT_RRI_A16_mem_ins<0, "addiu", CPU16RegsPlusSP>;
//
@@ -759,7 +734,7 @@ def JrcRx16: FRR16_JALRC_ins<1, 1, 0, "jrc"> {
// Purpose: Load Byte (Extended)
// To load a byte from memory as a signed value.
//
-def LbRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lb", mem16>, MayLoad{
+def LbRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lb", CPU16Regs>, MayLoad{
let isCodeGenOnly = 1;
}
@@ -769,7 +744,7 @@ def LbRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lb", mem16>, MayLoad{
// To load a byte from memory as a unsigned value.
//
def LbuRxRyOffMemX16:
- FEXT_RRI16_mem_ins<0b10100, "lbu", mem16>, MayLoad {
+ FEXT_RRI16_mem_ins<0b10100, "lbu", CPU16Regs>, MayLoad {
let isCodeGenOnly = 1;
}
@@ -778,7 +753,7 @@ def LbuRxRyOffMemX16:
// Purpose: Load Halfword signed (Extended)
// To load a halfword from memory as a signed value.
//
-def LhRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10100, "lh", mem16>, MayLoad{
+def LhRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10100, "lh", CPU16Regs>, MayLoad{
let isCodeGenOnly = 1;
}
@@ -788,7 +763,7 @@ def LhRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10100, "lh", mem16>, MayLoad{
// To load a halfword from memory as an unsigned value.
//
def LhuRxRyOffMemX16:
- FEXT_RRI16_mem_ins<0b10100, "lhu", mem16>, MayLoad {
+ FEXT_RRI16_mem_ins<0b10100, "lhu", CPU16Regs>, MayLoad {
let isCodeGenOnly = 1;
}
@@ -815,7 +790,7 @@ def LiRxImmAlignX16: FEXT_RI16_ins<0b01101, ".align 2\n\tli"> {
// Purpose: Load Word (Extended)
// To load a word from memory as a signed value.
//
-def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16>, MayLoad{
+def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", CPU16Regs>, MayLoad{
let isCodeGenOnly = 1;
}
@@ -824,7 +799,9 @@ def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16>, MayLoad{
// To load an SP-relative word from memory as a signed value.
//
let DecoderMethod = "DecodeFIXMEInstruction" in
-def LwRxSpImmX16: FEXT_RRI16_mem_ins<0b10010, "lw", mem16sp>, MayLoad;
+// The MIPS16 selector does not yet distinguish all SP-relative forms.
+// Keep CPU16RegsPlusSP here until it can constrain the base to CPUSPReg.
+def LwRxSpImmX16: FEXT_RRI16_mem_ins<0b10010, "lw", CPU16RegsPlusSP>, MayLoad;
def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw">, MayLoad;
@@ -983,7 +960,7 @@ def SaveX16:
//
let DecoderMethod = "DecodeFIXMEInstruction" in
def SbRxRyOffMemX16:
- FEXT_RRI16_mem2_ins<0b11000, "sb", mem16>, MayStore;
+ FEXT_RRI16_mem2_ins<0b11000, "sb", CPU16Regs>, MayStore;
//
// Format: SEB rx MIPS16e
@@ -1122,7 +1099,7 @@ def SelTBtneZSltiu: SeliT<"btnez", "sltiu">;
//
let DecoderMethod = "DecodeFIXMEInstruction" in
def ShRxRyOffMemX16:
- FEXT_RRI16_mem2_ins<0b11001, "sh", mem16>, MayStore;
+ FEXT_RRI16_mem2_ins<0b11001, "sh", CPU16Regs>, MayStore;
//
// Format: SLL rx, ry, sa MIPS16e
@@ -1258,7 +1235,7 @@ def SubuRxRyRz16: FRRR16_ins<0b11, "subu">, ArithLogic16Defs<0>;
// To store a word to memory.
//
let DecoderMethod = "DecodeFIXMEInstruction" in
-def SwRxRyOffMemX16: FEXT_RRI16_mem2_ins<0b11011, "sw", mem16>, MayStore;
+def SwRxRyOffMemX16: FEXT_RRI16_mem2_ins<0b11011, "sw", CPU16Regs>, MayStore;
//
// Format: SW rx, offset(sp) MIPS16e
@@ -1266,7 +1243,7 @@ def SwRxRyOffMemX16: FEXT_RRI16_mem2_ins<0b11011, "sw", mem16>, MayStore;
// To store an SP-relative word to memory.
//
let DecoderMethod = "DecodeFIXMEInstruction" in
-def SwRxSpImmX16: FEXT_RRI16_mem2_ins<0b11010, "sw", mem16sp>, MayStore;
+def SwRxSpImmX16: FEXT_RRI16_mem2_ins<0b11010, "sw", CPU16RegsPlusSP>, MayStore;
//
//
@@ -1321,7 +1298,8 @@ def: shift_rotate_reg16_pat<sra, SravRxRy16>;
def: shift_rotate_reg16_pat<srl, SrlvRxRy16>;
class LoadM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> :
- Mips16Pat<(OpNode Addr:$addr), (I Addr:$addr)>;
+ Mips16Pat<(OpNode (Addr CPU16RegsPlusSP:$base, iPTR:$offset)),
+ (I $base, $offset)>;
def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16, addr16>;
def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16, addr16>;
@@ -1330,7 +1308,9 @@ def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16, addr16>;
def: LoadM16_pat<load, LwRxSpImmX16, addr16sp>;
class StoreM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> :
- Mips16Pat<(OpNode CPU16Regs:$r, Addr:$addr), (I CPU16Regs:$r, Addr:$addr)>;
+ Mips16Pat<(OpNode CPU16Regs:$r,
+ (Addr CPU16RegsPlusSP:$base, iPTR:$offset)),
+ (I CPU16Regs:$r, $base, $offset)>;
def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16, addr16>;
def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16, addr16>;
@@ -1380,7 +1360,8 @@ class SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>:
(I CPU16Regs:$rx, imm_type:$imm16)>;
-def: Mips16Pat<(i32 addr16sp:$addr), (AddiuRxRyOffMemX16 addr16sp:$addr)>;
+def: Mips16Pat<(i32 (addr16sp CPU16RegsPlusSP:$base, iPTR:$offset)),
+ (AddiuRxRyOffMemX16 $base, $offset)>;
// Large (>16 bit) immediate loads
@@ -1852,10 +1833,12 @@ class Wrapper16Pat<SDNode node, Instruction ADDiuOp, RegisterClass RC>:
def : Wrapper16Pat<tglobaladdr, AddiuRxRxImmX16, CPU16Regs>;
def : Wrapper16Pat<tglobaltlsaddr, AddiuRxRxImmX16, CPU16Regs>;
-def : Mips16Pat<(i32 (extloadi8 addr16:$src)),
- (LbuRxRyOffMemX16 addr16:$src)>;
-def : Mips16Pat<(i32 (extloadi16 addr16:$src)),
- (LhuRxRyOffMemX16 addr16:$src)>;
+def : Mips16Pat<(i32 (extloadi8
+ (addr16 CPU16RegsPlusSP:$src_base, iPTR:$src_offset))),
+ (LbuRxRyOffMemX16 $src_base, $src_offset)>;
+def : Mips16Pat<(i32 (extloadi16
+ (addr16 CPU16RegsPlusSP:$src_base, iPTR:$src_offset))),
+ (LhuRxRyOffMemX16 $src_base, $src_offset)>;
def: Mips16Pat<(trap), (Break16)>;
diff --git a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td
index f0b02c6419a794..1e9800b024dd87 100644
--- a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td
+++ b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td
@@ -331,10 +331,9 @@ class SPECIAL3_2R_FM<OPCODE6 Operation> : MipsR6Inst {
}
class SPECIAL3_MEM_FM<OPCODE6 Operation> : MipsR6Inst {
- bits<21> addr;
bits<5> hint;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
@@ -497,9 +496,8 @@ class SPECIAL3_DALIGN_FM<OPCODE6 Operation> : MipsR6Inst {
class SPECIAL3_LL_SC_FM<OPCODE6 Operation> : MipsR6Inst {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
@@ -508,8 +506,6 @@ class SPECIAL3_LL_SC_FM<OPCODE6 Operation> : MipsR6Inst {
let Inst{20-16} = rt;
let Inst{15-7} = offset;
let Inst{5-0} = Operation.Value;
-
- string DecoderMethod = "DecodeSpecial3LlSc";
}
class SPECIAL_LSA_FM<OPCODE6 Operation> : MipsR6Inst {
@@ -574,9 +570,8 @@ class JR_HB_R6_FM<OPCODE6 Operation> : MipsR6Inst {
class COP2LDST_FM<OPCODE5 Operation> : MipsR6Inst {
bits<5> rt;
- bits<21> addr;
- bits<5> base = addr{20-16};
- bits<11> offset = addr{10-0};
+ bits<5> base;
+ bits<11> offset;
bits<32> Inst;
diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
index 5283a5da43eee8..377b82c41e5736 100644
--- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
@@ -676,10 +676,9 @@ class CLASS_D_DESC : CLASS_RINT_DESC_BASE<"class.d", FGR64Opnd>;
class CACHE_HINT_DESC<string instr_asm, Operand MemOpnd>
: MipsR6Arch<instr_asm> {
dag OutOperandList = (outs);
- dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint);
- string AsmString = !strconcat(instr_asm, "\t$hint, $addr");
+ dag InOperandList = (ins MemBase:$base, MemOpnd:$offset, uimm5:$hint);
+ string AsmString = !strconcat(instr_asm, "\t$hint, ${offset}(${base})");
list<dag> Pattern = [];
- string DecoderMethod = "DecodeCacheeOp_CacheOpR6";
}
class CACHE_DESC : CACHE_HINT_DESC<"cache", mem_simm9>;
@@ -687,11 +686,10 @@ class PREF_DESC : CACHE_HINT_DESC<"pref", mem_simm9>;
class COP2LD_DESC_BASE<string instr_asm, RegisterOperand COPOpnd> {
dag OutOperandList = (outs COPOpnd:$rt);
- dag InOperandList = (ins mem_simm11:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins MemBase:$base, mem_simm11:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
bit mayLoad = 1;
- string DecoderMethod = "DecodeFMemCop2R6";
}
class LDC2_R6_DESC : COP2LD_DESC_BASE<"ldc2", COP2Opnd>;
@@ -699,11 +697,10 @@ class LWC2_R6_DESC : COP2LD_DESC_BASE<"lwc2", COP2Opnd>;
class COP2ST_DESC_BASE<string instr_asm, RegisterOperand COPOpnd> {
dag OutOperandList = (outs);
- dag InOperandList = (ins COPOpnd:$rt, mem_simm11:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins COPOpnd:$rt, MemBase:$base, mem_simm11:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
bit mayStore = 1;
- string DecoderMethod = "DecodeFMemCop2R6";
}
class SDC2_R6_DESC : COP2ST_DESC_BASE<"sdc2", COP2Opnd>;
@@ -724,8 +721,8 @@ class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
Operand MemOpnd>
: MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rt);
- dag InOperandList = (ins MemOpnd:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins MemBase:$base, MemOpnd:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
bit mayLoad = 1;
}
@@ -734,8 +731,8 @@ class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9_exp>;
class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs GPROpnd:$dst);
- dag InOperandList = (ins GPROpnd:$rt, mem_simm9_exp:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins GPROpnd:$rt, MemBase:$base, mem_simm9_exp:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
bit mayStore = 1;
string Constraints = "$rt = $dst";
diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td
index b6d820bbc10256..4e8a76be90d2cb 100644
--- a/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -620,10 +620,14 @@ class Saa<string opstr>:
def SAA : Saa<"saa">, SAA_FM<0x18>, ASE_CNMIPSP;
def SAAD : Saa<"saad">, SAA_FM<0x19>, ASE_CNMIPSP;
-def SaaAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr),
- "saa\t$rt, $addr">, ASE_CNMIPSP;
-def SaadAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr),
- "saad\t$rt, $addr">, ASE_CNMIPSP;
+def SaaAddr : MipsAsmPseudoInst<(outs),
+ (ins GPR64Opnd:$rt, MemBase:$base,
+ imm_offset:$offset),
+ "saa\t$rt, ${offset}(${base})">, ASE_CNMIPSP;
+def SaadAddr : MipsAsmPseudoInst<(outs),
+ (ins GPR64Opnd:$rt, MemBase:$base,
+ imm_offset:$offset),
+ "saad\t$rt, ${offset}(${base})">, ASE_CNMIPSP;
}
}
@@ -666,14 +670,14 @@ def : MipsPat<(i64 immZExt32:$imm),
(LO16 imm:$imm))>, ISA_MIPS3, GPR_64;
// extended loads
-def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3,
- GPR_64;
-def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3,
- GPR_64;
-def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>, ISA_MIPS3,
- GPR_64;
-def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>, ISA_MIPS3,
- GPR_64;
+def : MipsPat<(i64 (extloadi1 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LB64 $src_base, $src_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(i64 (extloadi8 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LB64 $src_base, $src_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(i64 (extloadi16 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LH64 $src_base, $src_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(i64 (extloadi32 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LW64 $src_base, $src_offset)>, ISA_MIPS3, GPR_64;
// hi/lo relocs
let AdditionalPredicates = [NotInMicroMips] in
@@ -910,20 +914,27 @@ def : MipsPat<(brcond (i32 (setne (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:
ASE_MIPS64_CNMIPS;
// Atomic load patterns.
-def : MipsPat<(atomic_load_asext_8 addr:$a), (LB64 addr:$a)>, ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_load_asext_16 addr:$a), (LH64 addr:$a)>, ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_load_asext_32 addr:$a), (LW64 addr:$a)>, ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_load_nonext_64 addr:$a), (LD addr:$a)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_load_asext_8 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LB64 $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_load_asext_16 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LH64 $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_load_asext_32 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LW64 $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_load_nonext_64 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LD $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
// Atomic store patterns.
-def : MipsPat<(atomic_store_8 GPR64:$v, addr:$a), (SB64 GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_store_16 GPR64:$v, addr:$a), (SH64 GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_store_32 GPR64:$v, addr:$a), (SW64 GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_store_64 GPR64:$v, addr:$a), (SD GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_store_8 GPR64:$v, (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SB64 GPR64:$v, $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_store_16 GPR64:$v,
+ (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SH64 GPR64:$v, $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_store_32 GPR64:$v,
+ (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SW64 GPR64:$v, $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_store_64 GPR64:$v,
+ (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SD GPR64:$v, $a_base, $a_offset)>, ISA_MIPS3, GPR_64;
// Patterns used for matching away redundant sign extensions.
// MIPS32 arithmetic instructions sign extend their result implicitly.
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
index d2d7e491223c3c..78d976e73e0576 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -673,38 +673,6 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
if (closeP) O << ")";
}
-void MipsAsmPrinter::
-printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) {
- // Load/Store memory operands -- imm($reg)
- // If PIC target the target is loaded as the
- // pattern lw $25,%call16($28)
-
- // opNum can be invalid if instruction has reglist as operand.
- // MemOperand is always last operand of instruction (base + offset).
- switch (MI->getOpcode()) {
- default:
- break;
- case Mips::SWM32_MM:
- case Mips::LWM32_MM:
- opNum = MI->getNumOperands() - 2;
- break;
- }
-
- printOperand(MI, opNum+1, O);
- O << "(";
- printOperand(MI, opNum, O);
- O << ")";
-}
-
-void MipsAsmPrinter::
-printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) {
- // when using stack locations for not load/store instructions
- // print the same way as all normal 3 operand instructions.
- printOperand(MI, opNum, O);
- O << ", ";
- printOperand(MI, opNum+1, O);
-}
-
void MipsAsmPrinter::printFCCOperand(const MachineInstr *MI, int opNum,
raw_ostream &O) {
const MachineOperand &MO = MI->getOperand(opNum);
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.h b/llvm/lib/Target/Mips/MipsAsmPrinter.h
index a7e18ab008c7c2..0f6253a053581b 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.h
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.h
@@ -148,8 +148,6 @@ class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter {
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
const char *ExtraCode, raw_ostream &O) override;
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
- void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
- void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O);
void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
void printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O);
void emitStartOfAsmFile(Module &M) override;
diff --git a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td
index 9d7f12fbe01ecc..d77ee15f6bd068 100644
--- a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td
@@ -1311,14 +1311,14 @@ def : BitconvertPat<f32, v4i8, FGR32, DSPR>;
def : BitconvertPat<v2i16, f32, DSPR, FGR32>;
def : BitconvertPat<v4i8, f32, DSPR, FGR32>;
-def : DSPPat<(v2i16 (load addr:$a)),
- (v2i16 (COPY_TO_REGCLASS (LW addr:$a), DSPR))>;
-def : DSPPat<(v4i8 (load addr:$a)),
- (v4i8 (COPY_TO_REGCLASS (LW addr:$a), DSPR))>;
-def : DSPPat<(store (v2i16 DSPR:$val), addr:$a),
- (SW (COPY_TO_REGCLASS DSPR:$val, GPR32), addr:$a)>;
-def : DSPPat<(store (v4i8 DSPR:$val), addr:$a),
- (SW (COPY_TO_REGCLASS DSPR:$val, GPR32), addr:$a)>;
+def : DSPPat<(v2i16 (load (addr MemBase:$a_base, iPTR:$a_offset))),
+ (v2i16 (COPY_TO_REGCLASS (LW $a_base, $a_offset), DSPR))>;
+def : DSPPat<(v4i8 (load (addr MemBase:$a_base, iPTR:$a_offset))),
+ (v4i8 (COPY_TO_REGCLASS (LW $a_base, $a_offset), DSPR))>;
+def : DSPPat<(store (v2i16 DSPR:$val), (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SW (COPY_TO_REGCLASS DSPR:$val, GPR32), $a_base, $a_offset)>;
+def : DSPPat<(store (v4i8 DSPR:$val), (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SW (COPY_TO_REGCLASS DSPR:$val, GPR32), $a_base, $a_offset)>;
// Binary operations.
class DSPBinPat<Instruction Inst, ValueType ValTy, SDPatternOperator Node,
diff --git a/llvm/lib/Target/Mips/MipsEVAInstrFormats.td b/llvm/lib/Target/Mips/MipsEVAInstrFormats.td
index ec786c56c744e8..e4c7bdacde7e95 100644
--- a/llvm/lib/Target/Mips/MipsEVAInstrFormats.td
+++ b/llvm/lib/Target/Mips/MipsEVAInstrFormats.td
@@ -58,10 +58,9 @@ def OPGROUP_COP0_TLB : OPGROUP<0b010000>;
//===----------------------------------------------------------------------===//
class SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6 Operation> : MipsEVAInst {
- bits<21> addr;
bits<5> rt;
- bits<5> base = addr{20-16};
- bits<9> offset = addr{8-0};
+ bits<5> base;
+ bits<9> offset;
bits<32> Inst;
diff --git a/llvm/lib/Target/Mips/MipsEVAInstrInfo.td b/llvm/lib/Target/Mips/MipsEVAInstrInfo.td
index e8bb88c6955c68..cb940854e8bcab 100644
--- a/llvm/lib/Target/Mips/MipsEVAInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsEVAInstrInfo.td
@@ -52,10 +52,9 @@ class PREFE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_PREFE>;
// Memory Load/Store EVA descriptions
class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs GPROpnd:$rt);
- dag InOperandList = (ins mem_simm9:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins MemBase:$base, mem_simm9:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
- string DecoderMethod = "DecodeMemEVA";
bit canFoldAsLoad = 1;
string BaseOpcode = instr_asm;
bit mayLoad = 1;
@@ -69,10 +68,9 @@ class LWE_DESC : LOAD_EVA_DESC_BASE<"lwe", GPR32Opnd>;
class STORE_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs);
- dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins GPROpnd:$rt, MemBase:$base, mem_simm9:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
- string DecoderMethod = "DecodeMemEVA";
string BaseOpcode = instr_asm;
bit mayStore = 1;
}
@@ -84,10 +82,9 @@ class SWE_DESC : STORE_EVA_DESC_BASE<"swe", GPR32Opnd>;
// Load/Store Left/Right EVA descriptions
class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs GPROpnd:$rt);
- dag InOperandList = (ins mem_simm9:$addr, GPROpnd:$src);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins MemBase:$base, mem_simm9:$offset, GPROpnd:$src);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
- string DecoderMethod = "DecodeMemEVA";
string BaseOpcode = instr_asm;
string Constraints = "$src = $rt";
bit canFoldAsLoad = 1;
@@ -100,10 +97,9 @@ class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd>;
class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs);
- dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins GPROpnd:$rt, MemBase:$base, mem_simm9:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
- string DecoderMethod = "DecodeMemEVA";
string BaseOpcode = instr_asm;
bit mayLoad = 0;
bit mayStore = 1;
@@ -115,25 +111,23 @@ class SWRE_DESC : STORE_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd>;
// Load-linked EVA, Store-conditional EVA descriptions
class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs GPROpnd:$rt);
- dag InOperandList = (ins mem_simm9:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins MemBase:$base, mem_simm9:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
string BaseOpcode = instr_asm;
bit mayLoad = 1;
- string DecoderMethod = "DecodeMemEVA";
}
class LLE_DESC : LLE_DESC_BASE<"lle", GPR32Opnd>;
class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs GPROpnd:$dst);
- dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
- string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ dag InOperandList = (ins GPROpnd:$rt, MemBase:$base, mem_simm9:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$rt, ${offset}(${base})");
list<dag> Pattern = [];
string BaseOpcode = instr_asm;
bit mayStore = 1;
string Constraints = "$rt = $dst";
- string DecoderMethod = "DecodeMemEVA";
}
class SCE_DESC : SCE_DESC_BASE<"sce", GPR32Opnd>;
@@ -154,11 +148,10 @@ class CACHEE_DESC_BASE<string instr_asm, Operand MemOpnd> {
bits<5> rt = hint;
dag OutOperandList = (outs);
- dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint);
- string AsmString = !strconcat(instr_asm, "\t$hint, $addr");
+ dag InOperandList = (ins MemBase:$base, MemOpnd:$offset, uimm5:$hint);
+ string AsmString = !strconcat(instr_asm, "\t$hint, ${offset}(${base})");
list<dag> Pattern = [];
string BaseOpcode = instr_asm;
- string DecoderMethod = "DecodeCacheeOp_CacheOpR6";
}
class CACHEE_DESC : CACHEE_DESC_BASE<"cachee", mem_simm9>;
diff --git a/llvm/lib/Target/Mips/MipsInstrFPU.td b/llvm/lib/Target/Mips/MipsInstrFPU.td
index 1555e17572334b..f1944c784dc1a7 100644
--- a/llvm/lib/Target/Mips/MipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MipsInstrFPU.td
@@ -204,20 +204,29 @@ class MTC1_64_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC> :
let Constraints = "$fs = $fs_in";
}
+// Doubleword transfers encode all 32 FPR numbers, including odd ones when
+// the selected register model otherwise uses paired single registers.
+def AFGR64MemOpnd : RegisterOperand<AFGR64> {
+ let ParserMatchClass = AFGR64AsmOperand;
+ let DecoderMethod = "DecodeFGR64RegisterClass";
+}
+
class LW_FT<string opstr, RegisterOperand RC, DAGOperand MO,
SDPatternOperator OpNode = null_frag> :
- InstSE<(outs RC:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(set RC:$rt, (OpNode addrDefault:$addr))], FrmFI, opstr>,
+ InstSE<(outs RC:$rt), (ins MemBase:$base, MO:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(set RC:$rt, (OpNode (addrDefault MemBase:$base, iPTR:$offset)))],
+ FrmFI, opstr>,
HARDFLOAT {
- let DecoderMethod = "DecodeFMem";
let mayLoad = 1;
}
class SW_FT<string opstr, RegisterOperand RC, DAGOperand MO,
SDPatternOperator OpNode = null_frag> :
- InstSE<(outs), (ins RC:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(OpNode RC:$rt, addrDefault:$addr)], FrmFI, opstr>, HARDFLOAT {
- let DecoderMethod = "DecodeFMem";
+ InstSE<(outs), (ins RC:$rt, MemBase:$base, MO:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(OpNode RC:$rt, (addrDefault MemBase:$base, iPTR:$offset))],
+ FrmFI, opstr>, HARDFLOAT {
let mayStore = 1;
}
@@ -670,11 +679,11 @@ let DecoderNamespace = "MipsFP64", AdditionalPredicates = [NotInMicroMips] in {
}
let AdditionalPredicates = [NotInMicroMips] in {
- def LDC1 : MMRel, StdMMR6Rel, LW_FT<"ldc1", AFGR64Opnd, mem_simm16,
+ def LDC1 : MMRel, StdMMR6Rel, LW_FT<"ldc1", AFGR64MemOpnd, mem_simm16,
load>, LW_FM<0x35>, ISA_MIPS2, FGR_32 {
let BaseOpcode = "LDC132";
}
- def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_simm16, store>,
+ def SDC1 : MMRel, SW_FT<"sdc1", AFGR64MemOpnd, mem_simm16, store>,
LW_FM<0x3d>, ISA_MIPS2, FGR_32;
}
@@ -905,34 +914,41 @@ def LoadImmDoubleFGR : MipsAsmPseudoInst<(outs StrictlyFGR64Opnd:$rd),
FGR_64, HARDFLOAT;
def SDC1_M1 : MipsAsmPseudoInst<(outs AFGR64Opnd:$fd),
- (ins mem_simm16:$addr),
- "s.d\t$fd, $addr">,
+ (ins MemBase:$base, mem_simm16:$offset),
+ "s.d\t$fd, ${offset}(${base})">,
FGR_32, ISA_MIPS1, HARDFLOAT;
//===----------------------------------------------------------------------===//
// InstAliases.
//===----------------------------------------------------------------------===//
def : MipsInstAlias
- <"s.s $fd, $addr", (SWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>,
+ <"s.s $fd, ${offset}(${base})",
+ (SWC1 FGR32Opnd:$fd, MemBase:$base, mem_simm16:$offset), 0>,
ISA_MIPS2, HARDFLOAT;
def : MipsInstAlias
- <"s.d $fd, $addr", (SDC1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>,
+ <"s.d $fd, ${offset}(${base})",
+ (SDC1 AFGR64Opnd:$fd, MemBase:$base, mem_simm16:$offset), 0>,
FGR_32, ISA_MIPS2, HARDFLOAT;
def : MipsInstAlias
- <"s.d $fd, $addr", (SDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>,
+ <"s.d $fd, ${offset}(${base})",
+ (SDC164 FGR64Opnd:$fd, MemBase:$base, mem_simm16:$offset), 0>,
FGR_64, ISA_MIPS2, HARDFLOAT;
def : MipsInstAlias
- <"s.d $fd, $addr", (SDC1_M1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>,
+ <"s.d $fd, ${offset}(${base})",
+ (SDC1_M1 AFGR64Opnd:$fd, MemBase:$base, mem_simm16:$offset), 0>,
FGR_32, ISA_MIPS1, HARDFLOAT;
def : MipsInstAlias
- <"l.s $fd, $addr", (LWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>,
+ <"l.s $fd, ${offset}(${base})",
+ (LWC1 FGR32Opnd:$fd, MemBase:$base, mem_simm16:$offset), 0>,
ISA_MIPS2, HARDFLOAT;
def : MipsInstAlias
- <"l.d $fd, $addr", (LDC1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>,
+ <"l.d $fd, ${offset}(${base})",
+ (LDC1 AFGR64Opnd:$fd, MemBase:$base, mem_simm16:$offset), 0>,
FGR_32, ISA_MIPS2, HARDFLOAT;
def : MipsInstAlias
- <"l.d $fd, $addr", (LDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>,
+ <"l.d $fd, ${offset}(${base})",
+ (LDC164 FGR64Opnd:$fd, MemBase:$base, mem_simm16:$offset), 0>,
FGR_64, ISA_MIPS2, HARDFLOAT;
multiclass C_COND_ALIASES<string TypeStr, RegisterOperand RC> {
diff --git a/llvm/lib/Target/Mips/MipsInstrFormats.td b/llvm/lib/Target/Mips/MipsInstrFormats.td
index 5240550130d3cc..7b4b012185c2fe 100644
--- a/llvm/lib/Target/Mips/MipsInstrFormats.td
+++ b/llvm/lib/Target/Mips/MipsInstrFormats.td
@@ -422,15 +422,14 @@ class SYNC_FM : StdArch {
}
class SYNCI_FM : StdArch {
- // Produced by the mem_simm16 address as reg << 16 | imm (see getMemEncoding).
- bits<21> addr;
- bits<5> rs = addr{20-16};
- bits<16> offset = addr{15-0};
+ // Base register and signed displacement are encoded separately.
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
let Inst{31-26} = 0b000001;
- let Inst{25-21} = rs;
+ let Inst{25-21} = base;
let Inst{20-16} = 0b11111;
let Inst{15-0} = offset;
}
@@ -718,14 +717,15 @@ class MFC1_FM<bits<5> funct> : StdArch {
class LW_FM<bits<6> op> : StdArch {
bits<5> rt;
- bits<21> addr;
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
let Inst{31-26} = op;
- let Inst{25-21} = addr{20-16};
+ let Inst{25-21} = base;
let Inst{20-16} = rt;
- let Inst{15-0} = addr{15-0};
+ let Inst{15-0} = offset;
}
class MADDS_FM<bits<3> funct, bits<3> fmt> : StdArch {
@@ -918,10 +918,9 @@ class COP0_TLB_FM<bits<6> op> : StdArch {
}
class CACHEOP_FM<bits<6> op> : StdArch {
- bits<21> addr;
bits<5> hint;
- bits<5> base = addr{20-16};
- bits<16> offset = addr{15-0};
+ bits<5> base;
+ bits<16> offset;
bits<32> Inst;
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 3b523af856d1cf..7adb54e01fc22a 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -1063,7 +1063,8 @@ foreach I = {4, 5, 6, 9, 10, 11} in
foreach I = {1, 2, 3} in
def simm10_lsl # I : Operand<i32> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, " # I # ">";
+ let DecoderMethod =
+ "DecodeSImmWithOffsetAndScale<10, 0, " # !shl(1, I) # ">";
let ParserMatchClass =
!cast<AsmOperandClass>("ConstantSImm10Lsl" # I # "AsmOperandClass");
}
@@ -1082,8 +1083,8 @@ foreach I = {5, 10} in
}
def simm7_lsl2 : Operand<OtherVT> {
- let EncoderMethod = "getSImm7Lsl2Encoding";
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ", 0, 4>";
+ let EncoderMethod = "getScaledImmOpValue<2>";
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<7, 0, 4>";
let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass;
}
@@ -1120,30 +1121,6 @@ def li16_imm : Operand<i32> {
let ParserMatchClass = ConstantUImm7Sub1AsmOperandClass;
}
-def MipsMemAsmOperand : AsmOperandClass {
- let Name = "Mem";
- let ParserMethod = "parseMemOperand";
-}
-
-class MipsMemSimmAsmOperand<int Width, int Shift = 0> : AsmOperandClass {
- let Name = "MemOffsetSimm" # Width # "_" # Shift;
- let SuperClasses = [MipsMemAsmOperand];
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithSimmOffset<" # Width # ", " # Shift # ">";
- let DiagnosticType = !if(!eq(Shift, 0), "MemSImm" # Width,
- "MemSImm" # Width # "Lsl" # Shift);
-}
-
-def MipsMemSimmPtrAsmOperand : AsmOperandClass {
- let Name = "MemOffsetSimmPtr";
- let SuperClasses = [MipsMemAsmOperand];
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithPtrSizeOffset";
- let DiagnosticType = "MemSImmPtr";
-}
-
def MipsInvertedImmoperand : AsmOperandClass {
let Name = "InvNum";
let RenderMethod = "addImmOperands";
@@ -1158,55 +1135,94 @@ def InvertedImOperand64 : Operand<i64> {
let ParserMatchClass = MipsInvertedImmoperand;
}
-class mem_generic : Operand<iPTR> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops mips_ptr_rc, simm16);
- let EncoderMethod = "getMemEncoding";
- let ParserMatchClass = MipsMemAsmOperand;
+// Memory base registers follow the ABI pointer width.
+def PtrRegAsmOperand : MipsAsmRegOperand {
+ let Name = "PtrReg";
+ let PredicateMethod = "isGPRAsmReg";
+ let RenderMethod = "addPtrRegOperands";
+}
+
+def MemBase : RegisterOperand<mips_ptr_rc> {
+ let ParserMatchClass = PtrRegAsmOperand;
+ let DecoderMethod = "DecodePtrRegisterClass";
let OperandType = "OPERAND_MEMORY";
}
-// Address operand
-def mem : mem_generic;
+def AnyOffsetAsmOperand : AsmOperandClass {
+ let ParserMethod = "parseMemOffsetOperand";
+ let Name = "AnyOffset";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isImm";
+}
-// MSA specific address operand
-def mem_msa : mem_generic {
- let MIOperandInfo = (ops mips_ptr_rc, simm10);
- let EncoderMethod = "getMSAMemEncoding";
+def SImmPtrAsmOperand : AsmOperandClass {
+ let ParserMethod = "parseMemOffsetOperand";
+ let Name = "SImmPtr";
+ let SuperClasses = [AnyOffsetAsmOperand];
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isSImmPtr";
+ let DiagnosticType = "MemSImmPtr";
}
-def simm12 : Operand<i32> {
- let DecoderMethod = "DecodeSimm12";
+class SImmOffsetAsmOperand<int Bits, int Shift = 0,
+ string Diagnostic =
+ !if(!eq(Shift, 0), "MemSImm" # Bits,
+ "MemSImm" # Bits # "Lsl" # Shift)>
+ : AsmOperandClass {
+ let ParserMethod = "parseMemOffsetOperand";
+ let Name = "SImmOffset" # Bits # "_" # Shift;
+ let SuperClasses = [SImmPtrAsmOperand];
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">";
+ let DiagnosticType = Diagnostic;
}
-def mem_simm9_exp : mem_generic {
- let MIOperandInfo = (ops mips_ptr_rc, simm9);
- let ParserMatchClass = MipsMemSimmPtrAsmOperand;
- let OperandNamespace = "MipsII";
- let OperandType = "OPERAND_MEM_SIMM9";
+// Retain memory offset metadata for assembler macro expansion.
+class MemoryOffset<Operand Offset, AsmOperandClass MatchClass>
+ : Operand<Offset.Type> {
+ let EncoderMethod = Offset.EncoderMethod;
+ let DecoderMethod = Offset.DecoderMethod;
+ let ParserMatchClass = MatchClass;
+ let OperandType = "OPERAND_MEMORY";
+}
+
+def imm_offset : MemoryOffset<i32imm, AnyOffsetAsmOperand> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>";
+}
+
+def simm12 : Operand<i32> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<12>";
}
foreach I = {9, 10, 11, 12, 16} in
- def mem_simm # I : mem_generic {
- let MIOperandInfo = (ops mips_ptr_rc, !cast<Operand>("simm" # I));
- let ParserMatchClass = MipsMemSimmAsmOperand<I>;
- }
+ def mem_simm # I : MemoryOffset<!cast<Operand>("simm" # I),
+ SImmOffsetAsmOperand<I>>;
foreach I = {1, 2, 3} in
- def mem_simm10_lsl # I : mem_generic {
- let MIOperandInfo = (ops mips_ptr_rc, !cast<Operand>("simm10_lsl" # I));
- let EncoderMethod = "getMemEncoding<" # I # ">";
- let ParserMatchClass = MipsMemSimmAsmOperand<10, I>;
+ def mem_simm10_lsl # I : MemoryOffset<!cast<Operand>("simm10_lsl" # I),
+ SImmOffsetAsmOperand<10, I>> {
+ let EncoderMethod = "getScaledImmOpValue<" # I # ">";
}
-def mem_simmptr : mem_generic {
- let ParserMatchClass = MipsMemSimmPtrAsmOperand;
+def mem_simmptr : MemoryOffset<simm16, SImmPtrAsmOperand>;
+// These offsets permit values that require assembler macro expansion.
+def mem_simm9_exp : MemoryOffset<simm9, SImmPtrAsmOperand> {
+ let OperandNamespace = "MipsII";
+ let OperandType = "OPERAND_MEM_SIMM9";
+}
+
+// Load-address macros retain their compound address operand.
+def MipsMemAsmOperand : AsmOperandClass {
+ let Name = "Mem";
+ let ParserMethod = "parseMemOperand";
+ let PredicateMethod = "isMemOperand";
+ let RenderMethod = "addMemOperands";
}
-def mem_ea : Operand<iPTR> {
- let PrintMethod = "printMemOperandEA";
- let MIOperandInfo = (ops mips_ptr_rc, simm16);
- let EncoderMethod = "getMemEncoding";
+def mem : Operand<iPTR> {
+ let MIOperandInfo = (ops MemBase, imm_offset);
+ let ParserMatchClass = MipsMemAsmOperand;
+ let PrintMethod = "printMemOperand";
let OperandType = "OPERAND_MEMORY";
}
@@ -1422,9 +1438,10 @@ class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>:
class LoadMemory<string opstr, DAGOperand RO, DAGOperand MO,
SDPatternOperator OpNode = null_frag,
ComplexPattern Addr = addr> :
- InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, (OpNode Addr:$addr))], FrmI, opstr> {
- let DecoderMethod = "DecodeMem";
+ InstSE<(outs RO:$rt), (ins MemBase:$base, MO:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(set RO:$rt, (OpNode (Addr MemBase:$base, iPTR:$offset)))],
+ FrmI, opstr> {
let canFoldAsLoad = 1;
string BaseOpcode = opstr;
let mayLoad = 1;
@@ -1432,73 +1449,75 @@ class LoadMemory<string opstr, DAGOperand RO, DAGOperand MO,
class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
ComplexPattern Addr = addr> :
- LoadMemory<opstr, RO, mem, OpNode, Addr>;
+ LoadMemory<opstr, RO, imm_offset, OpNode, Addr>;
class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO,
- SDPatternOperator OpNode = null_frag,
- ComplexPattern Addr = addr> :
- InstSE<(outs), (ins RO:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(OpNode RO:$rt, Addr:$addr)], FrmI, opstr> {
- let DecoderMethod = "DecodeMem";
+ SDPatternOperator OpNode = null_frag,
+ ComplexPattern Addr = addr> :
+ InstSE<(outs), (ins RO:$rt, MemBase:$base, MO:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(OpNode RO:$rt, (Addr MemBase:$base, iPTR:$offset))], FrmI, opstr> {
string BaseOpcode = opstr;
let mayStore = 1;
}
class Store<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
- ComplexPattern Addr = addr, DAGOperand MO = mem> :
+ ComplexPattern Addr = addr, DAGOperand MO = imm_offset> :
StoreMemory<opstr, RO, MO, OpNode, Addr>;
// Load/Store Left/Right
let canFoldAsLoad = 1 in
class LoadLeftRight<string opstr, SDNode OpNode, RegisterOperand RO> :
- InstSE<(outs RO:$rt), (ins mem:$addr, RO:$src),
- !strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, (OpNode addr:$addr, RO:$src))], FrmI> {
- let DecoderMethod = "DecodeMem";
+ InstSE<(outs RO:$rt), (ins MemBase:$base, imm_offset:$offset, RO:$src),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(set RO:$rt, (OpNode (addr MemBase:$base, iPTR:$offset), RO:$src))],
+ FrmI> {
string Constraints = "$src = $rt";
let BaseOpcode = opstr;
}
class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO> :
- InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(OpNode RO:$rt, addr:$addr)], FrmI> {
- let DecoderMethod = "DecodeMem";
+ InstSE<(outs), (ins RO:$rt, MemBase:$base, imm_offset:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(OpNode RO:$rt, (addr MemBase:$base, iPTR:$offset))], FrmI> {
let BaseOpcode = opstr;
}
// COP2 Load/Store
class LW_FT2<string opstr, RegisterOperand RC,
- SDPatternOperator OpNode= null_frag> :
- InstSE<(outs RC:$rt), (ins mem_simm16:$addr),
- !strconcat(opstr, "\t$rt, $addr"),
- [(set RC:$rt, (OpNode addrDefault:$addr))], FrmFI, opstr> {
- let DecoderMethod = "DecodeFMem2";
+ SDPatternOperator OpNode = null_frag> :
+ InstSE<(outs RC:$rt), (ins MemBase:$base, mem_simm16:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(set RC:$rt, (OpNode (addrDefault MemBase:$base, iPTR:$offset)))],
+ FrmFI, opstr> {
let mayLoad = 1;
}
class SW_FT2<string opstr, RegisterOperand RC,
- SDPatternOperator OpNode= null_frag> :
- InstSE<(outs), (ins RC:$rt, mem_simm16:$addr),
- !strconcat(opstr, "\t$rt, $addr"),
- [(OpNode RC:$rt, addrDefault:$addr)], FrmFI, opstr> {
- let DecoderMethod = "DecodeFMem2";
+ SDPatternOperator OpNode = null_frag> :
+ InstSE<(outs), (ins RC:$rt, MemBase:$base, mem_simm16:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(OpNode RC:$rt, (addrDefault MemBase:$base, iPTR:$offset))],
+ FrmFI, opstr> {
let mayStore = 1;
}
// COP3 Load/Store
class LW_FT3<string opstr, RegisterOperand RC,
- SDPatternOperator OpNode= null_frag> :
- InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(set RC:$rt, (OpNode addrDefault:$addr))], FrmFI, opstr> {
- let DecoderMethod = "DecodeFMem3";
+ SDPatternOperator OpNode = null_frag> :
+ InstSE<(outs RC:$rt), (ins MemBase:$base, imm_offset:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(set RC:$rt, (OpNode (addrDefault MemBase:$base, iPTR:$offset)))],
+ FrmFI, opstr> {
let mayLoad = 1;
}
class SW_FT3<string opstr, RegisterOperand RC,
- SDPatternOperator OpNode= null_frag> :
- InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(OpNode RC:$rt, addrDefault:$addr)], FrmFI, opstr> {
- let DecoderMethod = "DecodeFMem3";
+ SDPatternOperator OpNode = null_frag> :
+ InstSE<(outs), (ins RC:$rt, MemBase:$base, imm_offset:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
+ [(OpNode RC:$rt, (addrDefault MemBase:$base, iPTR:$offset))],
+ FrmFI, opstr> {
let mayStore = 1;
}
@@ -1689,10 +1708,10 @@ class SYNC_FT<string opstr> :
[(MipsSync timmZExt5:$stype)], FrmOther, opstr>;
class SYNCI_FT<string opstr, DAGOperand MO> :
- InstSE<(outs), (ins MO:$addr), !strconcat(opstr, "\t$addr"), [],
+ InstSE<(outs), (ins MemBase:$base, MO:$offset),
+ !strconcat(opstr, "\t${offset}(${base})"), [],
FrmOther, opstr> {
let hasSideEffects = 1;
- let DecoderMethod = "DecodeSyncI";
}
let hasSideEffects = 1, isCTI = 1 in {
@@ -1773,12 +1792,13 @@ class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>:
}
class EffectiveAddress<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$rt), (ins mem_ea:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, addr:$addr)], FrmI,
+ InstSE<(outs RO:$rt), (ins MemBase:$base, simm16:$offset),
+ !strconcat(opstr, "\t$rt, $base, $offset"),
+ [(set RO:$rt, (addr MemBase:$base, simm16:$offset))], FrmI,
!strconcat(opstr, "_lea")> {
let isCodeGenOnly = 1;
let hasNoSchedulingInfo = 1;
- let DecoderMethod = "DecodeMem";
+ let FastISelShouldIgnore = 1;
}
// Count Leading Ones/Zeros in Word
@@ -1872,17 +1892,16 @@ class AtomicCmpSwapSubwordPostRA<RegisterClass RC> :
let Predicates = [NotR5900];
}
-class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> :
- InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
+class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = imm_offset> :
+ InstSE<(outs RO:$rt), (ins MemBase:$base, MO:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"),
[], FrmI, opstr> {
- let DecoderMethod = "DecodeMem";
let mayLoad = 1;
}
class SCBase<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$dst), (ins RO:$rt, mem:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], FrmI> {
- let DecoderMethod = "DecodeMem";
+ InstSE<(outs RO:$dst), (ins RO:$rt, MemBase:$base, imm_offset:$offset),
+ !strconcat(opstr, "\t$rt, ${offset}(${base})"), [], FrmI> {
let mayStore = 1;
let Constraints = "$rt = $dst";
}
@@ -2559,16 +2578,14 @@ let AdditionalPredicates = [NotInMicroMips] in {
def TLBWR : MMRel, TLB<"tlbwr">, COP0_TLB_FM<0x06>, ISA_MIPS1;
}
class CacheOp<string instr_asm, Operand MemOpnd> :
- InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint),
- !strconcat(instr_asm, "\t$hint, $addr"), [], FrmOther,
- instr_asm> {
- let DecoderMethod = "DecodeCacheOp";
-}
+ InstSE<(outs), (ins MemBase:$base, MemOpnd:$offset, uimm5:$hint),
+ !strconcat(instr_asm, "\t$hint, ${offset}(${base})"), [], FrmOther,
+ instr_asm>;
let AdditionalPredicates = [NotInMicroMips] in {
- def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>,
+ def CACHE : MMRel, CacheOp<"cache", mem_simmptr>, CACHEOP_FM<0b101111>,
INSN_MIPS3_32_NOT_32R6_64R6;
- def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>,
+ def PREF : MMRel, CacheOp<"pref", mem_simmptr>, CACHEOP_FM<0b110011>,
INSN_MIPS3_32_NOT_32R6_64R6;
}
// FIXME: We are missing the prefx instruction.
@@ -3129,37 +3146,46 @@ def : MipsInstAlias<"remu $rd, $imm", (URemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
simm32_relaxed:$imm), 0>,
ISA_MIPS1_NOT_32R6_64R6;
-def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
- "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
+def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
+ (ins MemBase:$base, imm_offset:$offset),
+ "ulh\t$rt, ${offset}(${base})">; //, ISA_MIPS1_NOT_32R6_64R6;
-def Ulhu : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
- "ulhu\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
+def Ulhu : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
+ (ins MemBase:$base, imm_offset:$offset),
+ "ulhu\t$rt, ${offset}(${base})">; //, ISA_MIPS1_NOT_32R6_64R6;
-def Ulw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
- "ulw\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
+def Ulw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
+ (ins MemBase:$base, imm_offset:$offset),
+ "ulw\t$rt, ${offset}(${base})">; //, ISA_MIPS1_NOT_32R6_64R6;
-def Ush : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
- "ush\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
+def Ush : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
+ (ins MemBase:$base, imm_offset:$offset),
+ "ush\t$rt, ${offset}(${base})">; //, ISA_MIPS1_NOT_32R6_64R6;
-def Usw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
- "usw\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
+def Usw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
+ (ins MemBase:$base, imm_offset:$offset),
+ "usw\t$rt, ${offset}(${base})">; //, ISA_MIPS1_NOT_32R6_64R6;
def LDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
- (ins mem_simm16:$addr), "ld $rt, $addr">,
- ISA_MIPS1_NOT_MIPS3;
+ (ins MemBase:$base, mem_simm16:$offset),
+ "ld $rt, ${offset}(${base})">,
+ ISA_MIPS1_NOT_MIPS3;
def SDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
- (ins mem_simm16:$addr), "sd $rt, $addr">,
- ISA_MIPS1_NOT_MIPS3;
+ (ins MemBase:$base, mem_simm16:$offset),
+ "sd $rt, ${offset}(${base})">,
+ ISA_MIPS1_NOT_MIPS3;
//===----------------------------------------------------------------------===//
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
// Load/store pattern templates.
class LoadRegImmPat<Instruction LoadInst, ValueType ValTy, PatFrag Node> :
- MipsPat<(ValTy (Node addrRegImm:$a)), (LoadInst addrRegImm:$a)>;
+ MipsPat<(ValTy (Node (addrRegImm MemBase:$a_base, iPTR:$a_offset))),
+ (LoadInst $a_base, $a_offset)>;
class StoreRegImmPat<Instruction StoreInst, ValueType ValTy> :
- MipsPat<(store ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>;
+ MipsPat<(store ValTy:$v, (addrRegImm MemBase:$a_base, iPTR:$a_offset)),
+ (StoreInst ValTy:$v, $a_base, $a_offset)>;
// Materialize constants.
multiclass MaterializeImms<ValueType VT, Register ZEROReg,
@@ -3289,12 +3315,16 @@ let AdditionalPredicates = [NotInMicroMips] in {
// extended loads
let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>, ISA_MIPS1;
- def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>, ISA_MIPS1;
- def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>, ISA_MIPS1;
+ def : MipsPat<(i32 (extloadi1 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LBu $src_base, $src_offset)>, ISA_MIPS1;
+ def : MipsPat<(i32 (extloadi8 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LBu $src_base, $src_offset)>, ISA_MIPS1;
+ def : MipsPat<(i32 (extloadi16 (addr MemBase:$src_base, iPTR:$src_offset))),
+ (LHu $src_base, $src_offset)>, ISA_MIPS1;
// peepholes
- def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>, ISA_MIPS1;
+ def : MipsPat<(store (i32 0), (addr MemBase:$dst_base, iPTR:$dst_offset)),
+ (SW ZERO, $dst_base, $dst_offset)>, ISA_MIPS1;
}
// brcond patterns
@@ -3403,17 +3433,23 @@ let AdditionalPredicates = [NotInMicroMips] in {
}
// Atomic load patterns.
- def : MipsPat<(atomic_load_asext_8 addr:$a), (LB addr:$a)>, ISA_MIPS1;
- def : MipsPat<(atomic_load_asext_16 addr:$a), (LH addr:$a)>, ISA_MIPS1;
- def : MipsPat<(atomic_load_nonext_32 addr:$a), (LW addr:$a)>, ISA_MIPS1;
+ def : MipsPat<(atomic_load_asext_8 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LB $a_base, $a_offset)>, ISA_MIPS1;
+ def : MipsPat<(atomic_load_asext_16 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LH $a_base, $a_offset)>, ISA_MIPS1;
+ def : MipsPat<(atomic_load_nonext_32 (addr MemBase:$a_base, iPTR:$a_offset)),
+ (LW $a_base, $a_offset)>, ISA_MIPS1;
// Atomic store patterns.
- def : MipsPat<(atomic_store_8 GPR32:$v, addr:$a), (SB GPR32:$v, addr:$a)>,
- ISA_MIPS1;
- def : MipsPat<(atomic_store_16 GPR32:$v, addr:$a), (SH GPR32:$v, addr:$a)>,
- ISA_MIPS1;
- def : MipsPat<(atomic_store_32 GPR32:$v, addr:$a), (SW GPR32:$v, addr:$a)>,
- ISA_MIPS1;
+ def : MipsPat<(atomic_store_8 GPR32:$v,
+ (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SB GPR32:$v, $a_base, $a_offset)>, ISA_MIPS1;
+ def : MipsPat<(atomic_store_16 GPR32:$v,
+ (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SH GPR32:$v, $a_base, $a_offset)>, ISA_MIPS1;
+ def : MipsPat<(atomic_store_32 GPR32:$v,
+ (addr MemBase:$a_base, iPTR:$a_offset)),
+ (SW GPR32:$v, $a_base, $a_offset)>, ISA_MIPS1;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Mips/MipsMSAInstrFormats.td b/llvm/lib/Target/Mips/MipsMSAInstrFormats.td
index c4ffb27f679c34..f66fb708bb09f7 100644
--- a/llvm/lib/Target/Mips/MipsMSAInstrFormats.td
+++ b/llvm/lib/Target/Mips/MipsMSAInstrFormats.td
@@ -384,11 +384,12 @@ class MSA_I10_FMT<bits<3> major, bits<2> df, bits<6> minor>: MSAInst {
}
class MSA_MI10_FMT<bits<2> df, bits<4> minor>: MSAInst {
- bits<21> addr;
+ bits<10> offset;
+ bits<5> base;
bits<5> wd;
- let Inst{25-16} = addr{9-0};
- let Inst{15-11} = addr{20-16};
+ let Inst{25-16} = offset;
+ let Inst{15-11} = base;
let Inst{10-6} = wd;
let Inst{5-2} = minor;
let Inst{1-0} = df;
diff --git a/llvm/lib/Target/Mips/MipsMSAInstrInfo.td b/llvm/lib/Target/Mips/MipsMSAInstrInfo.td
index 2512cc893c3207..9e72cb1bc9e32a 100644
--- a/llvm/lib/Target/Mips/MipsMSAInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsMSAInstrInfo.td
@@ -2185,10 +2185,10 @@ class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
ValueType TyNode, RegisterOperand ROWD,
Operand MemOpnd, ComplexPattern Addr = addrimm10> {
dag OutOperandList = (outs ROWD:$wd);
- dag InOperandList = (ins MemOpnd:$addr);
- string AsmString = !strconcat(instr_asm, "\t$wd, $addr");
- list<dag> Pattern = [(set ROWD:$wd, (TyNode (OpNode Addr:$addr)))];
- string DecoderMethod = "DecodeMSA128Mem";
+ dag InOperandList = (ins MemBase:$base, MemOpnd:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$wd, ${offset}(${base})");
+ list<dag> Pattern =
+ [(set ROWD:$wd, (TyNode (OpNode (Addr MemBase:$base, iPTR:$offset))))];
}
class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd, mem_simm10>;
@@ -2527,10 +2527,10 @@ class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
ValueType TyNode, RegisterOperand ROWD,
Operand MemOpnd, ComplexPattern Addr = addrimm10> {
dag OutOperandList = (outs);
- dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr);
- string AsmString = !strconcat(instr_asm, "\t$wd, $addr");
- list<dag> Pattern = [(OpNode (TyNode ROWD:$wd), Addr:$addr)];
- string DecoderMethod = "DecodeMSA128Mem";
+ dag InOperandList = (ins ROWD:$wd, MemBase:$base, MemOpnd:$offset);
+ string AsmString = !strconcat(instr_asm, "\t$wd, ${offset}(${base})");
+ list<dag> Pattern = [(OpNode (TyNode ROWD:$wd),
+ (Addr MemBase:$base, iPTR:$offset))];
}
class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd, mem_simm10>;
@@ -3443,16 +3443,25 @@ class MSAPat<dag pattern, dag result, list<Predicate> pred = [HasMSA]> :
def : MSAPat<(extractelt (v4i32 MSA128W:$ws), immZExt4:$idx),
(COPY_S_W MSA128W:$ws, immZExt4:$idx)>;
-def : MSAPat<(v8f16 (load addrimm10lsl1:$addr)), (LD_H addrimm10lsl1:$addr)>;
-def : MSAPat<(v4f32 (load addrimm10lsl2:$addr)), (LD_W addrimm10lsl2:$addr)>;
-def : MSAPat<(v2f64 (load addrimm10lsl3:$addr)), (LD_D addrimm10lsl3:$addr)>;
-
-def ST_FH : MSAPat<(store (v8f16 MSA128H:$ws), addrimm10lsl1:$addr),
- (ST_H MSA128H:$ws, addrimm10lsl1:$addr)>;
-def ST_FW : MSAPat<(store (v4f32 MSA128W:$ws), addrimm10lsl2:$addr),
- (ST_W MSA128W:$ws, addrimm10lsl2:$addr)>;
-def ST_FD : MSAPat<(store (v2f64 MSA128D:$ws), addrimm10lsl3:$addr),
- (ST_D MSA128D:$ws, addrimm10lsl3:$addr)>;
+def : MSAPat<(v8f16 (load (addrimm10lsl1 MemBase:$addr_base,
+ iPTR:$addr_offset))),
+ (LD_H $addr_base, $addr_offset)>;
+def : MSAPat<(v4f32 (load (addrimm10lsl2 MemBase:$addr_base,
+ iPTR:$addr_offset))),
+ (LD_W $addr_base, $addr_offset)>;
+def : MSAPat<(v2f64 (load (addrimm10lsl3 MemBase:$addr_base,
+ iPTR:$addr_offset))),
+ (LD_D $addr_base, $addr_offset)>;
+
+def ST_FH : MSAPat<(store (v8f16 MSA128H:$ws),
+ (addrimm10lsl1 MemBase:$addr_base, iPTR:$addr_offset)),
+ (ST_H MSA128H:$ws, $addr_base, $addr_offset)>;
+def ST_FW : MSAPat<(store (v4f32 MSA128W:$ws),
+ (addrimm10lsl2 MemBase:$addr_base, iPTR:$addr_offset)),
+ (ST_W MSA128W:$ws, $addr_base, $addr_offset)>;
+def ST_FD : MSAPat<(store (v2f64 MSA128D:$ws),
+ (addrimm10lsl3 MemBase:$addr_base, iPTR:$addr_offset)),
+ (ST_D MSA128D:$ws, $addr_base, $addr_offset)>;
class MSA_FABS_PSEUDO_DESC_BASE<RegisterOperand ROWD,
RegisterOperand ROWS = ROWD> :
diff --git a/llvm/test/MC/Disassembler/Mips/marked-up.txt b/llvm/test/MC/Disassembler/Mips/marked-up.txt
index ef805c0a1cde64..4e8e2244bd038f 100644
--- a/llvm/test/MC/Disassembler/Mips/marked-up.txt
+++ b/llvm/test/MC/Disassembler/Mips/marked-up.txt
@@ -6,5 +6,5 @@
0x21 0x2d 0x66 0xd2
# CHECK: xor <reg:$18>, <reg:$4>, <reg:$fp>
0x00 0x9e 0x90 0x26
-# CHECK: lwr <reg:$zero>, <mem:<imm:-19147>(<reg:$gp>)>
+# CHECK: lwr <reg:$zero>, <imm:-19147>(<reg:$gp>)
0x9b 0x80 0xb5 0x35
diff --git a/llvm/test/MC/Disassembler/Mips/micromips32r3/valid-el.txt b/llvm/test/MC/Disassembler/Mips/micromips32r3/valid-el.txt
index 8fd45d2fb9a8ab..f53775d4b93f1f 100644
--- a/llvm/test/MC/Disassembler/Mips/micromips32r3/valid-el.txt
+++ b/llvm/test/MC/Disassembler/Mips/micromips32r3/valid-el.txt
@@ -178,6 +178,7 @@
0x00 0x74 0x98 0x02 # CHECK: jals 1328
0xe6 0x03 0x3c 0x4f # CHECK: jalrs $ra, $6
0x44 0x20 0x08 0x50 # CHECK: lwm32 $16, $17, 8($4)
+0x84 0x22 0x0c 0x50 # CHECK: lwm32 $16, $17, $18, $19, $ra, 12($4)
0x3b 0x21 0x84 0x59 # CHECK: lwm32 $16, $17, $18, $19, $20, $21, $22, $23, $fp, -1660($27)
0x44 0x20 0x08 0xd0 # CHECK: swm32 $16, $17, 8($4)
0x04 0x22 0x08 0x90 # CHECK: swp $16, 8($4)
diff --git a/llvm/test/MC/Mips/cnmipsp/invalid.s b/llvm/test/MC/Mips/cnmipsp/invalid.s
index d6af1c1d4c5e4d..7c8848de7c5146 100644
--- a/llvm/test/MC/Mips/cnmipsp/invalid.s
+++ b/llvm/test/MC/Mips/cnmipsp/invalid.s
@@ -4,7 +4,7 @@
# RUN: FileCheck %s < %t1
saa $2 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-saa $2, $5, $6 # CHECK: :[[@LINE]]:12: error: unexpected token in argument list
+saa $2, $5, $6 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
saad $2 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-saad $2, $5, $6 # CHECK: :[[@LINE]]:12: error: unexpected token in argument list
+saad $2, $5, $6 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
diff --git a/llvm/test/MC/Mips/expr1.s b/llvm/test/MC/Mips/expr1.s
index f707091bed7bd1..5b90ae27250a6b 100644
--- a/llvm/test/MC/Mips/expr1.s
+++ b/llvm/test/MC/Mips/expr1.s
@@ -9,11 +9,11 @@
# 32R2-EL: lw $4, %lo(foo)($4) # encoding: [A,A,0x84,0x8c]
# 32R2-EL: # fixup A - offset: 0, value: %lo(foo), kind: fixup_Mips_LO16
# 32R2-EL: lw $4, 56($4) # encoding: [0x38,0x00,0x84,0x8c]
-# 32R2-EL: lui $1, %hi(foo+%lo(8)) # encoding: [A,A,0x01,0x3c]
-# 32R2-EL: # fixup A - offset: 0, value: %hi(foo+%lo(8)), kind: fixup_Mips_HI16
+# 32R2-EL: lui $1, %hi(%lo(8)+foo) # encoding: [A,A,0x01,0x3c]
+# 32R2-EL: # fixup A - offset: 0, value: %hi(%lo(8)+foo), kind: fixup_Mips_HI16
# 32R2-EL: addu $1, $1, $4 # encoding: [0x21,0x08,0x24,0x00]
-# 32R2-EL: lw $4, %lo(foo+%lo(8))($1) # encoding: [A,A,0x24,0x8c]
-# 32R2-EL: # fixup A - offset: 0, value: %lo(foo+%lo(8)), kind: fixup_Mips_LO16
+# 32R2-EL: lw $4, %lo(%lo(8)+foo)($1) # encoding: [A,A,0x24,0x8c]
+# 32R2-EL: # fixup A - offset: 0, value: %lo(%lo(8)+foo), kind: fixup_Mips_LO16
# 32R2-EL: lw $4, %lo(12+foo)($4) # encoding: [A,A,0x84,0x8c]
# 32R2-EL: # fixup A - offset: 0, value: %lo(12+foo), kind: fixup_Mips_LO16
# 32R2-EL: lw $4, 10($4) # encoding: [0x0a,0x00,0x84,0x8c]
@@ -27,11 +27,11 @@
# MM-32R2-EL: lw $4, %lo(foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
# MM-32R2-EL: # fixup A - offset: 0, value: %lo(foo), kind: fixup_MICROMIPS_LO16
# MM-32R2-EL: lw $4, 56($4) # encoding: [0x84,0xfc,0x38,0x00]
-# MM-32R2-EL: lui $1, %hi(foo+%lo(8)) # encoding: [0xa1'A',0x41'A',0x00,0x00]
-# MM-32R2-EL: # fixup A - offset: 0, value: %hi(foo+%lo(8)), kind: fixup_MICROMIPS_HI16
+# MM-32R2-EL: lui $1, %hi(%lo(8)+foo) # encoding: [0xa1'A',0x41'A',0x00,0x00]
+# MM-32R2-EL: # fixup A - offset: 0, value: %hi(%lo(8)+foo), kind: fixup_MICROMIPS_HI16
# MM-32R2-EL: addu $1, $1, $4 # encoding: [0x81,0x00,0x50,0x09]
-# MM-32R2-EL: lw $4, %lo(foo+%lo(8))($1) # encoding: [0x81'A',0xfc'A',0x00,0x00]
-# MM-32R2-EL: # fixup A - offset: 0, value: %lo(foo+%lo(8)), kind: fixup_MICROMIPS_LO16
+# MM-32R2-EL: lw $4, %lo(%lo(8)+foo)($1) # encoding: [0x81'A',0xfc'A',0x00,0x00]
+# MM-32R2-EL: # fixup A - offset: 0, value: %lo(%lo(8)+foo), kind: fixup_MICROMIPS_LO16
# MM-32R2-EL: lw $4, %lo(12+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
# MM-32R2-EL: # fixup A - offset: 0, value: %lo(12+foo), kind: fixup_MICROMIPS_LO16
# MM-32R2-EL: lw $4, 10($4) # encoding: [0x84,0xfc,0x0a,0x00]
diff --git a/llvm/test/MC/Mips/macro-dla-32bit.s b/llvm/test/MC/Mips/macro-dla-32bit.s
index 2fd6abfe42f4b5..95a880934514d5 100644
--- a/llvm/test/MC/Mips/macro-dla-32bit.s
+++ b/llvm/test/MC/Mips/macro-dla-32bit.s
@@ -1,3 +1,5 @@
+# RUN: llvm-mc %s -triple=mips64 -mcpu=mips64r2 -target-abi=n32 -show-encoding | \
+# RUN: FileCheck %s
# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | \
# RUN: FileCheck %s
# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r6 | \
@@ -225,4 +227,23 @@ dla $5, extern_sym-8($5)
# CHECK: # fixup A - offset: 0, value: %lo(extern_sym-8), kind: fixup_Mips_LO16
# CHECK: addu $5, $1, $5 # encoding: [0x00,0x25,0x28,0x21]
+# Absolute aliases, parenthesized expressions, and symbolic aliases.
+.set absolute, 24
+.set alias, symbol+16
+dla $2, absolute # CHECK: addiu $2, $zero, 24
+
+dla $2, absolute($4) # CHECK: addiu $2, $4, 24
+
+dla $2, (8+16)($4) # CHECK: addiu $2, $4, 24
+
+dla $2, ($4) # CHECK: addiu $2, $4, 0
+
+dla $2, (symbol+8)($4) # CHECK: lui $2, %hi(symbol+8)
+ # CHECK: addiu $2, $2, %lo(symbol+8)
+ # CHECK: addu $2, $2, $4
+
+dla $2, alias($4) # CHECK: lui $2, %hi(alias)
+ # CHECK: addiu $2, $2, %lo(alias)
+ # CHECK: addu $2, $2, $4
+
.option pic2
diff --git a/llvm/test/MC/Mips/macro-dla-bad.s b/llvm/test/MC/Mips/macro-dla-bad.s
index 7dc64555a88f09..bcd52b01d5c1df 100644
--- a/llvm/test/MC/Mips/macro-dla-bad.s
+++ b/llvm/test/MC/Mips/macro-dla-bad.s
@@ -1,3 +1,5 @@
+# RUN: not llvm-mc %s -triple=mips64 -mcpu=mips64r2 -target-abi=n32 2>&1 | \
+# RUN: FileCheck %s
# RUN: not llvm-mc %s -triple=mips64 -mcpu=mips3 -target-abi n64 2>&1 | \
# RUN: FileCheck %s
@@ -19,3 +21,6 @@
# CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
dla $25, symbol-0x8001($6)
# CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+
+ dla $2, 24($f4)
+ # CHECK: :[[@LINE-1]]:14: error: invalid operand for instruction
diff --git a/llvm/test/MC/Mips/macro-dla.s b/llvm/test/MC/Mips/macro-dla.s
index 321af00c8be312..61f45d1ef05e5b 100644
--- a/llvm/test/MC/Mips/macro-dla.s
+++ b/llvm/test/MC/Mips/macro-dla.s
@@ -751,5 +751,32 @@ dla $4, extern_sym+8($6) # CHECK: lui $4, %highest(extern_sym+8) # encodi
.set at
+# Absolute aliases, parenthesized expressions, and symbolic aliases.
+.set absolute, 24
+.set alias, symbol+16
+dla $2, absolute # CHECK: daddiu $2, $zero, 24
+
+dla $2, absolute($4) # CHECK: daddiu $2, $4, 24
+
+dla $2, (8+16)($4) # CHECK: daddiu $2, $4, 24
+
+dla $2, ($4) # CHECK: daddiu $2, $4, 0
+
+dla $2, (symbol+8)($4) # CHECK: lui $2, %highest(symbol+8)
+ # CHECK: lui $1, %hi(symbol+8)
+ # CHECK: daddiu $2, $2, %higher(symbol+8)
+ # CHECK: daddiu $1, $1, %lo(symbol+8)
+ # CHECK: dsll32 $2, $2, 0
+ # CHECK: daddu $2, $2, $1
+ # CHECK: daddu $2, $2, $4
+
+dla $2, alias($4) # CHECK: lui $2, %highest(alias)
+ # CHECK: lui $1, %hi(alias)
+ # CHECK: daddiu $2, $2, %higher(alias)
+ # CHECK: daddiu $1, $1, %lo(alias)
+ # CHECK: dsll32 $2, $2, 0
+ # CHECK: daddu $2, $2, $1
+ # CHECK: daddu $2, $2, $4
+
.option pic2
#dla $5, symbol
diff --git a/llvm/test/MC/Mips/macro-la-bad.s b/llvm/test/MC/Mips/macro-la-bad.s
index 7728785041ffc9..3bc06be58b3771 100644
--- a/llvm/test/MC/Mips/macro-la-bad.s
+++ b/llvm/test/MC/Mips/macro-la-bad.s
@@ -1,9 +1,9 @@
# RUN: not llvm-mc %s -triple=mips -mcpu=mips32r2 2>%t1
-# RUN: FileCheck %s < %t1 --check-prefix=O32
+# RUN: FileCheck %s < %t1 --check-prefixes=CHECK,O32
# RUN: not llvm-mc %s -triple=mips64 -mcpu=mips64 -target-abi n32 2>&1 | \
-# RUN: FileCheck %s --check-prefix=N32
-# RUN: llvm-mc %s -triple=mips64 -mcpu=mips64 -target-abi n64 2>&1 | \
-# RUN: FileCheck %s --check-prefix=N64
+# RUN: FileCheck %s --check-prefixes=CHECK,N32
+# RUN: not llvm-mc %s -triple=mips64 -mcpu=mips64 -target-abi n64 2>&1 | \
+# RUN: FileCheck %s --check-prefixes=CHECK,N64
.text
la $5, 0x100000000
@@ -19,3 +19,6 @@
la $5, symbol
# N32-NOT: :[[@LINE-1]]:3: warning: la used to load 64-bit address
# N64: :[[@LINE-2]]:3: warning: la used to load 64-bit address
+
+ la $2, symbol($f4)
+ # CHECK: :[[@LINE-1]]:17: error: invalid operand for instruction
diff --git a/llvm/test/MC/Mips/macro-la.s b/llvm/test/MC/Mips/macro-la.s
index c419d64b391852..fa20e8732aa43a 100644
--- a/llvm/test/MC/Mips/macro-la.s
+++ b/llvm/test/MC/Mips/macro-la.s
@@ -281,3 +281,22 @@ la $5, 1f # O32: lui $5, %hi($tmp0) # encoding: [0x3c,0x0
# N32: addiu $5, $5, %lo(.Ltmp0) # encoding: [0x24,0xa5,A,A]
# N32: # fixup A - offset: 0, value: %lo(.Ltmp0), kind: fixup_Mips_LO16
1:
+
+# Absolute aliases, parenthesized expressions, and symbolic aliases.
+.set absolute, 24
+.set alias, symbol+16
+la $2, absolute # CHECK: addiu $2, $zero, 24
+
+la $2, absolute($4) # CHECK: addiu $2, $4, 24
+
+la $2, (8+16)($4) # CHECK: addiu $2, $4, 24
+
+la $2, ($4) # CHECK: addiu $2, $4, 0
+
+la $2, (symbol+8)($4) # CHECK: lui $2, %hi(symbol+8)
+ # CHECK: addiu $2, $2, %lo(symbol+8)
+ # CHECK: addu $2, $2, $4
+
+la $2, alias($4) # CHECK: lui $2, %hi(alias)
+ # CHECK: addiu $2, $2, %lo(alias)
+ # CHECK: addu $2, $2, $4
diff --git a/llvm/test/MC/Mips/memory-offsets.s b/llvm/test/MC/Mips/memory-offsets.s
index 7f5a59152eee69..b4e58670229fe1 100644
--- a/llvm/test/MC/Mips/memory-offsets.s
+++ b/llvm/test/MC/Mips/memory-offsets.s
@@ -1,6 +1,6 @@
# RUN: llvm-mc -triple=mips -mcpu=mips32 -show-encoding %s | FileCheck %s
-# Check that parseMemOperand handles expressions such as <int>, (<int>),
+# Check that parseMemOffset handles expressions such as <int>, (<int>),
# <expr>, <expr> op <expr>, (<expr>) op (<expr>).
.global __start
@@ -25,9 +25,9 @@ __start:
lw $31, (8 * 4) % (8 * 31)($29) # CHECK: lw $ra, 32($sp) # encoding: [0x8f,0xbf,0x00,0x20]
lw $31, (8 * 4) % (8)($29) # CHECK: lw $ra, 0($sp) # encoding: [0x8f,0xbf,0x00,0x00]
lw $31, (8 * 4) + (8 * 31) ($29) # CHECK: lw $ra, 280($sp) # encoding: [0x8f,0xbf,0x01,0x18]
- lw $31, (8*4) + (8*31) + (8*32 + __start) ($29) # CHECK: lui $ra, %hi(248+((8*32)+__start)+32) # encoding: [0x3c,0x1f,A,A]
- # CHECK: # fixup A - offset: 0, value: %hi(248+((8*32)+__start)+32), kind: fixup_Mips_HI16
+ lw $31, (8*4) + (8*31) + (8*32 + __start) ($29) # CHECK: lui $ra, %hi(32+248+((8*32)+__start)) # encoding: [0x3c,0x1f,A,A]
+ # CHECK: # fixup A - offset: 0, value: %hi(32+248+((8*32)+__start)), kind: fixup_Mips_HI16
# CHECK: addu $ra, $ra, $sp # encoding: [0x03,0xfd,0xf8,0x21]
- # CHECK: lw $ra, %lo(248+((8*32)+__start)+32)($ra) # encoding: [0x8f,0xff,A,A]
- # CHECK: # fixup A - offset: 0, value: %lo(248+((8*32)+__start)+32), kind: fixup_Mips_LO16
+ # CHECK: lw $ra, %lo(32+248+((8*32)+__start))($ra) # encoding: [0x8f,0xff,A,A]
+ # CHECK: # fixup A - offset: 0, value: %lo(32+248+((8*32)+__start)), kind: fixup_Mips_LO16
.end __start
diff --git a/llvm/test/MC/Mips/micromips-16-bit-instructions.s b/llvm/test/MC/Mips/micromips-16-bit-instructions.s
index 53efb6c152c3fa..4f31314f5af386 100644
--- a/llvm/test/MC/Mips/micromips-16-bit-instructions.s
+++ b/llvm/test/MC/Mips/micromips-16-bit-instructions.s
@@ -1,3 +1,5 @@
+# RUN: llvm-mc %s -triple=mipsel -mattr=micromips -filetype=obj | \
+# RUN: llvm-objdump -d --no-print-imm-hex - | FileCheck %s --check-prefix=DIS
# RUN: llvm-mc %s -triple=mipsel -show-encoding -mattr=micromips | \
# RUN: FileCheck -check-prefix=CHECK-EL %s
# RUN: llvm-mc %s -triple=mips -show-encoding -mattr=micromips | \
@@ -127,7 +129,7 @@
sll16 $3, $16, 5
srl16 $4, $17, 6
lbu16 $3, 4($17)
- lbu16 $3, -1($16)
+ lbu16 $3, -1($16) # DIS: lbu16 $3, -1($16)
lhu16 $3, 4($16)
lw16 $4, 8($17)
sb16 $3, 4($16)
@@ -136,7 +138,7 @@
sw16 $0, 4($17)
lw $3, 32($gp)
lw $3, 32($sp)
- sw $4, 124($sp)
+ sw $4, 124($sp) # DIS: sw $4, 124($sp)
li16 $3, -1
li16 $3, 126
addiur1sp $7, 4
@@ -163,3 +165,17 @@
b16 132
break16 8
sdbbp16 14
+
+# Scaled memory offset boundaries.
+ lhu16 $3, 30($17) # CHECK-EL: lhu16 $3, 30($17) # encoding: [0x9f,0x29]
+ # CHECK-EB: lhu16 $3, 30($17) # encoding: [0x29,0x9f]
+ # DIS: lhu16 $3, 30($17)
+ lw16 $3, 60($16) # CHECK-EL: lw16 $3, 60($16) # encoding: [0x8f,0x69]
+ # CHECK-EB: lw16 $3, 60($16) # encoding: [0x69,0x8f]
+ # DIS: lw16 $3, 60($16)
+ lw $3, 124($sp) # CHECK-EL: lw $3, 124($sp) # encoding: [0x7f,0x48]
+ # CHECK-EB: lw $3, 124($sp) # encoding: [0x48,0x7f]
+ # DIS: lw $3, 124($sp)
+ lw $3, -256($gp) # CHECK-EL: lw $3, -256($gp) # encoding: [0xc0,0x65]
+ # CHECK-EB: lw $3, -256($gp) # encoding: [0x65,0xc0]
+ # DIS: lw $3, -256($gp)
diff --git a/llvm/test/MC/Mips/micromips-invalid.s b/llvm/test/MC/Mips/micromips-invalid.s
index d7fe09a22e2063..76dc4c8ed20655 100644
--- a/llvm/test/MC/Mips/micromips-invalid.s
+++ b/llvm/test/MC/Mips/micromips-invalid.s
@@ -89,3 +89,13 @@
jraddiusp 125 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected both 7-bit unsigned immediate and multiple of 4
jraddiusp 132 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected both 7-bit unsigned immediate and multiple of 4
lwu $32, 4096($32) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
+
+# Memory bases and offsets are checked independently.
+ lbu16 $3, 15($16) # CHECK: :[[@LINE]]:13: error: immediate operand value out of range
+ lhu16 $3, 1($16) # CHECK: :[[@LINE]]:13: error: immediate operand value out of range
+ lw16 $3, 64($16) # CHECK: :[[@LINE]]:12: error: immediate operand value out of range
+ lbu16 $3, symbol($16) # CHECK: :[[@LINE]]:13: error: expected immediate operand kind
+ lbu16 $3, 0($f2) # CHECK: :[[@LINE]]:15: error: invalid operand for instruction
+ lbu16 $3, 0($8) # CHECK: :[[@LINE]]:15: error: invalid operand for instruction
+ lwm16 $16-$17, $ra, 8($fp) # CHECK: :[[@LINE]]:25: error: invalid operand for instruction
+ lw $3, 0($f2) # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
diff --git a/llvm/test/MC/Mips/micromips32r6/invalid.s b/llvm/test/MC/Mips/micromips32r6/invalid.s
index d194d3bb92e741..14ad8e26e49fb6 100644
--- a/llvm/test/MC/Mips/micromips32r6/invalid.s
+++ b/llvm/test/MC/Mips/micromips32r6/invalid.s
@@ -93,7 +93,7 @@
lwm16 $16, $17, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
lwm16 $16-$20, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
lwm16 $16, $17, $ra, 8($fp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
- lwm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+ lwm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
sb16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
sb16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
sb16 $16, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
@@ -115,7 +115,7 @@
swm16 $16, $17, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
swm16 $16-$20, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
swm16 $16, $17, $ra, 8($fp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
- swm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+ swm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
mtc0 $4, $3, -1 # CHECK: :[[@LINE]]:17: error: expected 3-bit unsigned immediate
mtc0 $4, $3, 8 # CHECK: :[[@LINE]]:17: error: expected 3-bit unsigned immediate
mthc0 $4, $3, -1 # CHECK: :[[@LINE]]:17: error: expected 3-bit unsigned immediate
@@ -390,3 +390,13 @@
maddu $4, $5 # CHECK: :[[@LINE]]:3: error: instruction requires a CPU feature not currently enabled
msub $4, $5 # CHECK: :[[@LINE]]:3: error: instruction requires a CPU feature not currently enabled
msubu $4, $5 # CHECK: :[[@LINE]]:3: error: instruction requires a CPU feature not currently enabled
+
+# Memory bases and offsets are checked independently.
+ lbu16 $3, 15($16) # CHECK: :[[@LINE]]:13: error: immediate operand value out of range
+ lhu16 $3, 1($16) # CHECK: :[[@LINE]]:13: error: immediate operand value out of range
+ lw16 $3, 64($16) # CHECK: :[[@LINE]]:12: error: immediate operand value out of range
+ lbu16 $3, symbol($16) # CHECK: :[[@LINE]]:13: error: expected immediate operand kind
+ lbu16 $3, 0($f2) # CHECK: :[[@LINE]]:15: error: invalid operand for instruction
+ lbu16 $3, 0($8) # CHECK: :[[@LINE]]:15: error: invalid operand for instruction
+ lwm16 $16-$17, $ra, 8($fp) # CHECK: :[[@LINE]]:25: error: invalid operand for instruction
+ lw $3, 0($f2) # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
diff --git a/llvm/test/MC/Mips/micromips32r6/valid.s b/llvm/test/MC/Mips/micromips32r6/valid.s
index b6af2b951c77c7..ad375822d9c67e 100644
--- a/llvm/test/MC/Mips/micromips32r6/valid.s
+++ b/llvm/test/MC/Mips/micromips32r6/valid.s
@@ -1,3 +1,5 @@
+# RUN: llvm-mc %s -triple=mips -mcpu=mips32r6 -mattr=micromips -filetype=obj | \
+# RUN: llvm-objdump -d --no-print-imm-hex - | FileCheck %s --check-prefix=DIS
# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -show-inst -mcpu=mips32r6 -mattr=micromips | FileCheck %s
.set noat
@@ -145,6 +147,7 @@
sub $3, $4, $5 # CHECK: sub $3, $4, $5 # encoding: [0x00,0xa4,0x19,0x90]
subu $3, $4, $5 # CHECK: subu $3, $4, $5 # encoding: [0x00,0xa4,0x19,0xd0]
sw $4, 124($sp) # CHECK: sw $4, 124($sp) # encoding: [0xc8,0x9f]
+ # DIS: sw $4, 124($sp)
sw $4, 128($sp) # CHECK: sw $4, 128($sp) # encoding: [0xf8,0x9d,0x00,0x80]
# CHECK-NEXT: # <MCInst #{{[0-9]+}} SW_MMR6
sw16 $4, 4($17) # CHECK: sw16 $4, 4($17) # encoding: [0xea,0x11]
@@ -434,3 +437,6 @@
neg $4, $4 # CHECK: neg $4, $4 # encoding: [0x00,0x80,0x21,0x90]
negu $4, $5 # CHECK: negu $4, $5 # encoding: [0x00,0xa0,0x21,0xd0]
negu $4, $4 # CHECK: negu $4, $4 # encoding: [0x00,0x80,0x21,0xd0]
+
+ lwm16 $16, $17, $ra, 60($sp) # CHECK: lwm16 $16, $17, $ra, 60($sp) # encoding: [0x45,0xf2]
+ # DIS: lwm16 $16, $17, $ra, 60($sp)
diff --git a/llvm/test/MC/Mips/mips-memory-instructions.s b/llvm/test/MC/Mips/mips-memory-instructions.s
index c8b055906ebbf0..4b0b7eae302b86 100644
--- a/llvm/test/MC/Mips/mips-memory-instructions.s
+++ b/llvm/test/MC/Mips/mips-memory-instructions.s
@@ -1,3 +1,7 @@
+# RUN: llvm-mc %s -triple=mips64el -mcpu=mips64r2 -target-abi=n32 -show-encoding | \
+# RUN: FileCheck %s
+# RUN: llvm-mc %s -triple=mips64el -mcpu=mips64r2 -target-abi=n64 -show-encoding | \
+# RUN: FileCheck %s
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding -mcpu=mips32r2 | FileCheck %s
# Check that the assembler can handle the documented syntax
# for loads and stores.
@@ -42,3 +46,18 @@
lw $4, 4($5)
lw $7, ($7)
lw $2, 16($sp)
+
+# Omitted offsets, parenthesized expressions, and implicit zero bases.
+# CHECK: lw $2, 0($sp) # encoding: [0x00,0x00,0xa2,0x8f]
+# CHECK: lw $2, 12($3) # encoding: [0x0c,0x00,0x62,0x8c]
+# CHECK: lw $2, 12($zero) # encoding: [0x0c,0x00,0x02,0x8c]
+# CHECK: synci 0($3) # encoding: [0x00,0x00,0x7f,0x04]
+# CHECK: synci 12($3) # encoding: [0x0c,0x00,0x7f,0x04]
+# CHECK: synci 12($zero) # encoding: [0x0c,0x00,0x1f,0x04]
+
+ lw $2, ($sp)
+ lw $2, (4 + 8)($3)
+ lw $2, 12
+ synci ($3)
+ synci (4 + 8)($3)
+ synci 12
More information about the llvm-commits
mailing list