summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp1724
1 files changed, 949 insertions, 775 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index d4e061f00d3ac..b51d0200b0b1a 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -13,7 +13,6 @@
#include "MipsRegisterInfo.h"
#include "MipsTargetObjectFile.h"
#include "MipsTargetStreamer.h"
-#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCContext.h"
@@ -22,11 +21,13 @@
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ELF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
@@ -157,7 +158,6 @@ class MipsAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseImm(OperandVector &Operands);
OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
OperandMatchResultTy parseInvNum(OperandVector &Operands);
- OperandMatchResultTy parseLSAImm(OperandVector &Operands);
OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
OperandMatchResultTy parseRegisterList(OperandVector &Operands);
@@ -173,74 +173,77 @@ class MipsAsmParser : public MCTargetAsmParser {
};
// Expands assembly pseudo instructions.
- MacroExpanderResultTy
- tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MCStreamer &Out, const MCSubtargetInfo *STI);
bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MCStreamer &Out, const MCSubtargetInfo *STI);
bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MCStreamer &Out, const MCSubtargetInfo *STI);
bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
const MCOperand &Offset, bool Is32BitAddress,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
+ SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- void expandMemInst(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions, bool isLoad,
- bool isImmOpnd);
+ void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
- bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsImmOpnd);
- bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsImmOpnd);
- bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandDiv(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
- const bool Signed);
+ bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandUlw(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed);
- bool expandRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
- bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
- bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
- bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
+ MCStreamer &Out, const MCSubtargetInfo *STI);
- void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
- bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
+ bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandRotation(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out, const MCSubtargetInfo *STI);
+ bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+ bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+ bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+
+ bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
bool reportParseError(Twine ErrorMsg);
bool reportParseError(SMLoc Loc, Twine ErrorMsg);
@@ -263,6 +266,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseDirectiveSet();
bool parseDirectiveOption();
bool parseInsnDirective();
+ bool parseSSectionDirective(StringRef Section, unsigned Type);
bool parseSetAtDirective();
bool parseSetNoAtDirective();
@@ -295,16 +299,12 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseInternalDirectiveReallowModule();
- MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
-
bool eatComma(StringRef ErrorStr);
int matchCPURegisterName(StringRef Symbol);
int matchHWRegsRegisterName(StringRef Symbol);
- int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
-
int matchFPURegisterName(StringRef Name);
int matchFCCRegisterName(StringRef Name);
@@ -317,15 +317,13 @@ class MipsAsmParser : public MCTargetAsmParser {
unsigned getReg(int RC, int RegNo);
- unsigned getGPR(int RegNo);
-
/// Returns the internal register number for the current AT. Also checks if
/// the current AT is unavailable (set to $0) and gives an error if it is.
/// This should be used in pseudo-instruction expansions which need AT.
unsigned getATReg(SMLoc Loc);
- bool processInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
// Helper function that checks if the value of a vector index is within the
// boundaries of accepted values for each RegisterKind
@@ -395,6 +393,8 @@ class MipsAsmParser : public MCTargetAsmParser {
public:
enum MipsMatchResultTy {
Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
+ Match_RequiresDifferentOperands,
+ Match_RequiresNoZeroRegister,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -427,13 +427,12 @@ public:
CurrentFn = nullptr;
- IsPicEnabled =
- (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
+ IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
IsCpRestoreSet = false;
CpRestoreOffset = -1;
- Triple TheTriple(sti.getTargetTriple());
+ const Triple &TheTriple = sti.getTargetTriple();
if ((TheTriple.getArch() == Triple::mips) ||
(TheTriple.getArch() == Triple::mips64))
IsLittleEndian = false;
@@ -584,7 +583,6 @@ private:
enum KindTy {
k_Immediate, /// An immediate (possibly involving symbol references)
k_Memory, /// Base + Offset Memory Address
- k_PhysRegister, /// A physical register from the Mips namespace
k_RegisterIndex, /// A register index in one or more RegKind.
k_Token, /// A simple token
k_RegList, /// A physical register list
@@ -604,10 +602,6 @@ private:
unsigned Length;
};
- struct PhysRegOp {
- unsigned Num; /// Register Number
- };
-
struct RegIdxOp {
unsigned Index; /// Index into the register class
RegKind Kind; /// Bitfield of the kinds it could possibly be
@@ -629,7 +623,6 @@ private:
union {
struct Token Tok;
- struct PhysRegOp PhysReg;
struct RegIdxOp RegIdx;
struct ImmOp Imm;
struct MemOp Mem;
@@ -938,6 +931,34 @@ public:
Inst.addOperand(MCOperand::createImm(Imm));
}
+ template <unsigned Bits>
+ void addSImmOperands(MCInst &Inst, unsigned N) const {
+ if (isImm() && !isConstantImm()) {
+ addExpr(Inst, getImm());
+ return;
+ }
+ addConstantSImmOperands<Bits, 0, 0>(Inst, N);
+ }
+
+ template <unsigned Bits>
+ void addUImmOperands(MCInst &Inst, unsigned N) const {
+ if (isImm() && !isConstantImm()) {
+ addExpr(Inst, getImm());
+ return;
+ }
+ addConstantUImmOperands<Bits, 0, 0>(Inst, N);
+ }
+
+ template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
+ void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ int64_t Imm = getConstantImm() - Offset;
+ Imm = SignExtend64<Bits>(Imm);
+ Imm += Offset;
+ Imm += AdjustOffset;
+ Inst.addOperand(MCOperand::createImm(Imm));
+ }
+
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCExpr *Expr = getImm();
@@ -973,9 +994,19 @@ public:
void addRegPairOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
+ assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
unsigned RegNo = getRegPair();
- Inst.addOperand(MCOperand::createReg(RegNo++));
- Inst.addOperand(MCOperand::createReg(RegNo));
+ AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
+ Inst.addOperand(MCOperand::createReg(
+ RegIdx.RegInfo->getRegClass(
+ AsmParser.getABI().AreGprs64bit()
+ ? Mips::GPR64RegClassID
+ : Mips::GPR32RegClassID).getRegister(RegNo++)));
+ Inst.addOperand(MCOperand::createReg(
+ RegIdx.RegInfo->getRegClass(
+ AsmParser.getABI().AreGprs64bit()
+ ? Mips::GPR64RegClassID
+ : Mips::GPR32RegClassID).getRegister(RegNo)));
}
void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
@@ -985,12 +1016,9 @@ public:
}
bool isReg() const override {
- // As a special case until we sort out the definition of div/divu, pretend
- // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
- if (isGPRAsmReg() && RegIdx.Index == 0)
- return true;
-
- return Kind == k_PhysRegister;
+ // As a special case until we sort out the definition of div/divu, accept
+ // $0/$zero here so that MCK_ZERO works correctly.
+ return isGPRAsmReg() && RegIdx.Index == 0;
}
bool isRegIdx() const { return Kind == k_RegisterIndex; }
bool isImm() const override { return Kind == k_Immediate; }
@@ -1003,8 +1031,23 @@ public:
template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
}
- template <unsigned Bits> bool isConstantSImm() const {
- return isConstantImm() && isInt<Bits>(getConstantImm());
+ template <unsigned Bits> bool isSImm() const {
+ return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
+ }
+ template <unsigned Bits> bool isUImm() const {
+ return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
+ }
+ template <unsigned Bits> bool isAnyImm() const {
+ return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
+ isUInt<Bits>(getConstantImm()))
+ : isImm();
+ }
+ template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
+ return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
+ }
+ template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
+ return isConstantImm() && getConstantImm() >= Bottom &&
+ getConstantImm() <= Top;
}
bool isToken() const override {
// Note: It's not possible to pretend that other operand kinds are tokens.
@@ -1015,13 +1058,22 @@ public:
bool isConstantMemOff() const {
return isMem() && isa<MCConstantExpr>(getMemOff());
}
- template <unsigned Bits> bool isMemWithSimmOffset() const {
- return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
- && getMemBase()->isGPRAsmReg();
- }
- template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
- return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
- getMemBase()->isGPRAsmReg();
+ // Allow relocation operators.
+ // FIXME: This predicate and others need to look through binary expressions
+ // and determine whether a Value is a constant or not.
+ template <unsigned Bits, unsigned ShiftAmount = 0>
+ bool isMemWithSimmOffset() const {
+ if (!isMem())
+ return false;
+ if (!getMemBase()->isGPRAsmReg())
+ return false;
+ if (isa<MCTargetExpr>(getMemOff()) ||
+ (isConstantMemOff() &&
+ isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
+ return true;
+ MCValue Res;
+ bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
+ return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
}
bool isMemWithGRPMM16Base() const {
return isMem() && getMemBase()->isMM16AsmReg();
@@ -1035,11 +1087,21 @@ public:
&& (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>
bool isScaledUImm() const {
return isConstantImm() &&
isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
}
+ template <unsigned Bits, unsigned ShiftLeftAmount>
+ bool isScaledSImm() const {
+ return isConstantImm() &&
+ isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
+ }
bool isRegList16() const {
if (!isRegList())
return false;
@@ -1086,7 +1148,15 @@ public:
(R0 == Mips::A0 && R1 == Mips::S6) ||
(R0 == Mips::A0 && R1 == Mips::A1) ||
(R0 == Mips::A0 && R1 == Mips::A2) ||
- (R0 == Mips::A0 && R1 == Mips::A3))
+ (R0 == Mips::A0 && R1 == Mips::A3) ||
+ (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
+ (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
+ (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::A3_64))
return true;
return false;
@@ -1096,17 +1166,19 @@ public:
assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
- bool isRegPair() const { return Kind == k_RegPair; }
+ bool isRegPair() const {
+ return Kind == k_RegPair && RegIdx.Index <= 30;
+ }
unsigned getReg() const override {
- // As a special case until we sort out the definition of div/divu, pretend
- // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
+ // As a special case until we sort out the definition of div/divu, accept
+ // $0/$zero here so that MCK_ZERO works correctly.
if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
RegIdx.Kind & RegKind_GPR)
return getGPR32Reg(); // FIXME: GPR64 too
- assert(Kind == k_PhysRegister && "Invalid access!");
- return PhysReg.Num;
+ llvm_unreachable("Invalid access!");
+ return 0;
}
const MCExpr *getImm() const {
@@ -1250,10 +1322,13 @@ public:
return Op;
}
- static std::unique_ptr<MipsOperand>
- CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
+ static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
+ SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
- Op->RegIdx.Index = RegNo;
+ Op->RegIdx.Index = MOP.RegIdx.Index;
+ Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
+ Op->RegIdx.Kind = MOP.RegIdx.Kind;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
@@ -1331,7 +1406,6 @@ public:
break;
case k_RegList:
delete RegList.List;
- case k_PhysRegister:
case k_RegisterIndex:
case k_Token:
case k_RegPair:
@@ -1353,9 +1427,6 @@ public:
OS << *Mem.Off;
OS << ">";
break;
- case k_PhysRegister:
- OS << "PhysReg<" << PhysReg.Num << ">";
- break;
case k_RegisterIndex:
OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
break;
@@ -1434,83 +1505,10 @@ static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
return 0;
}
-namespace {
-void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createReg(Reg0));
- tmpInst.addOperand(Op1);
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
-}
-
-void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
-}
-
-void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createImm(Imm1));
- tmpInst.addOperand(MCOperand::createImm(Imm2));
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createReg(Reg0));
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createReg(Reg0));
- tmpInst.addOperand(MCOperand::createReg(Reg1));
- tmpInst.addOperand(Op2);
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
- Instructions);
-}
-
-void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
- Instructions);
-}
-
-void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- if (ShiftAmount >= 32) {
- emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
- Instructions);
- return;
- }
-
- emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
-}
-} // end anonymous namespace.
-
bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
bool ExpandedJalSym = false;
@@ -1560,6 +1558,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case Mips::BLTZAL_MM:
case Mips::BC1F_MM:
case Mips::BC1T_MM:
+ case Mips::BC1EQZC_MMR6:
+ case Mips::BC1NEZC_MMR6:
+ case Mips::BC2EQZC_MMR6:
+ case Mips::BC2NEZC_MMR6:
assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Offset = Inst.getOperand(1);
if (!Offset.isImm())
@@ -1650,9 +1652,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
// FIXME: This is checking the expression can be handled by the later stages
- // of the assembler. We ought to leave it to those later stages but
- // we can't do that until we stop evaluateRelocExpr() rewriting the
- // expressions into non-equivalent forms.
+ // of the assembler. We ought to leave it to those later stages.
const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
// FIXME: Add support for label+offset operands (currently causes an error).
@@ -1666,33 +1666,38 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// addiu $25, $25, 0
// R_(MICRO)MIPS_LO16 label
// jalr $25
- const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
- const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
-
- emitRRX(Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
- emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
- MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
+ const MCExpr *Got16RelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
+ const MCExpr *Lo16RelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
+
+ TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
+ MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
+ MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
} else if (isABI_N32() || isABI_N64()) {
// If it's a local symbol and the N32/N64 ABIs are being used,
// we expand to:
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_GOT_DISP label
// jalr $25
- const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
+ const MCExpr *GotDispRelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
- emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
+ TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
+ Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
+ STI);
}
} else {
// If it's an external/weak symbol, we expand to:
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_CALL16 label
// jalr $25
- const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
+ const MCExpr *Call16RelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
- emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
+ TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
+ MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
}
MCInst JalrInst;
@@ -1723,7 +1728,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
int MemOffset = Op.getImm();
if (MemOffset < -32768 || MemOffset > 32767) {
// Offset can't exceed 16bit value.
- expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
return false;
}
} else if (Op.isExpr()) {
@@ -1733,11 +1738,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
static_cast<const MCSymbolRefExpr *>(Expr);
if (SR->getKind() == MCSymbolRefExpr::VK_None) {
// Expand symbol.
- expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
return false;
}
} else if (!isEvaluated(Expr)) {
- expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
return false;
}
}
@@ -1763,8 +1768,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
(BaseReg.getReg() == Mips::GP ||
BaseReg.getReg() == Mips::GP_64)) {
- emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
- IDLoc, Instructions);
+ TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
+ IDLoc, STI);
return false;
}
}
@@ -1780,14 +1785,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
switch (Inst.getOpcode()) {
default:
break;
- case Mips::ADDIUS5_MM:
- Opnd = Inst.getOperand(2);
- if (!Opnd.isImm())
- return Error(IDLoc, "expected immediate operand kind");
- Imm = Opnd.getImm();
- if (Imm < -8 || Imm > 7)
- return Error(IDLoc, "immediate operand value out of range");
- break;
case Mips::ADDIUSP_MM:
Opnd = Inst.getOperand(0);
if (!Opnd.isImm())
@@ -1823,16 +1820,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
return Error(IDLoc, "immediate operand value out of range");
break;
- case Mips::ADDIUR1SP_MM:
- Opnd = Inst.getOperand(1);
- if (!Opnd.isImm())
- return Error(IDLoc, "expected immediate operand kind");
- Imm = Opnd.getImm();
- if (OffsetToAlignment(Imm, 4LL))
- return Error(IDLoc, "misaligned immediate operand value");
- if (Imm < 0 || Imm > 255)
- return Error(IDLoc, "immediate operand value out of range");
- break;
case Mips::ANDI16_MM:
Opnd = Inst.getOperand(2);
if (!Opnd.isImm())
@@ -1851,12 +1838,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
if (Imm < -1 || Imm > 14)
return Error(IDLoc, "immediate operand value out of range");
break;
- case Mips::TEQ_MM:
- case Mips::TGE_MM:
- case Mips::TGEU_MM:
- case Mips::TLT_MM:
- case Mips::TLTU_MM:
- case Mips::TNE_MM:
case Mips::SB16_MM:
case Mips::SB16_MMR6:
Opnd = Inst.getOperand(2);
@@ -1897,11 +1878,16 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
}
}
+ bool FillDelaySlot =
+ MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
+ if (FillDelaySlot)
+ TOut.emitDirectiveSetNoReorder();
+
MacroExpanderResultTy ExpandResult =
- tryExpandInstruction(Inst, IDLoc, Instructions);
+ tryExpandInstruction(Inst, IDLoc, Out, STI);
switch (ExpandResult) {
case MER_NotAMacro:
- Instructions.push_back(Inst);
+ Out.EmitInstruction(Inst, *STI);
break;
case MER_Success:
break;
@@ -1909,10 +1895,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return true;
}
+ // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
+ // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
+ if (inMicroMipsMode())
+ TOut.setUsesMicroMips();
+
// If this instruction has a delay slot and .set reorder is active,
// emit a NOP after it.
- if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
- createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
+ if (FillDelaySlot) {
+ TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
+ TOut.emitDirectiveSetReorder();
+ }
if ((Inst.getOpcode() == Mips::JalOneReg ||
Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
@@ -1922,16 +1915,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// If .set reorder has been used, we've already emitted a NOP.
// If .set noreorder has been used, we need to emit a NOP at this point.
if (!AssemblerOptions.back()->isReorder())
- createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
+ TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
+ STI);
// Load the $gp from the stack.
- SmallVector<MCInst, 3> LoadInsts;
- createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
- IDLoc, LoadInsts);
-
- for (const MCInst &Inst : LoadInsts)
- Instructions.push_back(Inst);
-
+ TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
} else
Warning(IDLoc, "no .cprestore used in PIC mode");
}
@@ -1940,17 +1928,15 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
}
MipsAsmParser::MacroExpanderResultTy
-MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
switch (Inst.getOpcode()) {
default:
return MER_NotAMacro;
case Mips::LoadImm32:
- return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::LoadImm64:
- return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::LoadAddrImm32:
case Mips::LoadAddrImm64:
assert(Inst.getOperand(0).isReg() && "expected register operand kind");
@@ -1960,7 +1946,7 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
Inst.getOperand(1),
Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
- Instructions)
+ Out, STI)
? MER_Fail
: MER_Success;
case Mips::LoadAddrReg32:
@@ -1973,24 +1959,23 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
return expandLoadAddress(Inst.getOperand(0).getReg(),
Inst.getOperand(1).getReg(), Inst.getOperand(2),
Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
- Instructions)
+ Out, STI)
? MER_Fail
: MER_Success;
case Mips::B_MM_Pseudo:
case Mips::B_MMR6_Pseudo:
- return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
case Mips::SWM_MM:
case Mips::LWM_MM:
- return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
case Mips::JalOneReg:
case Mips::JalTwoReg:
- return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::BneImm:
case Mips::BeqImm:
- return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::BLT:
case Mips::BLE:
case Mips::BGE:
@@ -2023,29 +2008,36 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
case Mips::BLEULImmMacro:
case Mips::BGEULImmMacro:
case Mips::BGTULImmMacro:
- return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::SDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
+ : MER_Success;
case Mips::DSDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
+ : MER_Success;
case Mips::UDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
+ : MER_Success;
case Mips::DUDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
+ : MER_Success;
+ case Mips::PseudoTRUNC_W_S:
+ return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
+ case Mips::PseudoTRUNC_W_D32:
+ return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
+ case Mips::PseudoTRUNC_W_D:
+ return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
case Mips::Ulh:
- return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::Ulhu:
- return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::Ulw:
- return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::NORImm:
- return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::ADDi:
case Mips::ADDiu:
case Mips::SLTi:
@@ -2055,8 +2047,8 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
int64_t ImmValue = Inst.getOperand(2).getImm();
if (isInt<16>(ImmValue))
return MER_NotAMacro;
- return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
}
return MER_NotAMacro;
case Mips::ANDi:
@@ -2067,31 +2059,32 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
int64_t ImmValue = Inst.getOperand(2).getImm();
if (isUInt<16>(ImmValue))
return MER_NotAMacro;
- return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
}
return MER_NotAMacro;
case Mips::ROL:
case Mips::ROR:
- return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::ROLImm:
case Mips::RORImm:
- return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::DROL:
case Mips::DROR:
- return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::DROLImm:
case Mips::DRORImm:
- return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::ABSMacro:
+ return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
}
}
bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
// Create a JALR instruction which is going to replace the pseudo-JAL.
MCInst JalrInst;
JalrInst.setLoc(IDLoc);
@@ -2121,14 +2114,14 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
const MCOperand SecondRegOp = Inst.getOperand(1);
JalrInst.addOperand(SecondRegOp);
}
- Instructions.push_back(JalrInst);
+ Out.EmitInstruction(JalrInst, *STI);
// If .set reorder is active and branch instruction has a delay slot,
// emit a NOP after it.
const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
- if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
- createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
- }
+ if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
+ TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
+ STI);
return false;
}
@@ -2150,11 +2143,12 @@ template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
/// @param IsAddress True if the immediate represents an address. False if it
/// is an integer.
/// @param IDLoc Location of the immediate in the source file.
-/// @param Instructions The instructions emitted by this expansion.
bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
unsigned SrcReg, bool Is32BitImm,
- bool IsAddress, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
if (!Is32BitImm && !isGP64bit()) {
Error(IDLoc, "instruction requires a 64-bit architecture");
return true;
@@ -2180,7 +2174,8 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
UseSrcReg = true;
unsigned TmpReg = DstReg;
- if (UseSrcReg && (DstReg == SrcReg)) {
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
// At this point we need AT to perform the expansions and we exit if it is
// not available.
unsigned ATReg = getATReg(IDLoc);
@@ -2197,11 +2192,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// traditional assembler behaviour. N32 would normally use addiu for both
// integers and addresses.
if (IsAddress && !Is32BitImm) {
- emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
+ TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
return false;
}
- emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
return false;
}
@@ -2213,9 +2208,9 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
return true;
}
- emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
if (UseSrcReg)
- emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2229,29 +2224,29 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Traditional behaviour seems to special case this particular value. It's
// not clear why other masks are handled differently.
if (ImmValue == 0xffffffff) {
- emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
- emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
+ TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
+ TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
// Expand to an ORi instead of a LUi to avoid sign-extending into the
// upper 32 bits.
- emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
- emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
if (Bits15To0)
- emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
- emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
+ TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
if (Bits15To0)
- emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2267,11 +2262,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
unsigned LastSet = findLastSet((uint64_t)ImmValue);
unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
- emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
- emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2284,7 +2279,7 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
- IDLoc, Instructions))
+ IDLoc, Out, STI))
return false;
// Shift and accumulate into the register. If a 16-bit chunk is zero, then
@@ -2294,9 +2289,8 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
if (ImmChunk != 0) {
- emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
- Instructions);
- emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
+ TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
+ TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
ShiftCarriedForwards = 0;
}
@@ -2306,24 +2300,23 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Finish any remaining shifts left by trailing zeros.
if (ShiftCarriedForwards)
- emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
- Instructions);
+ TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out, const MCSubtargetInfo *STI) {
const MCOperand &ImmOp = Inst.getOperand(1);
assert(ImmOp.isImm() && "expected immediate operand kind");
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
- Is32BitImm, false, IDLoc, Instructions))
+ Is32BitImm, false, IDLoc, Out, STI))
return true;
return false;
@@ -2332,7 +2325,8 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
const MCOperand &Offset,
bool Is32BitAddress, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
// la can't produce a usable address when addresses are 64-bit.
if (Is32BitAddress && ABI.ArePtrs64bit()) {
// FIXME: Demote this to a warning and continue as if we had 'dla' instead.
@@ -2344,31 +2338,109 @@ bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
}
// dla requires 64-bit addresses.
- if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
+ if (!Is32BitAddress && !hasMips3()) {
Error(IDLoc, "instruction requires a 64-bit architecture");
return true;
}
if (!Offset.isImm())
return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
- Is32BitAddress, IDLoc, Instructions);
+ Is32BitAddress, IDLoc, Out, STI);
+
+ if (!ABI.ArePtrs64bit()) {
+ // Continue as if we had 'la' whether we had 'la' or 'dla'.
+ Is32BitAddress = true;
+ }
return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
- IDLoc, Instructions);
+ IDLoc, Out, STI);
}
-bool MipsAsmParser::loadAndAddSymbolAddress(
- const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
+ unsigned DstReg, unsigned SrcReg,
+ bool Is32BitSym, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ bool UseSrcReg = SrcReg != Mips::NoRegister;
warnIfNoMacro(IDLoc);
- const MCExpr *Symbol = cast<MCExpr>(SymExpr);
- const MipsMCExpr *HiExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
- const MipsMCExpr *LoExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
+ if (inPicMode() && ABI.IsO32()) {
+ MCValue Res;
+ if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
+ Error(IDLoc, "expected relocatable expression");
+ return true;
+ }
+ if (Res.getSymB() != nullptr) {
+ Error(IDLoc, "expected relocatable expression with only one symbol");
+ return true;
+ }
+
+ // The case where the result register is $25 is somewhat special. If the
+ // symbol in the final relocation is external and not modified with a
+ // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
+ if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
+ Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
+ !Res.getSymA()->getSymbol().isTemporary()) {
+ const MCExpr *CallExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
+ TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
+ MCOperand::createExpr(CallExpr), IDLoc, STI);
+ return false;
+ }
- bool UseSrcReg = SrcReg != Mips::NoRegister;
+ // The remaining cases are:
+ // External GOT: lw $tmp, %got(symbol+offset)($gp)
+ // >addiu $tmp, $tmp, %lo(offset)
+ // >addiu $rd, $tmp, $rs
+ // Local GOT: lw $tmp, %got(symbol+offset)($gp)
+ // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
+ // >addiu $rd, $tmp, $rs
+ // The addiu's marked with a '>' may be omitted if they are redundant. If
+ // this happens then the last instruction must use $rd as the result
+ // register.
+ const MipsMCExpr *GotExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
+ const MCExpr *LoExpr = nullptr;
+ if (Res.getSymA()->getSymbol().isInSection() ||
+ Res.getSymA()->getSymbol().isTemporary())
+ LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
+ else if (Res.getConstant() != 0) {
+ // External symbols fully resolve the symbol with just the %got(symbol)
+ // but we must still account for any offset to the symbol for expressions
+ // like symbol+8.
+ LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
+ }
+
+ unsigned TmpReg = DstReg;
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
+ SrcReg)) {
+ // If $rs is the same as $rd, we need to use AT.
+ // If it is not available we exit.
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ TmpReg = ATReg;
+ }
+
+ TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
+ MCOperand::createExpr(GotExpr), IDLoc, STI);
+
+ if (LoExpr)
+ TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+
+ if (UseSrcReg)
+ TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
+
+ return false;
+ }
+
+ const MipsMCExpr *HiExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
+ const MipsMCExpr *LoExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
// This is the 64-bit symbol address expansion.
if (ABI.ArePtrs64bit() && isGP64bit()) {
@@ -2378,12 +2450,14 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
if (!ATReg)
return true;
- const MipsMCExpr *HighestExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
- const MipsMCExpr *HigherExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
+ const MipsMCExpr *HighestExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
+ const MipsMCExpr *HigherExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
- if (UseSrcReg && (DstReg == SrcReg)) {
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
+ SrcReg)) {
// If $rs is the same as $rd:
// (d)la $rd, sym($rd) => lui $at, %highest(sym)
// daddiu $at, $at, %higher(sym)
@@ -2392,17 +2466,17 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
// dsll $at, $at, 16
// daddiu $at, $at, %lo(sym)
// daddu $rd, $at, $rd
- emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
- Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
- IDLoc, Instructions);
- emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
- Instructions);
- emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
- Instructions);
- emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
+ MCOperand::createExpr(HigherExpr), IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
+ IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+ TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2415,18 +2489,17 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
// dsll32 $rd, $rd, 0
// daddu $rd, $rd, $at
// (daddu $rd, $rd, $rs)
- emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
- Instructions);
- emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
- Instructions);
- emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
- IDLoc, Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
- Instructions);
- emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
- emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
+ TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ STI);
+ TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+ MCOperand::createExpr(HigherExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
+ TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
if (UseSrcReg)
- emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2441,7 +2514,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
// ori $rd, $rd, %lo(sym)
// (addu $rd, $rd, $rs)
unsigned TmpReg = DstReg;
- if (UseSrcReg && (DstReg == SrcReg)) {
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
// If $rs is the same as $rd, we need to use AT.
// If it is not available we exit.
unsigned ATReg = getATReg(IDLoc);
@@ -2450,20 +2524,24 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
TmpReg = ATReg;
}
- emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
- emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
if (UseSrcReg)
- emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
else
- assert(DstReg == TmpReg);
+ assert(
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
return false;
}
-bool MipsAsmParser::expandUncondBranchMMPseudo(
- MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
"unexpected number of operands");
@@ -2493,19 +2571,20 @@ bool MipsAsmParser::expandUncondBranchMMPseudo(
Inst.addOperand(MCOperand::createImm(Offset.getImm()));
}
}
- Instructions.push_back(Inst);
+ Out.EmitInstruction(Inst, *STI);
// If .set reorder is active and branch instruction has a delay slot,
// emit a NOP after it.
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
- createNop(true, IDLoc, Instructions);
+ TOut.emitEmptyDelaySlot(true, IDLoc, STI);
return false;
}
-bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
@@ -2513,7 +2592,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
assert(ImmOp.isImm() && "expected immediate operand kind");
const MCOperand &MemOffsetOp = Inst.getOperand(2);
- assert(MemOffsetOp.isImm() && "expected immediate operand kind");
+ assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
+ "expected immediate or expression operand");
unsigned OpCode = 0;
switch(Inst.getOpcode()) {
@@ -2530,8 +2610,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
int64_t ImmValue = ImmOp.getImm();
if (ImmValue == 0)
- emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
- Instructions);
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
+ STI);
else {
warnIfNoMacro(IDLoc);
@@ -2540,94 +2620,112 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
return true;
if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
- IDLoc, Instructions))
+ IDLoc, Out, STI))
return true;
- emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
}
return false;
}
-void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions,
- bool isLoad, bool isImmOpnd) {
- unsigned ImmOffset, HiOffset, LoOffset;
- const MCExpr *ExprOffset;
- unsigned TmpRegNum;
- // 1st operand is either the source or destination register.
- assert(Inst.getOperand(0).isReg() && "expected register operand kind");
- unsigned RegOpNum = Inst.getOperand(0).getReg();
- // 2nd operand is the base register.
- assert(Inst.getOperand(1).isReg() && "expected register operand kind");
- unsigned BaseRegNum = Inst.getOperand(1).getReg();
- // 3rd operand is either an immediate or expression.
- if (isImmOpnd) {
- assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
- ImmOffset = Inst.getOperand(2).getImm();
- LoOffset = ImmOffset & 0x0000ffff;
- HiOffset = (ImmOffset & 0xffff0000) >> 16;
- // If msb of LoOffset is 1(negative number) we must increment HiOffset.
- if (LoOffset & 0x8000)
- HiOffset++;
- } else
- ExprOffset = Inst.getOperand(2).getExpr();
- // These are some of the types of expansions we perform here:
- // 1) lw $8, sym => lui $8, %hi(sym)
- // lw $8, %lo(sym)($8)
- // 2) lw $8, offset($9) => lui $8, %hi(offset)
- // add $8, $8, $9
- // lw $8, %lo(offset)($9)
- // 3) lw $8, offset($8) => lui $at, %hi(offset)
- // add $at, $at, $8
- // lw $8, %lo(offset)($at)
- // 4) sw $8, sym => lui $at, %hi(sym)
- // sw $8, %lo(sym)($at)
- // 5) sw $8, offset($8) => lui $at, %hi(offset)
- // add $at, $at, $8
- // sw $8, %lo(offset)($at)
- // 6) ldc1 $f0, sym => lui $at, %hi(sym)
- // ldc1 $f0, %lo(sym)($at)
- //
- // For load instructions we can use the destination register as a temporary
- // if base and dst are different (examples 1 and 2) and if the base register
- // is general purpose otherwise we must use $at (example 6) and error if it's
- // not available. For stores we must use $at (examples 4 and 5) because we
- // must not clobber the source register setting up the offset.
+void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsLoad,
+ bool IsImmOpnd) {
+ if (IsLoad) {
+ expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
+ return;
+ }
+ expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
+}
+
+void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsImmOpnd) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
+ unsigned DstReg = Inst.getOperand(0).getReg();
+ unsigned BaseReg = Inst.getOperand(1).getReg();
+
const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
- int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
- unsigned RegClassIDOp0 =
- getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
- bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
- (RegClassIDOp0 == Mips::GPR64RegClassID);
- if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
- TmpRegNum = RegOpNum;
- else {
+ int16_t DstRegClass = Desc.OpInfo[0].RegClass;
+ unsigned DstRegClassID =
+ getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
+ bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
+ (DstRegClassID == Mips::GPR64RegClassID);
+
+ if (IsImmOpnd) {
+ // Try to use DstReg as the temporary.
+ if (IsGPR && (BaseReg != DstReg)) {
+ TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
+ Inst.getOperand(2).getImm(), DstReg, IDLoc,
+ STI);
+ return;
+ }
+
// At this point we need AT to perform the expansions and we exit if it is
// not available.
- TmpRegNum = getATReg(IDLoc);
- if (!TmpRegNum)
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
return;
+
+ TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
+ Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
+ return;
}
- emitRX(Mips::LUi, TmpRegNum,
- isImmOpnd ? MCOperand::createImm(HiOffset)
- : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
- IDLoc, Instructions);
- // Add temp register to base.
- if (BaseRegNum != Mips::ZERO)
- emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
- // And finally, create original instruction with low part
- // of offset and new base.
- emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
- isImmOpnd
- ? MCOperand::createImm(LoOffset)
- : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
- IDLoc, Instructions);
+ const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
+ MCOperand LoOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+ MCOperand HiOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+
+ // Try to use DstReg as the temporary.
+ if (IsGPR && (BaseReg != DstReg)) {
+ TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+ LoOperand, DstReg, IDLoc, STI);
+ return;
+ }
+
+ // At this point we need AT to perform the expansions and we exit if it is
+ // not available.
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return;
+
+ TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+ LoOperand, ATReg, IDLoc, STI);
}
-bool
-MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI,
+ bool IsImmOpnd) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
+ unsigned SrcReg = Inst.getOperand(0).getReg();
+ unsigned BaseReg = Inst.getOperand(1).getReg();
+
+ if (IsImmOpnd) {
+ TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
+ Inst.getOperand(2).getImm(),
+ [&]() { return getATReg(IDLoc); }, IDLoc, STI);
+ return;
+ }
+
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return;
+
+ const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
+ MCOperand LoOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+ MCOperand HiOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+ TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
+ LoOperand, ATReg, IDLoc, STI);
+}
+
+bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
unsigned OpNum = Inst.getNumOperands();
unsigned Opcode = Inst.getOpcode();
unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
@@ -2650,12 +2748,14 @@ MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
}
Inst.setOpcode(NewOpcode);
- Instructions.push_back(Inst);
+ Out.EmitInstruction(Inst, *STI);
return false;
}
bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
bool EmittedNoMacroWarning = false;
unsigned PseudoOpcode = Inst.getOpcode();
unsigned SrcReg = Inst.getOperand(0).getReg();
@@ -2730,7 +2830,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
}
if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
- false, IDLoc, Instructions))
+ false, IDLoc, Out, STI))
return true;
}
@@ -2790,37 +2890,37 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// with GAS' behaviour. However, they may not generate the most efficient
// code in some circumstances.
if (PseudoOpcode == Mips::BLT) {
- emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
return false;
}
if (PseudoOpcode == Mips::BLE) {
- emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
if (PseudoOpcode == Mips::BGE) {
- emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
if (PseudoOpcode == Mips::BGT) {
- emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
return false;
}
if (PseudoOpcode == Mips::BGTU) {
- emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
return false;
}
if (AcceptsEquality) {
// If both registers are $0 and the pseudo-branch accepts equality, it
// will always be taken, so we emit an unconditional branch.
- emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
@@ -2844,8 +2944,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// the pseudo-branch will always be taken, so we emit an unconditional
// branch.
// This only applies to unsigned pseudo-branches.
- emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
@@ -2862,17 +2962,17 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
//
// Because only BLEU and BGEU branch on equality, we can use the
// AcceptsEquality variable to decide when to emit the BEQZ.
- emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
- IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
+ IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
return false;
}
// If we have a signed pseudo-branch and one of the registers is $0,
// we can use an appropriate compare-to-zero branch. We select which one
// to use in the switch statement above.
- emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
- IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
- IDLoc, Instructions);
+ TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
+ IsSrcRegZero ? TrgReg : SrcReg,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
return false;
}
@@ -2900,32 +3000,33 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
//
// The same applies to the unsigned variants, except that SLTu is used
// instead of SLT.
- emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
- ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
- IDLoc, Instructions);
-
- emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
- : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
- ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
+ ReverseOrderSLT ? TrgReg : SrcReg,
+ ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
+
+ TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
+ : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
+ ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
+ STI);
return false;
}
-bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions,
- const bool IsMips64, const bool Signed) {
- if (hasMips32r6()) {
- Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
- return false;
- }
+bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
warnIfNoMacro(IDLoc);
- const MCOperand &RsRegOp = Inst.getOperand(0);
+ const MCOperand &RdRegOp = Inst.getOperand(0);
+ assert(RdRegOp.isReg() && "expected register operand kind");
+ unsigned RdReg = RdRegOp.getReg();
+
+ const MCOperand &RsRegOp = Inst.getOperand(1);
assert(RsRegOp.isReg() && "expected register operand kind");
unsigned RsReg = RsRegOp.getReg();
- const MCOperand &RtRegOp = Inst.getOperand(1);
+ const MCOperand &RtRegOp = Inst.getOperand(2);
assert(RtRegOp.isReg() && "expected register operand kind");
unsigned RtReg = RtRegOp.getReg();
unsigned DivOp;
@@ -2947,15 +3048,15 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
if (IsMips64) {
if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
if (UseTraps) {
- emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
return false;
}
- emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
+ TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
return false;
}
} else {
- emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
+ TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
return false;
}
}
@@ -2964,11 +3065,11 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
Warning(IDLoc, "division by zero");
if (Signed) {
if (UseTraps) {
- emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
return false;
}
- emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
+ TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
return false;
}
}
@@ -2980,22 +3081,21 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
if (UseTraps) {
BranchTarget = IsMips64 ? 12 : 8;
- emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
} else {
BranchTarget = IsMips64 ? 20 : 16;
BranchTargetNoTraps = 8;
// Branch to the li instruction.
- emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
}
- emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
+ TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
if (!UseTraps)
- emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
+ TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
if (!Signed) {
- emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
+ TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
return false;
}
@@ -3003,32 +3103,73 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
if (IsMips64) {
// Branch to the mflo instruction.
- emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
- emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
- emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
+ TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
+ TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
} else {
// Branch to the mflo instruction.
- emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
- emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
+ TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
+ TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
}
if (UseTraps)
- emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
else {
// Branch to the mflo instruction.
- emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
- emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
- emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
+ TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
+ TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
+ TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
+ }
+ TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ return false;
+}
+
+bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
+ SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
+ assert(Inst.getNumOperands() == 3 && "Invalid operand count");
+ assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
+ Inst.getOperand(2).isReg() && "Invalid instruction operand.");
+
+ unsigned FirstReg = Inst.getOperand(0).getReg();
+ unsigned SecondReg = Inst.getOperand(1).getReg();
+ unsigned ThirdReg = Inst.getOperand(2).getReg();
+
+ if (hasMips1() && !hasMips2()) {
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
+ TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
+ TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
+ TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
+ TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
+ TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
+ : Mips::CVT_W_S,
+ FirstReg, SecondReg, IDLoc, STI);
+ TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
+ return false;
}
- emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
+
+ TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
+ : Mips::TRUNC_W_S,
+ FirstReg, SecondReg, IDLoc, STI);
+
return false;
}
bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out, const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
if (hasMips32r6() || hasMips64r6()) {
Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
return false;
@@ -3063,7 +3204,7 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
LoadedOffsetInAT = true;
if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
- true, IDLoc, Instructions))
+ true, IDLoc, Out, STI))
return true;
// NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
@@ -3073,7 +3214,7 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
// NOTE: If there is no source register specified in the ULHU, the parser
// will interpret it as $0.
if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
- createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
+ TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
}
unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
@@ -3091,21 +3232,23 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
- emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
- FirstLbuOffset, IDLoc, Instructions);
+ TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
+ FirstLbuOffset, IDLoc, STI);
- emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
+ STI);
- emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
+ TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
- emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
+ TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
return false;
}
-bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
if (hasMips32r6() || hasMips64r6()) {
Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
return false;
@@ -3137,7 +3280,7 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
warnIfNoMacro(IDLoc);
if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
- true, IDLoc, Instructions))
+ true, IDLoc, Out, STI))
return true;
// NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
@@ -3147,7 +3290,7 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
// NOTE: If there is no source register specified in the ULW, the parser
// will interpret it as $0.
if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
- createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
+ TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
}
unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
@@ -3160,17 +3303,19 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
}
- emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
+ STI);
- emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
+ IDLoc, STI);
return false;
}
bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
assert (Inst.getNumOperands() == 3 && "Invalid operand count");
assert (Inst.getOperand(0).isReg() &&
@@ -3195,7 +3340,7 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
DstReg = ATReg;
}
- if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
+ if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
switch (FinalOpcode) {
default:
llvm_unreachable("unimplemented expansion");
@@ -3226,17 +3371,17 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
}
if (FinalDstReg == Mips::NoRegister)
- emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
else
- emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
- Instructions);
+ TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
return false;
}
return true;
}
-bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3255,13 +3400,13 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
}
if (Inst.getOpcode() == Mips::ROL) {
- emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
return false;
}
if (Inst.getOpcode() == Mips::ROR) {
- emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
return false;
}
@@ -3287,10 +3432,10 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
- emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
+ TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3299,8 +3444,9 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
}
bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
-
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3316,12 +3462,12 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
uint64_t ShiftValue = ImmValue;
if (ImmValue != 0)
ShiftValue = MaxShift - ImmValue;
- emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
return false;
}
if (Inst.getOpcode() == Mips::RORImm) {
- emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
return false;
}
@@ -3331,7 +3477,7 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
if (hasMips32()) {
if (ImmValue == 0) {
- emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
return false;
}
@@ -3352,9 +3498,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
- emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
+ TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3362,9 +3508,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
return true;
}
-bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
-
+bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3383,13 +3529,13 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
}
if (Inst.getOpcode() == Mips::DROL) {
- emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
return false;
}
if (Inst.getOpcode() == Mips::DROR) {
- emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
return false;
}
@@ -3415,10 +3561,10 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
- emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
+ TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3427,8 +3573,9 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
}
bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
-
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3462,7 +3609,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (Inst.getOpcode() == Mips::DROLImm)
ShiftValue = (32 - ImmValue % 32) % 32;
- emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
+ TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
return false;
}
@@ -3470,7 +3617,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (hasMips64()) {
if (ImmValue == 0) {
- emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
return false;
}
@@ -3511,9 +3658,10 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
- emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
+ TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
+ Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3521,49 +3669,76 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
return true;
}
-void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- if (hasShortDelaySlot)
- emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
- else
- emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
-}
+bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ unsigned FirstRegOp = Inst.getOperand(0).getReg();
+ unsigned SecondRegOp = Inst.getOperand(1).getReg();
-void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
- unsigned TrgReg, bool Is64Bit,
- SmallVectorImpl<MCInst> &Instructions) {
- emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
- Instructions);
-}
-
-void MipsAsmParser::createCpRestoreMemOp(
- bool IsLoad, int StackOffset, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- // If the offset can not fit into 16 bits, we need to expand.
- if (!isInt<16>(StackOffset)) {
- MCInst MemInst;
- MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
- MemInst.addOperand(MCOperand::createReg(Mips::GP));
- MemInst.addOperand(MCOperand::createReg(Mips::SP));
- MemInst.addOperand(MCOperand::createImm(StackOffset));
- expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
- return;
- }
+ TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
+ if (FirstRegOp != SecondRegOp)
+ TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
+ else
+ TOut.emitEmptyDelaySlot(false, IDLoc, STI);
+ TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
- emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
- Instructions);
+ return false;
}
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
+ switch (Inst.getOpcode()) {
// As described by the Mips32r2 spec, the registers Rd and Rs for
// jalr.hb must be different.
- unsigned Opcode = Inst.getOpcode();
-
- if (Opcode == Mips::JALR_HB &&
- (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
- return Match_RequiresDifferentSrcAndDst;
-
- return Match_Success;
+ // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
+ // and registers Rd and Base for microMIPS lwp instruction
+ case Mips::JALR_HB:
+ case Mips::JALRC_HB_MMR6:
+ case Mips::JALRC_MMR6:
+ if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
+ return Match_RequiresDifferentSrcAndDst;
+ return Match_Success;
+ case Mips::LWP_MM:
+ case Mips::LWP_MMR6:
+ if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
+ return Match_RequiresDifferentSrcAndDst;
+ return Match_Success;
+ // As described the MIPSR6 spec, the compact branches that compare registers
+ // must:
+ // a) Not use the zero register.
+ // b) Not use the same register twice.
+ // c) rs < rt for bnec, beqc.
+ // NB: For this case, the encoding will swap the operands as their
+ // ordering doesn't matter. GAS performs this transformation too.
+ // Hence, that constraint does not have to be enforced.
+ //
+ // The compact branches that branch iff the signed addition of two registers
+ // would overflow must have rs >= rt. That can be handled like beqc/bnec with
+ // operand swapping. They do not have restriction of using the zero register.
+ case Mips::BLEZC:
+ case Mips::BGEZC:
+ case Mips::BGTZC:
+ case Mips::BLTZC:
+ case Mips::BEQZC:
+ case Mips::BNEZC:
+ if (Inst.getOperand(0).getReg() == Mips::ZERO)
+ return Match_RequiresNoZeroRegister;
+ return Match_Success;
+ case Mips::BGEC:
+ case Mips::BLTC:
+ case Mips::BGEUC:
+ case Mips::BLTUC:
+ case Mips::BEQC:
+ case Mips::BNEC:
+ if (Inst.getOperand(0).getReg() == Mips::ZERO)
+ return Match_RequiresNoZeroRegister;
+ if (Inst.getOperand(1).getReg() == Mips::ZERO)
+ return Match_RequiresNoZeroRegister;
+ if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
+ return Match_RequiresDifferentOperands;
+ return Match_Success;
+ default:
+ return Match_Success;
+ }
}
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
@@ -3584,16 +3759,13 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
bool MatchingInlineAsm) {
MCInst Inst;
- SmallVector<MCInst, 8> Instructions;
unsigned MatchResult =
MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
switch (MatchResult) {
case Match_Success: {
- if (processInstruction(Inst, IDLoc, Instructions))
+ if (processInstruction(Inst, IDLoc, Out, STI))
return true;
- for (unsigned i = 0; i < Instructions.size(); i++)
- Out.EmitInstruction(Instructions[i], getSTI());
return false;
}
case Match_MissingFeature:
@@ -3616,6 +3788,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "invalid instruction");
case Match_RequiresDifferentSrcAndDst:
return Error(IDLoc, "source and destination must be different");
+ case Match_RequiresDifferentOperands:
+ return Error(IDLoc, "registers must be different");
+ case Match_RequiresNoZeroRegister:
+ return Error(IDLoc, "invalid operand ($zero) for instruction");
case Match_Immz:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
case Match_UImm1_0:
@@ -3633,9 +3809,15 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_UImm4_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 4-bit unsigned immediate");
+ case Match_SImm4_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 4-bit signed immediate");
case Match_UImm5_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 5-bit unsigned immediate");
+ case Match_SImm5_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 5-bit signed immediate");
case Match_UImm5_1:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range 1 .. 32");
@@ -3653,21 +3835,81 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_UImm5_Lsl2:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected both 7-bit unsigned immediate and multiple of 4");
+ case Match_UImmRange2_64:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range 2 .. 64");
case Match_UImm6_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit unsigned immediate");
- case Match_SImm6:
+ case Match_UImm6_Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected both 8-bit unsigned immediate and multiple of 4");
+ case Match_SImm6_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit signed immediate");
case Match_UImm7_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 7-bit unsigned immediate");
+ case Match_UImm7_N1:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range -1 .. 126");
+ case Match_SImm7_Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected both 9-bit signed immediate and multiple of 4");
case Match_UImm8_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 8-bit unsigned immediate");
case Match_UImm10_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 10-bit unsigned immediate");
+ case Match_SImm10_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 10-bit signed immediate");
+ case Match_SImm11_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 11-bit signed immediate");
+ case Match_UImm16:
+ case Match_UImm16_Relaxed:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 16-bit unsigned immediate");
+ case Match_SImm16:
+ case Match_SImm16_Relaxed:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 16-bit signed immediate");
+ case Match_UImm20_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 20-bit unsigned immediate");
+ case Match_UImm26_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 26-bit unsigned immediate");
+ case Match_SImm32:
+ case Match_SImm32_Relaxed:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 32-bit signed immediate");
+ case Match_MemSImm9:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 9-bit signed offset");
+ case Match_MemSImm10:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 10-bit signed offset");
+ case Match_MemSImm10Lsl1:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 11-bit signed offset and multiple of 2");
+ case Match_MemSImm10Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 12-bit signed offset and multiple of 4");
+ case Match_MemSImm10Lsl3:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 13-bit signed offset and multiple of 8");
+ case Match_MemSImm11:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 11-bit signed offset");
+ case Match_MemSImm12:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 12-bit signed offset");
+ case Match_MemSImm16:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 16-bit signed offset");
}
llvm_unreachable("Implement any new match types added!");
@@ -3871,19 +4113,6 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) {
return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
}
-unsigned MipsAsmParser::getGPR(int RegNo) {
- return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
- RegNo);
-}
-
-int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
- if (RegNum >
- getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
- return -1;
-
- return getReg(RegClass, RegNum);
-}
-
bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
MCAsmParser &Parser = getParser();
DEBUG(dbgs() << "parseOperand\n");
@@ -3960,63 +4189,41 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
StringRef RelocStr) {
- const MCExpr *Res;
- // Check the type of the expression.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
- // It's a constant, evaluate reloc value.
- int16_t Val;
- switch (getVariantKind(RelocStr)) {
- case MCSymbolRefExpr::VK_Mips_ABS_LO:
- // Get the 1st 16-bits.
- Val = MCE->getValue() & 0xffff;
- break;
- case MCSymbolRefExpr::VK_Mips_ABS_HI:
- // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
- // 16 bits being negative.
- Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
- break;
- case MCSymbolRefExpr::VK_Mips_HIGHER:
- // Get the 3rd 16-bits.
- Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
- break;
- case MCSymbolRefExpr::VK_Mips_HIGHEST:
- // Get the 4th 16-bits.
- Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
- break;
- default:
- report_fatal_error("unsupported reloc value");
- }
- return MCConstantExpr::create(Val, getContext());
- }
-
- if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
- // It's a symbol, create a symbolic expression from the symbol.
- const MCSymbol *Symbol = &MSRE->getSymbol();
- MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
- Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
- return Res;
- }
-
- if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
- MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
-
- // Try to create target expression.
- if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
- return MipsMCExpr::create(VK, Expr, getContext());
-
- const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
- const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
- Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
- return Res;
- }
-
- if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
- const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
- Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
- return Res;
- }
- // Just return the original expression.
- return Expr;
+ if (RelocStr == "hi(%neg(%gp_rel")
+ return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
+ else if (RelocStr == "lo(%neg(%gp_rel")
+ return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
+
+ MipsMCExpr::MipsExprKind Kind =
+ StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
+ .Case("call16", MipsMCExpr::MEK_GOT_CALL)
+ .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
+ .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
+ .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
+ .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
+ .Case("got", MipsMCExpr::MEK_GOT)
+ .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
+ .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
+ .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
+ .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
+ .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
+ .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
+ .Case("gp_rel", MipsMCExpr::MEK_GPREL)
+ .Case("hi", MipsMCExpr::MEK_HI)
+ .Case("higher", MipsMCExpr::MEK_HIGHER)
+ .Case("highest", MipsMCExpr::MEK_HIGHEST)
+ .Case("lo", MipsMCExpr::MEK_LO)
+ .Case("neg", MipsMCExpr::MEK_NEG)
+ .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
+ .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
+ .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
+ .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
+ .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
+ .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
+ .Default(MipsMCExpr::MEK_None);
+
+ assert(Kind != MipsMCExpr::MEK_None);
+ return MipsMCExpr::create(Kind, Expr, getContext());
}
bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
@@ -4248,12 +4455,6 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
llvm_unreachable("Should never ParseFail");
return false;
}
- } else if (Expr->getKind() == MCExpr::Constant) {
- Parser.Lex();
- const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
- Operands.push_back(
- MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
- return true;
}
}
return false;
@@ -4439,46 +4640,6 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) {
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseLSAImm(OperandVector &Operands) {
- MCAsmParser &Parser = getParser();
- switch (getLexer().getKind()) {
- default:
- return MatchOperand_NoMatch;
- case AsmToken::LParen:
- case AsmToken::Plus:
- case AsmToken::Minus:
- case AsmToken::Integer:
- break;
- }
-
- const MCExpr *Expr;
- SMLoc S = Parser.getTok().getLoc();
-
- if (getParser().parseExpression(Expr))
- return MatchOperand_ParseFail;
-
- int64_t Val;
- if (!Expr->evaluateAsAbsolute(Val)) {
- Error(S, "expected immediate value");
- return MatchOperand_ParseFail;
- }
-
- // The LSA instruction allows a 2-bit unsigned immediate. For this reason
- // and because the CPU always adds one to the immediate field, the allowed
- // range becomes 1..4. We'll only check the range here and will deal
- // with the addition/subtraction when actually decoding/encoding
- // the instruction.
- if (Val < 1 || Val > 4) {
- Error(S, "immediate not in range (1..4)");
- return MatchOperand_ParseFail;
- }
-
- Operands.push_back(
- MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
- return MatchOperand_Success;
-}
-
-MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseRegisterList(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
SmallVector<unsigned, 10> Regs;
@@ -4573,10 +4734,10 @@ MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
return MatchOperand_ParseFail;
SMLoc E = Parser.getTok().getLoc();
- MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
- unsigned Reg = Op.getGPR32Reg();
+ MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
+
Operands.pop_back();
- Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
+ Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
return MatchOperand_Success;
}
@@ -4619,42 +4780,6 @@ MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
return MatchOperand_Success;
}
-MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
-
- MCSymbolRefExpr::VariantKind VK =
- StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
- .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
- .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
- .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
- .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
- .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
- .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
- .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
- .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
- .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
- .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
- .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
- .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
- .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
- .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
- .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
- .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
- .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
- .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
- .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
- .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
- .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
- .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
- .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
- .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
- .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
- .Default(MCSymbolRefExpr::VK_None);
-
- assert(VK != MCSymbolRefExpr::VK_None);
-
- return VK;
-}
-
/// Sometimes (i.e. load/stores) the operand may be followed immediately by
/// either this.
/// ::= '(', register, ')'
@@ -4767,6 +4892,8 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
return false;
}
+// FIXME: Given that these have the same name, these should both be
+// consistent on affecting the Parser.
bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
MCAsmParser &Parser = getParser();
SMLoc Loc = getLexer().getLoc();
@@ -5174,7 +5301,7 @@ bool MipsAsmParser::parseSetArchDirective() {
.Case("mips64r3", "mips64r3")
.Case("mips64r5", "mips64r5")
.Case("mips64r6", "mips64r6")
- .Case("cnmips", "cnmips")
+ .Case("octeon", "cnmips")
.Case("r4000", "mips3") // This is an implementation of Mips3.
.Default("");
@@ -5200,6 +5327,7 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
getTargetStreamer().emitDirectiveSetDsp();
break;
case Mips::FeatureMicroMips:
+ setFeatureBits(Mips::FeatureMicroMips, "micromips");
getTargetStreamer().emitDirectiveSetMicroMips();
break;
case Mips::FeatureMips1:
@@ -5356,12 +5484,9 @@ bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
return false;
}
- // Store the $gp on the stack.
- SmallVector<MCInst, 3> StoreInsts;
- createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
- StoreInsts);
-
- getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
+ if (!getTargetStreamer().emitDirectiveCpRestore(
+ CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
+ return true;
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
@@ -5376,7 +5501,6 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
if (ResTy == MatchOperand_NoMatch) {
reportParseError("expected register containing function address");
- Parser.eatToEndOfStatement();
return false;
}
@@ -5502,6 +5626,7 @@ bool MipsAsmParser::parseDirectiveSet() {
} else if (Tok.getString() == "nomips16") {
return parseSetNoMips16Directive();
} else if (Tok.getString() == "nomicromips") {
+ clearFeatureBits(Mips::FeatureMicroMips, "micromips");
getTargetStreamer().emitDirectiveSetNoMicroMips();
Parser.eatToEndOfStatement();
return false;
@@ -5686,6 +5811,24 @@ bool MipsAsmParser::parseInsnDirective() {
return false;
}
+/// parseSSectionDirective
+/// ::= .sbss
+/// ::= .sdata
+bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ MCSection *ELFSection = getContext().getELFSection(
+ Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
+ getParser().getStreamer().SwitchSection(ELFSection);
+
+ getParser().Lex(); // Eat EndOfStatement token.
+ return false;
+}
+
/// parseDirectiveModule
/// ::= .module oddspreg
/// ::= .module nooddspreg
@@ -5905,13 +6048,22 @@ bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
}
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
+ // This returns false if this function recognizes the directive
+ // regardless of whether it is successfully handles or reports an
+ // error. Otherwise it returns true to give the generic parser a
+ // chance at recognizing it.
+
MCAsmParser &Parser = getParser();
StringRef IDVal = DirectiveID.getString();
- if (IDVal == ".cpload")
- return parseDirectiveCpLoad(DirectiveID.getLoc());
- if (IDVal == ".cprestore")
- return parseDirectiveCpRestore(DirectiveID.getLoc());
+ if (IDVal == ".cpload") {
+ parseDirectiveCpLoad(DirectiveID.getLoc());
+ return false;
+ }
+ if (IDVal == ".cprestore") {
+ parseDirectiveCpRestore(DirectiveID.getLoc());
+ return false;
+ }
if (IDVal == ".dword") {
parseDataDirective(8, DirectiveID.getLoc());
return false;
@@ -6068,7 +6220,8 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
}
if (IDVal == ".set") {
- return parseDirectiveSet();
+ parseDirectiveSet();
+ return false;
}
if (IDVal == ".mask" || IDVal == ".fmask") {
@@ -6147,8 +6300,15 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
- if (IDVal == ".option")
- return parseDirectiveOption();
+ if (IDVal == ".hword") {
+ parseDataDirective(2, DirectiveID.getLoc());
+ return false;
+ }
+
+ if (IDVal == ".option") {
+ parseDirectiveOption();
+ return false;
+ }
if (IDVal == ".abicalls") {
getTargetStreamer().emitDirectiveAbiCalls();
@@ -6161,20 +6321,34 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
- if (IDVal == ".cpsetup")
- return parseDirectiveCPSetup();
-
- if (IDVal == ".cpreturn")
- return parseDirectiveCPReturn();
-
- if (IDVal == ".module")
- return parseDirectiveModule();
-
- if (IDVal == ".llvm_internal_mips_reallow_module_directive")
- return parseInternalDirectiveReallowModule();
-
- if (IDVal == ".insn")
- return parseInsnDirective();
+ if (IDVal == ".cpsetup") {
+ parseDirectiveCPSetup();
+ return false;
+ }
+ if (IDVal == ".cpreturn") {
+ parseDirectiveCPReturn();
+ return false;
+ }
+ if (IDVal == ".module") {
+ parseDirectiveModule();
+ return false;
+ }
+ if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
+ parseInternalDirectiveReallowModule();
+ return false;
+ }
+ if (IDVal == ".insn") {
+ parseInsnDirective();
+ return false;
+ }
+ if (IDVal == ".sbss") {
+ parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
+ return false;
+ }
+ if (IDVal == ".sdata") {
+ parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
+ return false;
+ }
return true;
}