xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- PPCAsmParser.cpp - Parse PowerPC asm to MCInst instructions -------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCExpr.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h"
110b57cec5SDimitry Andric #include "PPCTargetStreamer.h"
120b57cec5SDimitry Andric #include "TargetInfo/PowerPCTargetInfo.h"
130b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
140b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
26349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
270b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric 
32bdd1243dSDimitry Andric DEFINE_PPC_REGCLASSES
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric // Evaluate an expression containing condition register
350b57cec5SDimitry Andric // or condition register field symbols.  Returns positive
360b57cec5SDimitry Andric // value on success, or -1 on error.
370b57cec5SDimitry Andric static int64_t
380b57cec5SDimitry Andric EvaluateCRExpr(const MCExpr *E) {
390b57cec5SDimitry Andric   switch (E->getKind()) {
400b57cec5SDimitry Andric   case MCExpr::Target:
410b57cec5SDimitry Andric     return -1;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   case MCExpr::Constant: {
440b57cec5SDimitry Andric     int64_t Res = cast<MCConstantExpr>(E)->getValue();
450b57cec5SDimitry Andric     return Res < 0 ? -1 : Res;
460b57cec5SDimitry Andric   }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   case MCExpr::SymbolRef: {
490b57cec5SDimitry Andric     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
500b57cec5SDimitry Andric     StringRef Name = SRE->getSymbol().getName();
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric     if (Name == "lt") return 0;
530b57cec5SDimitry Andric     if (Name == "gt") return 1;
540b57cec5SDimitry Andric     if (Name == "eq") return 2;
550b57cec5SDimitry Andric     if (Name == "so") return 3;
560b57cec5SDimitry Andric     if (Name == "un") return 3;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric     if (Name == "cr0") return 0;
590b57cec5SDimitry Andric     if (Name == "cr1") return 1;
600b57cec5SDimitry Andric     if (Name == "cr2") return 2;
610b57cec5SDimitry Andric     if (Name == "cr3") return 3;
620b57cec5SDimitry Andric     if (Name == "cr4") return 4;
630b57cec5SDimitry Andric     if (Name == "cr5") return 5;
640b57cec5SDimitry Andric     if (Name == "cr6") return 6;
650b57cec5SDimitry Andric     if (Name == "cr7") return 7;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric     return -1;
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   case MCExpr::Unary:
710b57cec5SDimitry Andric     return -1;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   case MCExpr::Binary: {
740b57cec5SDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
750b57cec5SDimitry Andric     int64_t LHSVal = EvaluateCRExpr(BE->getLHS());
760b57cec5SDimitry Andric     int64_t RHSVal = EvaluateCRExpr(BE->getRHS());
770b57cec5SDimitry Andric     int64_t Res;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric     if (LHSVal < 0 || RHSVal < 0)
800b57cec5SDimitry Andric       return -1;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric     switch (BE->getOpcode()) {
830b57cec5SDimitry Andric     default: return -1;
840b57cec5SDimitry Andric     case MCBinaryExpr::Add: Res = LHSVal + RHSVal; break;
850b57cec5SDimitry Andric     case MCBinaryExpr::Mul: Res = LHSVal * RHSVal; break;
860b57cec5SDimitry Andric     }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric     return Res < 0 ? -1 : Res;
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   llvm_unreachable("Invalid expression kind!");
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric namespace {
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric struct PPCOperand;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric class PPCAsmParser : public MCTargetAsmParser {
1000b57cec5SDimitry Andric   bool IsPPC64;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   bool isPPC64() const { return IsPPC64; }
1050b57cec5SDimitry Andric 
106bdd1243dSDimitry Andric   bool MatchRegisterName(MCRegister &RegNo, int64_t &IntVal);
1070b57cec5SDimitry Andric 
1085f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1095f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1105ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   const MCExpr *ExtractModifierFromExpr(const MCExpr *E,
1130b57cec5SDimitry Andric                                         PPCMCExpr::VariantKind &Variant);
1140b57cec5SDimitry Andric   const MCExpr *FixupVariantKind(const MCExpr *E);
1150b57cec5SDimitry Andric   bool ParseExpression(const MCExpr *&EVal);
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   bool ParseOperand(OperandVector &Operands);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   bool ParseDirectiveWord(unsigned Size, AsmToken ID);
1200b57cec5SDimitry Andric   bool ParseDirectiveTC(unsigned Size, AsmToken ID);
1210b57cec5SDimitry Andric   bool ParseDirectiveMachine(SMLoc L);
1220b57cec5SDimitry Andric   bool ParseDirectiveAbiVersion(SMLoc L);
1230b57cec5SDimitry Andric   bool ParseDirectiveLocalEntry(SMLoc L);
12404eeddc0SDimitry Andric   bool ParseGNUAttribute(SMLoc L);
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1270b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
1280b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
1290b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   void ProcessInstruction(MCInst &Inst, const OperandVector &Ops);
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   /// @name Auto-generated Match Functions
1340b57cec5SDimitry Andric   /// {
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
1370b57cec5SDimitry Andric #include "PPCGenAsmMatcher.inc"
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   /// }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric public:
1430b57cec5SDimitry Andric   PPCAsmParser(const MCSubtargetInfo &STI, MCAsmParser &,
1440b57cec5SDimitry Andric                const MCInstrInfo &MII, const MCTargetOptions &Options)
1450b57cec5SDimitry Andric     : MCTargetAsmParser(Options, STI, MII) {
1460b57cec5SDimitry Andric     // Check for 64-bit vs. 32-bit pointer mode.
1470b57cec5SDimitry Andric     const Triple &TheTriple = STI.getTargetTriple();
1480b57cec5SDimitry Andric     IsPPC64 = TheTriple.isPPC64();
1490b57cec5SDimitry Andric     // Initialize the set of available features.
1500b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1540b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1590b57cec5SDimitry Andric                                       unsigned Kind) override;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   const MCExpr *applyModifierToExpr(const MCExpr *E,
1620b57cec5SDimitry Andric                                     MCSymbolRefExpr::VariantKind,
1630b57cec5SDimitry Andric                                     MCContext &Ctx) override;
1640b57cec5SDimitry Andric };
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric /// PPCOperand - Instances of this class represent a parsed PowerPC machine
1670b57cec5SDimitry Andric /// instruction.
1680b57cec5SDimitry Andric struct PPCOperand : public MCParsedAsmOperand {
1690b57cec5SDimitry Andric   enum KindTy {
1700b57cec5SDimitry Andric     Token,
1710b57cec5SDimitry Andric     Immediate,
1720b57cec5SDimitry Andric     ContextImmediate,
1730b57cec5SDimitry Andric     Expression,
1740b57cec5SDimitry Andric     TLSRegister
1750b57cec5SDimitry Andric   } Kind;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   SMLoc StartLoc, EndLoc;
1780b57cec5SDimitry Andric   bool IsPPC64;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   struct TokOp {
1810b57cec5SDimitry Andric     const char *Data;
1820b57cec5SDimitry Andric     unsigned Length;
1830b57cec5SDimitry Andric   };
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   struct ImmOp {
1860b57cec5SDimitry Andric     int64_t Val;
1870b57cec5SDimitry Andric   };
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   struct ExprOp {
1900b57cec5SDimitry Andric     const MCExpr *Val;
1910b57cec5SDimitry Andric     int64_t CRVal;     // Cached result of EvaluateCRExpr(Val)
1920b57cec5SDimitry Andric   };
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   struct TLSRegOp {
1950b57cec5SDimitry Andric     const MCSymbolRefExpr *Sym;
1960b57cec5SDimitry Andric   };
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   union {
1990b57cec5SDimitry Andric     struct TokOp Tok;
2000b57cec5SDimitry Andric     struct ImmOp Imm;
2010b57cec5SDimitry Andric     struct ExprOp Expr;
2020b57cec5SDimitry Andric     struct TLSRegOp TLSReg;
2030b57cec5SDimitry Andric   };
2040b57cec5SDimitry Andric 
20504eeddc0SDimitry Andric   PPCOperand(KindTy K) : Kind(K) {}
20604eeddc0SDimitry Andric 
2070b57cec5SDimitry Andric public:
2080b57cec5SDimitry Andric   PPCOperand(const PPCOperand &o) : MCParsedAsmOperand() {
2090b57cec5SDimitry Andric     Kind = o.Kind;
2100b57cec5SDimitry Andric     StartLoc = o.StartLoc;
2110b57cec5SDimitry Andric     EndLoc = o.EndLoc;
2120b57cec5SDimitry Andric     IsPPC64 = o.IsPPC64;
2130b57cec5SDimitry Andric     switch (Kind) {
2140b57cec5SDimitry Andric     case Token:
2150b57cec5SDimitry Andric       Tok = o.Tok;
2160b57cec5SDimitry Andric       break;
2170b57cec5SDimitry Andric     case Immediate:
2180b57cec5SDimitry Andric     case ContextImmediate:
2190b57cec5SDimitry Andric       Imm = o.Imm;
2200b57cec5SDimitry Andric       break;
2210b57cec5SDimitry Andric     case Expression:
2220b57cec5SDimitry Andric       Expr = o.Expr;
2230b57cec5SDimitry Andric       break;
2240b57cec5SDimitry Andric     case TLSRegister:
2250b57cec5SDimitry Andric       TLSReg = o.TLSReg;
2260b57cec5SDimitry Andric       break;
2270b57cec5SDimitry Andric     }
2280b57cec5SDimitry Andric   }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   // Disable use of sized deallocation due to overallocation of PPCOperand
2310b57cec5SDimitry Andric   // objects in CreateTokenWithStringCopy.
2320b57cec5SDimitry Andric   void operator delete(void *p) { ::operator delete(p); }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   /// getStartLoc - Get the location of the first token of this operand.
2350b57cec5SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   /// getEndLoc - Get the location of the last token of this operand.
2380b57cec5SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   /// getLocRange - Get the range between the first and last token of this
2410b57cec5SDimitry Andric   /// operand.
2420b57cec5SDimitry Andric   SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   /// isPPC64 - True if this operand is for an instruction in 64-bit mode.
2450b57cec5SDimitry Andric   bool isPPC64() const { return IsPPC64; }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   int64_t getImm() const {
2480b57cec5SDimitry Andric     assert(Kind == Immediate && "Invalid access!");
2490b57cec5SDimitry Andric     return Imm.Val;
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric   int64_t getImmS16Context() const {
2520b57cec5SDimitry Andric     assert((Kind == Immediate || Kind == ContextImmediate) &&
2530b57cec5SDimitry Andric            "Invalid access!");
2540b57cec5SDimitry Andric     if (Kind == Immediate)
2550b57cec5SDimitry Andric       return Imm.Val;
2560b57cec5SDimitry Andric     return static_cast<int16_t>(Imm.Val);
2570b57cec5SDimitry Andric   }
2580b57cec5SDimitry Andric   int64_t getImmU16Context() const {
2590b57cec5SDimitry Andric     assert((Kind == Immediate || Kind == ContextImmediate) &&
2600b57cec5SDimitry Andric            "Invalid access!");
2610b57cec5SDimitry Andric     return Imm.Val;
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   const MCExpr *getExpr() const {
2650b57cec5SDimitry Andric     assert(Kind == Expression && "Invalid access!");
2660b57cec5SDimitry Andric     return Expr.Val;
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   int64_t getExprCRVal() const {
2700b57cec5SDimitry Andric     assert(Kind == Expression && "Invalid access!");
2710b57cec5SDimitry Andric     return Expr.CRVal;
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   const MCExpr *getTLSReg() const {
2750b57cec5SDimitry Andric     assert(Kind == TLSRegister && "Invalid access!");
2760b57cec5SDimitry Andric     return TLSReg.Sym;
2770b57cec5SDimitry Andric   }
2780b57cec5SDimitry Andric 
279*0fca6ea1SDimitry Andric   MCRegister getReg() const override { llvm_unreachable("Not implemented"); }
280*0fca6ea1SDimitry Andric 
281*0fca6ea1SDimitry Andric   unsigned getRegNum() const {
2820b57cec5SDimitry Andric     assert(isRegNumber() && "Invalid access!");
2830b57cec5SDimitry Andric     return (unsigned)Imm.Val;
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
28606c3fb27SDimitry Andric   unsigned getFpReg() const {
28706c3fb27SDimitry Andric     assert(isEvenRegNumber() && "Invalid access!");
28806c3fb27SDimitry Andric     return (unsigned)(Imm.Val >> 1);
28906c3fb27SDimitry Andric   }
29006c3fb27SDimitry Andric 
2910b57cec5SDimitry Andric   unsigned getVSReg() const {
2920b57cec5SDimitry Andric     assert(isVSRegNumber() && "Invalid access!");
2930b57cec5SDimitry Andric     return (unsigned) Imm.Val;
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
296e8d8bef9SDimitry Andric   unsigned getACCReg() const {
297e8d8bef9SDimitry Andric     assert(isACCRegNumber() && "Invalid access!");
298e8d8bef9SDimitry Andric     return (unsigned) Imm.Val;
299e8d8bef9SDimitry Andric   }
300e8d8bef9SDimitry Andric 
301bdd1243dSDimitry Andric   unsigned getDMRROWReg() const {
302bdd1243dSDimitry Andric     assert(isDMRROWRegNumber() && "Invalid access!");
303bdd1243dSDimitry Andric     return (unsigned)Imm.Val;
304bdd1243dSDimitry Andric   }
305bdd1243dSDimitry Andric 
306bdd1243dSDimitry Andric   unsigned getDMRROWpReg() const {
307bdd1243dSDimitry Andric     assert(isDMRROWpRegNumber() && "Invalid access!");
308bdd1243dSDimitry Andric     return (unsigned)Imm.Val;
309bdd1243dSDimitry Andric   }
310bdd1243dSDimitry Andric 
311bdd1243dSDimitry Andric   unsigned getDMRReg() const {
312bdd1243dSDimitry Andric     assert(isDMRRegNumber() && "Invalid access!");
313bdd1243dSDimitry Andric     return (unsigned)Imm.Val;
314bdd1243dSDimitry Andric   }
315bdd1243dSDimitry Andric 
316bdd1243dSDimitry Andric   unsigned getDMRpReg() const {
317bdd1243dSDimitry Andric     assert(isDMRpRegNumber() && "Invalid access!");
318bdd1243dSDimitry Andric     return (unsigned)Imm.Val;
319bdd1243dSDimitry Andric   }
320bdd1243dSDimitry Andric 
321e8d8bef9SDimitry Andric   unsigned getVSRpEvenReg() const {
322e8d8bef9SDimitry Andric     assert(isVSRpEvenRegNumber() && "Invalid access!");
323e8d8bef9SDimitry Andric     return (unsigned) Imm.Val >> 1;
324e8d8bef9SDimitry Andric   }
325e8d8bef9SDimitry Andric 
326fe6060f1SDimitry Andric   unsigned getG8pReg() const {
327fe6060f1SDimitry Andric     assert(isEvenRegNumber() && "Invalid access!");
328fe6060f1SDimitry Andric     return (unsigned)Imm.Val;
329fe6060f1SDimitry Andric   }
330fe6060f1SDimitry Andric 
3310b57cec5SDimitry Andric   unsigned getCCReg() const {
3320b57cec5SDimitry Andric     assert(isCCRegNumber() && "Invalid access!");
3330b57cec5SDimitry Andric     return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal);
3340b57cec5SDimitry Andric   }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   unsigned getCRBit() const {
3370b57cec5SDimitry Andric     assert(isCRBitNumber() && "Invalid access!");
3380b57cec5SDimitry Andric     return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal);
3390b57cec5SDimitry Andric   }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   unsigned getCRBitMask() const {
3420b57cec5SDimitry Andric     assert(isCRBitMask() && "Invalid access!");
34306c3fb27SDimitry Andric     return 7 - llvm::countr_zero<uint64_t>(Imm.Val);
3440b57cec5SDimitry Andric   }
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   bool isToken() const override { return Kind == Token; }
3470b57cec5SDimitry Andric   bool isImm() const override {
3480b57cec5SDimitry Andric     return Kind == Immediate || Kind == Expression;
3490b57cec5SDimitry Andric   }
3500b57cec5SDimitry Andric   bool isU1Imm() const { return Kind == Immediate && isUInt<1>(getImm()); }
3510b57cec5SDimitry Andric   bool isU2Imm() const { return Kind == Immediate && isUInt<2>(getImm()); }
3520b57cec5SDimitry Andric   bool isU3Imm() const { return Kind == Immediate && isUInt<3>(getImm()); }
3530b57cec5SDimitry Andric   bool isU4Imm() const { return Kind == Immediate && isUInt<4>(getImm()); }
3540b57cec5SDimitry Andric   bool isU5Imm() const { return Kind == Immediate && isUInt<5>(getImm()); }
3550b57cec5SDimitry Andric   bool isS5Imm() const { return Kind == Immediate && isInt<5>(getImm()); }
3560b57cec5SDimitry Andric   bool isU6Imm() const { return Kind == Immediate && isUInt<6>(getImm()); }
3570b57cec5SDimitry Andric   bool isU6ImmX2() const { return Kind == Immediate &&
3580b57cec5SDimitry Andric                                   isUInt<6>(getImm()) &&
3590b57cec5SDimitry Andric                                   (getImm() & 1) == 0; }
3600b57cec5SDimitry Andric   bool isU7Imm() const { return Kind == Immediate && isUInt<7>(getImm()); }
3610b57cec5SDimitry Andric   bool isU7ImmX4() const { return Kind == Immediate &&
3620b57cec5SDimitry Andric                                   isUInt<7>(getImm()) &&
3630b57cec5SDimitry Andric                                   (getImm() & 3) == 0; }
3640b57cec5SDimitry Andric   bool isU8Imm() const { return Kind == Immediate && isUInt<8>(getImm()); }
3650b57cec5SDimitry Andric   bool isU8ImmX8() const { return Kind == Immediate &&
3660b57cec5SDimitry Andric                                   isUInt<8>(getImm()) &&
3670b57cec5SDimitry Andric                                   (getImm() & 7) == 0; }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   bool isU10Imm() const { return Kind == Immediate && isUInt<10>(getImm()); }
3700b57cec5SDimitry Andric   bool isU12Imm() const { return Kind == Immediate && isUInt<12>(getImm()); }
3713a9a9c0cSDimitry Andric   bool isU16Imm() const { return isExtImm<16>(/*Signed*/ false, 1); }
3723a9a9c0cSDimitry Andric   bool isS16Imm() const { return isExtImm<16>(/*Signed*/ true, 1); }
3733a9a9c0cSDimitry Andric   bool isS16ImmX4() const { return isExtImm<16>(/*Signed*/ true, 4); }
3743a9a9c0cSDimitry Andric   bool isS16ImmX16() const { return isExtImm<16>(/*Signed*/ true, 16); }
3753a9a9c0cSDimitry Andric   bool isS17Imm() const { return isExtImm<17>(/*Signed*/ true, 1); }
376fe6060f1SDimitry Andric 
377fe6060f1SDimitry Andric   bool isHashImmX8() const {
378fe6060f1SDimitry Andric     // The Hash Imm form is used for instructions that check or store a hash.
379fe6060f1SDimitry Andric     // These instructions have a small immediate range that spans between
380fe6060f1SDimitry Andric     // -8 and -512.
381fe6060f1SDimitry Andric     return (Kind == Immediate && getImm() <= -8 && getImm() >= -512 &&
382fe6060f1SDimitry Andric             (getImm() & 7) == 0);
383fe6060f1SDimitry Andric   }
384fe6060f1SDimitry Andric 
3855ffd83dbSDimitry Andric   bool isS34ImmX16() const {
3865ffd83dbSDimitry Andric     return Kind == Expression ||
3875ffd83dbSDimitry Andric            (Kind == Immediate && isInt<34>(getImm()) && (getImm() & 15) == 0);
3885ffd83dbSDimitry Andric   }
3895ffd83dbSDimitry Andric   bool isS34Imm() const {
3905ffd83dbSDimitry Andric     // Once the PC-Rel ABI is finalized, evaluate whether a 34-bit
3915ffd83dbSDimitry Andric     // ContextImmediate is needed.
3925ffd83dbSDimitry Andric     return Kind == Expression || (Kind == Immediate && isInt<34>(getImm()));
3935ffd83dbSDimitry Andric   }
3945ffd83dbSDimitry Andric 
3950b57cec5SDimitry Andric   bool isTLSReg() const { return Kind == TLSRegister; }
3960b57cec5SDimitry Andric   bool isDirectBr() const {
3970b57cec5SDimitry Andric     if (Kind == Expression)
3980b57cec5SDimitry Andric       return true;
3990b57cec5SDimitry Andric     if (Kind != Immediate)
4000b57cec5SDimitry Andric       return false;
4010b57cec5SDimitry Andric     // Operand must be 64-bit aligned, signed 27-bit immediate.
4020b57cec5SDimitry Andric     if ((getImm() & 3) != 0)
4030b57cec5SDimitry Andric       return false;
4040b57cec5SDimitry Andric     if (isInt<26>(getImm()))
4050b57cec5SDimitry Andric       return true;
4060b57cec5SDimitry Andric     if (!IsPPC64) {
4070b57cec5SDimitry Andric       // In 32-bit mode, large 32-bit quantities wrap around.
4080b57cec5SDimitry Andric       if (isUInt<32>(getImm()) && isInt<26>(static_cast<int32_t>(getImm())))
4090b57cec5SDimitry Andric         return true;
4100b57cec5SDimitry Andric     }
4110b57cec5SDimitry Andric     return false;
4120b57cec5SDimitry Andric   }
4130b57cec5SDimitry Andric   bool isCondBr() const { return Kind == Expression ||
4140b57cec5SDimitry Andric                                  (Kind == Immediate && isInt<16>(getImm()) &&
4150b57cec5SDimitry Andric                                   (getImm() & 3) == 0); }
4165ffd83dbSDimitry Andric   bool isImmZero() const { return Kind == Immediate && getImm() == 0; }
4170b57cec5SDimitry Andric   bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); }
418e8d8bef9SDimitry Andric   bool isACCRegNumber() const {
419e8d8bef9SDimitry Andric     return Kind == Immediate && isUInt<3>(getImm());
420e8d8bef9SDimitry Andric   }
421bdd1243dSDimitry Andric   bool isDMRROWRegNumber() const {
422bdd1243dSDimitry Andric     return Kind == Immediate && isUInt<6>(getImm());
423bdd1243dSDimitry Andric   }
424bdd1243dSDimitry Andric   bool isDMRROWpRegNumber() const {
425bdd1243dSDimitry Andric     return Kind == Immediate && isUInt<5>(getImm());
426bdd1243dSDimitry Andric   }
427bdd1243dSDimitry Andric   bool isDMRRegNumber() const {
428bdd1243dSDimitry Andric     return Kind == Immediate && isUInt<3>(getImm());
429bdd1243dSDimitry Andric   }
430bdd1243dSDimitry Andric   bool isDMRpRegNumber() const {
431bdd1243dSDimitry Andric     return Kind == Immediate && isUInt<2>(getImm());
432bdd1243dSDimitry Andric   }
433e8d8bef9SDimitry Andric   bool isVSRpEvenRegNumber() const {
434e8d8bef9SDimitry Andric     return Kind == Immediate && isUInt<6>(getImm()) && ((getImm() & 1) == 0);
435e8d8bef9SDimitry Andric   }
4360b57cec5SDimitry Andric   bool isVSRegNumber() const {
4370b57cec5SDimitry Andric     return Kind == Immediate && isUInt<6>(getImm());
4380b57cec5SDimitry Andric   }
4390b57cec5SDimitry Andric   bool isCCRegNumber() const { return (Kind == Expression
4400b57cec5SDimitry Andric                                        && isUInt<3>(getExprCRVal())) ||
4410b57cec5SDimitry Andric                                       (Kind == Immediate
4420b57cec5SDimitry Andric                                        && isUInt<3>(getImm())); }
4430b57cec5SDimitry Andric   bool isCRBitNumber() const { return (Kind == Expression
4440b57cec5SDimitry Andric                                        && isUInt<5>(getExprCRVal())) ||
4450b57cec5SDimitry Andric                                       (Kind == Immediate
4460b57cec5SDimitry Andric                                        && isUInt<5>(getImm())); }
447fe6060f1SDimitry Andric 
448fe6060f1SDimitry Andric   bool isEvenRegNumber() const { return isRegNumber() && (getImm() & 1) == 0; }
449fe6060f1SDimitry Andric 
45006c3fb27SDimitry Andric   bool isCRBitMask() const {
45106c3fb27SDimitry Andric     return Kind == Immediate && isUInt<8>(getImm()) &&
45206c3fb27SDimitry Andric            llvm::has_single_bit<uint32_t>(getImm());
45306c3fb27SDimitry Andric   }
4540b57cec5SDimitry Andric   bool isATBitsAsHint() const { return false; }
4550b57cec5SDimitry Andric   bool isMem() const override { return false; }
4560b57cec5SDimitry Andric   bool isReg() const override { return false; }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
4590b57cec5SDimitry Andric     llvm_unreachable("addRegOperands");
4600b57cec5SDimitry Andric   }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   void addRegGPRCOperands(MCInst &Inst, unsigned N) const {
4630b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
464*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(RRegs[getRegNum()]));
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   void addRegGPRCNoR0Operands(MCInst &Inst, unsigned N) const {
4680b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
469*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(RRegsNoR0[getRegNum()]));
4700b57cec5SDimitry Andric   }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   void addRegG8RCOperands(MCInst &Inst, unsigned N) const {
4730b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
474*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(XRegs[getRegNum()]));
4750b57cec5SDimitry Andric   }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   void addRegG8RCNoX0Operands(MCInst &Inst, unsigned N) const {
4780b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
479*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(XRegsNoX0[getRegNum()]));
4800b57cec5SDimitry Andric   }
4810b57cec5SDimitry Andric 
482fe6060f1SDimitry Andric   void addRegG8pRCOperands(MCInst &Inst, unsigned N) const {
483fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
484fe6060f1SDimitry Andric     Inst.addOperand(MCOperand::createReg(XRegs[getG8pReg()]));
485fe6060f1SDimitry Andric   }
486fe6060f1SDimitry Andric 
4870b57cec5SDimitry Andric   void addRegGxRCOperands(MCInst &Inst, unsigned N) const {
4880b57cec5SDimitry Andric     if (isPPC64())
4890b57cec5SDimitry Andric       addRegG8RCOperands(Inst, N);
4900b57cec5SDimitry Andric     else
4910b57cec5SDimitry Andric       addRegGPRCOperands(Inst, N);
4920b57cec5SDimitry Andric   }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   void addRegGxRCNoR0Operands(MCInst &Inst, unsigned N) const {
4950b57cec5SDimitry Andric     if (isPPC64())
4960b57cec5SDimitry Andric       addRegG8RCNoX0Operands(Inst, N);
4970b57cec5SDimitry Andric     else
4980b57cec5SDimitry Andric       addRegGPRCNoR0Operands(Inst, N);
4990b57cec5SDimitry Andric   }
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   void addRegF4RCOperands(MCInst &Inst, unsigned N) const {
5020b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
503*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(FRegs[getRegNum()]));
5040b57cec5SDimitry Andric   }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric   void addRegF8RCOperands(MCInst &Inst, unsigned N) const {
5070b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
508*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(FRegs[getRegNum()]));
5090b57cec5SDimitry Andric   }
5100b57cec5SDimitry Andric 
51106c3fb27SDimitry Andric   void addRegFpRCOperands(MCInst &Inst, unsigned N) const {
51206c3fb27SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
51306c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createReg(FpRegs[getFpReg()]));
51406c3fb27SDimitry Andric   }
51506c3fb27SDimitry Andric 
5160b57cec5SDimitry Andric   void addRegVFRCOperands(MCInst &Inst, unsigned N) const {
5170b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
518*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(VFRegs[getRegNum()]));
5190b57cec5SDimitry Andric   }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   void addRegVRRCOperands(MCInst &Inst, unsigned N) const {
5220b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
523*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(VRegs[getRegNum()]));
5240b57cec5SDimitry Andric   }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   void addRegVSRCOperands(MCInst &Inst, unsigned N) const {
5270b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
5280b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(VSRegs[getVSReg()]));
5290b57cec5SDimitry Andric   }
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   void addRegVSFRCOperands(MCInst &Inst, unsigned N) const {
5320b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
5330b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(VSFRegs[getVSReg()]));
5340b57cec5SDimitry Andric   }
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   void addRegVSSRCOperands(MCInst &Inst, unsigned N) const {
5370b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
5380b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(VSSRegs[getVSReg()]));
5390b57cec5SDimitry Andric   }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   void addRegSPE4RCOperands(MCInst &Inst, unsigned N) const {
5420b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
543*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(RRegs[getRegNum()]));
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   void addRegSPERCOperands(MCInst &Inst, unsigned N) const {
5470b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
548*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createReg(SPERegs[getRegNum()]));
5490b57cec5SDimitry Andric   }
5500b57cec5SDimitry Andric 
551e8d8bef9SDimitry Andric   void addRegACCRCOperands(MCInst &Inst, unsigned N) const {
552e8d8bef9SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
553e8d8bef9SDimitry Andric     Inst.addOperand(MCOperand::createReg(ACCRegs[getACCReg()]));
554e8d8bef9SDimitry Andric   }
555e8d8bef9SDimitry Andric 
556bdd1243dSDimitry Andric   void addRegDMRROWRCOperands(MCInst &Inst, unsigned N) const {
557bdd1243dSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
558bdd1243dSDimitry Andric     Inst.addOperand(MCOperand::createReg(DMRROWRegs[getDMRROWReg()]));
559bdd1243dSDimitry Andric   }
560bdd1243dSDimitry Andric 
561bdd1243dSDimitry Andric   void addRegDMRROWpRCOperands(MCInst &Inst, unsigned N) const {
562bdd1243dSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
563bdd1243dSDimitry Andric     Inst.addOperand(MCOperand::createReg(DMRROWpRegs[getDMRROWpReg()]));
564bdd1243dSDimitry Andric   }
565bdd1243dSDimitry Andric 
566bdd1243dSDimitry Andric   void addRegDMRRCOperands(MCInst &Inst, unsigned N) const {
567bdd1243dSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
568bdd1243dSDimitry Andric     Inst.addOperand(MCOperand::createReg(DMRRegs[getDMRReg()]));
569bdd1243dSDimitry Andric   }
570bdd1243dSDimitry Andric 
571bdd1243dSDimitry Andric   void addRegDMRpRCOperands(MCInst &Inst, unsigned N) const {
572bdd1243dSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
573bdd1243dSDimitry Andric     Inst.addOperand(MCOperand::createReg(DMRpRegs[getDMRpReg()]));
574bdd1243dSDimitry Andric   }
575bdd1243dSDimitry Andric 
576bdd1243dSDimitry Andric   void addRegWACCRCOperands(MCInst &Inst, unsigned N) const {
577bdd1243dSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
578bdd1243dSDimitry Andric     Inst.addOperand(MCOperand::createReg(WACCRegs[getACCReg()]));
579bdd1243dSDimitry Andric   }
580bdd1243dSDimitry Andric 
581bdd1243dSDimitry Andric   void addRegWACC_HIRCOperands(MCInst &Inst, unsigned N) const {
582bdd1243dSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
583bdd1243dSDimitry Andric     Inst.addOperand(MCOperand::createReg(WACC_HIRegs[getACCReg()]));
584bdd1243dSDimitry Andric   }
585bdd1243dSDimitry Andric 
586e8d8bef9SDimitry Andric   void addRegVSRpRCOperands(MCInst &Inst, unsigned N) const {
587e8d8bef9SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
588e8d8bef9SDimitry Andric     Inst.addOperand(MCOperand::createReg(VSRpRegs[getVSRpEvenReg()]));
589e8d8bef9SDimitry Andric   }
590e8d8bef9SDimitry Andric 
591e8d8bef9SDimitry Andric   void addRegVSRpEvenRCOperands(MCInst &Inst, unsigned N) const {
592e8d8bef9SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
593e8d8bef9SDimitry Andric     Inst.addOperand(MCOperand::createReg(VSRpRegs[getVSRpEvenReg()]));
594e8d8bef9SDimitry Andric   }
595e8d8bef9SDimitry Andric 
5960b57cec5SDimitry Andric   void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const {
5970b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
5980b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(CRBITRegs[getCRBit()]));
5990b57cec5SDimitry Andric   }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   void addRegCRRCOperands(MCInst &Inst, unsigned N) const {
6020b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
6030b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(CRRegs[getCCReg()]));
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   void addCRBitMaskOperands(MCInst &Inst, unsigned N) const {
6070b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
6080b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(CRRegs[getCRBitMask()]));
6090b57cec5SDimitry Andric   }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
6120b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
6130b57cec5SDimitry Andric     if (Kind == Immediate)
6140b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(getImm()));
6150b57cec5SDimitry Andric     else
6160b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(getExpr()));
6170b57cec5SDimitry Andric   }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   void addS16ImmOperands(MCInst &Inst, unsigned N) const {
6200b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
6210b57cec5SDimitry Andric     switch (Kind) {
6220b57cec5SDimitry Andric       case Immediate:
6230b57cec5SDimitry Andric         Inst.addOperand(MCOperand::createImm(getImm()));
6240b57cec5SDimitry Andric         break;
6250b57cec5SDimitry Andric       case ContextImmediate:
6260b57cec5SDimitry Andric         Inst.addOperand(MCOperand::createImm(getImmS16Context()));
6270b57cec5SDimitry Andric         break;
6280b57cec5SDimitry Andric       default:
6290b57cec5SDimitry Andric         Inst.addOperand(MCOperand::createExpr(getExpr()));
6300b57cec5SDimitry Andric         break;
6310b57cec5SDimitry Andric     }
6320b57cec5SDimitry Andric   }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   void addU16ImmOperands(MCInst &Inst, unsigned N) const {
6350b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
6360b57cec5SDimitry Andric     switch (Kind) {
6370b57cec5SDimitry Andric       case Immediate:
6380b57cec5SDimitry Andric         Inst.addOperand(MCOperand::createImm(getImm()));
6390b57cec5SDimitry Andric         break;
6400b57cec5SDimitry Andric       case ContextImmediate:
6410b57cec5SDimitry Andric         Inst.addOperand(MCOperand::createImm(getImmU16Context()));
6420b57cec5SDimitry Andric         break;
6430b57cec5SDimitry Andric       default:
6440b57cec5SDimitry Andric         Inst.addOperand(MCOperand::createExpr(getExpr()));
6450b57cec5SDimitry Andric         break;
6460b57cec5SDimitry Andric     }
6470b57cec5SDimitry Andric   }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   void addBranchTargetOperands(MCInst &Inst, unsigned N) const {
6500b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
6510b57cec5SDimitry Andric     if (Kind == Immediate)
6520b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(getImm() / 4));
6530b57cec5SDimitry Andric     else
6540b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(getExpr()));
6550b57cec5SDimitry Andric   }
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   void addTLSRegOperands(MCInst &Inst, unsigned N) const {
6580b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
6590b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createExpr(getTLSReg()));
6600b57cec5SDimitry Andric   }
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   StringRef getToken() const {
6630b57cec5SDimitry Andric     assert(Kind == Token && "Invalid access!");
6640b57cec5SDimitry Andric     return StringRef(Tok.Data, Tok.Length);
6650b57cec5SDimitry Andric   }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   void print(raw_ostream &OS) const override;
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   static std::unique_ptr<PPCOperand> CreateToken(StringRef Str, SMLoc S,
6700b57cec5SDimitry Andric                                                  bool IsPPC64) {
6718bcb0991SDimitry Andric     auto Op = std::make_unique<PPCOperand>(Token);
6720b57cec5SDimitry Andric     Op->Tok.Data = Str.data();
6730b57cec5SDimitry Andric     Op->Tok.Length = Str.size();
6740b57cec5SDimitry Andric     Op->StartLoc = S;
6750b57cec5SDimitry Andric     Op->EndLoc = S;
6760b57cec5SDimitry Andric     Op->IsPPC64 = IsPPC64;
6770b57cec5SDimitry Andric     return Op;
6780b57cec5SDimitry Andric   }
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric   static std::unique_ptr<PPCOperand>
6810b57cec5SDimitry Andric   CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64) {
6820b57cec5SDimitry Andric     // Allocate extra memory for the string and copy it.
6830b57cec5SDimitry Andric     // FIXME: This is incorrect, Operands are owned by unique_ptr with a default
6840b57cec5SDimitry Andric     // deleter which will destroy them by simply using "delete", not correctly
6850b57cec5SDimitry Andric     // calling operator delete on this extra memory after calling the dtor
6860b57cec5SDimitry Andric     // explicitly.
6870b57cec5SDimitry Andric     void *Mem = ::operator new(sizeof(PPCOperand) + Str.size());
6880b57cec5SDimitry Andric     std::unique_ptr<PPCOperand> Op(new (Mem) PPCOperand(Token));
6890b57cec5SDimitry Andric     Op->Tok.Data = reinterpret_cast<const char *>(Op.get() + 1);
6900b57cec5SDimitry Andric     Op->Tok.Length = Str.size();
6910b57cec5SDimitry Andric     std::memcpy(const_cast<char *>(Op->Tok.Data), Str.data(), Str.size());
6920b57cec5SDimitry Andric     Op->StartLoc = S;
6930b57cec5SDimitry Andric     Op->EndLoc = S;
6940b57cec5SDimitry Andric     Op->IsPPC64 = IsPPC64;
6950b57cec5SDimitry Andric     return Op;
6960b57cec5SDimitry Andric   }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric   static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
6990b57cec5SDimitry Andric                                                bool IsPPC64) {
7008bcb0991SDimitry Andric     auto Op = std::make_unique<PPCOperand>(Immediate);
7010b57cec5SDimitry Andric     Op->Imm.Val = Val;
7020b57cec5SDimitry Andric     Op->StartLoc = S;
7030b57cec5SDimitry Andric     Op->EndLoc = E;
7040b57cec5SDimitry Andric     Op->IsPPC64 = IsPPC64;
7050b57cec5SDimitry Andric     return Op;
7060b57cec5SDimitry Andric   }
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S,
7090b57cec5SDimitry Andric                                                 SMLoc E, bool IsPPC64) {
7108bcb0991SDimitry Andric     auto Op = std::make_unique<PPCOperand>(Expression);
7110b57cec5SDimitry Andric     Op->Expr.Val = Val;
7120b57cec5SDimitry Andric     Op->Expr.CRVal = EvaluateCRExpr(Val);
7130b57cec5SDimitry Andric     Op->StartLoc = S;
7140b57cec5SDimitry Andric     Op->EndLoc = E;
7150b57cec5SDimitry Andric     Op->IsPPC64 = IsPPC64;
7160b57cec5SDimitry Andric     return Op;
7170b57cec5SDimitry Andric   }
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric   static std::unique_ptr<PPCOperand>
7200b57cec5SDimitry Andric   CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64) {
7218bcb0991SDimitry Andric     auto Op = std::make_unique<PPCOperand>(TLSRegister);
7220b57cec5SDimitry Andric     Op->TLSReg.Sym = Sym;
7230b57cec5SDimitry Andric     Op->StartLoc = S;
7240b57cec5SDimitry Andric     Op->EndLoc = E;
7250b57cec5SDimitry Andric     Op->IsPPC64 = IsPPC64;
7260b57cec5SDimitry Andric     return Op;
7270b57cec5SDimitry Andric   }
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   static std::unique_ptr<PPCOperand>
7300b57cec5SDimitry Andric   CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) {
7318bcb0991SDimitry Andric     auto Op = std::make_unique<PPCOperand>(ContextImmediate);
7320b57cec5SDimitry Andric     Op->Imm.Val = Val;
7330b57cec5SDimitry Andric     Op->StartLoc = S;
7340b57cec5SDimitry Andric     Op->EndLoc = E;
7350b57cec5SDimitry Andric     Op->IsPPC64 = IsPPC64;
7360b57cec5SDimitry Andric     return Op;
7370b57cec5SDimitry Andric   }
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric   static std::unique_ptr<PPCOperand>
7400b57cec5SDimitry Andric   CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) {
7410b57cec5SDimitry Andric     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
7420b57cec5SDimitry Andric       return CreateImm(CE->getValue(), S, E, IsPPC64);
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric     if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val))
745e8d8bef9SDimitry Andric       if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS ||
746e8d8bef9SDimitry Andric           SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL)
7470b57cec5SDimitry Andric         return CreateTLSReg(SRE, S, E, IsPPC64);
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric     if (const PPCMCExpr *TE = dyn_cast<PPCMCExpr>(Val)) {
7500b57cec5SDimitry Andric       int64_t Res;
7510b57cec5SDimitry Andric       if (TE->evaluateAsConstant(Res))
7520b57cec5SDimitry Andric         return CreateContextImm(Res, S, E, IsPPC64);
7530b57cec5SDimitry Andric     }
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric     return CreateExpr(Val, S, E, IsPPC64);
7560b57cec5SDimitry Andric   }
7573a9a9c0cSDimitry Andric 
7583a9a9c0cSDimitry Andric private:
7593a9a9c0cSDimitry Andric   template <unsigned Width>
7603a9a9c0cSDimitry Andric   bool isExtImm(bool Signed, unsigned Multiple) const {
7613a9a9c0cSDimitry Andric     switch (Kind) {
7623a9a9c0cSDimitry Andric     default:
7633a9a9c0cSDimitry Andric       return false;
7643a9a9c0cSDimitry Andric     case Expression:
7653a9a9c0cSDimitry Andric       return true;
7663a9a9c0cSDimitry Andric     case Immediate:
7673a9a9c0cSDimitry Andric     case ContextImmediate:
7683a9a9c0cSDimitry Andric       if (Signed)
7693a9a9c0cSDimitry Andric         return isInt<Width>(getImmS16Context()) &&
7703a9a9c0cSDimitry Andric                (getImmS16Context() & (Multiple - 1)) == 0;
7713a9a9c0cSDimitry Andric       else
7723a9a9c0cSDimitry Andric         return isUInt<Width>(getImmU16Context()) &&
7733a9a9c0cSDimitry Andric                (getImmU16Context() & (Multiple - 1)) == 0;
7743a9a9c0cSDimitry Andric     }
7753a9a9c0cSDimitry Andric   }
7760b57cec5SDimitry Andric };
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric } // end anonymous namespace.
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric void PPCOperand::print(raw_ostream &OS) const {
7810b57cec5SDimitry Andric   switch (Kind) {
7820b57cec5SDimitry Andric   case Token:
7830b57cec5SDimitry Andric     OS << "'" << getToken() << "'";
7840b57cec5SDimitry Andric     break;
7850b57cec5SDimitry Andric   case Immediate:
7860b57cec5SDimitry Andric   case ContextImmediate:
7870b57cec5SDimitry Andric     OS << getImm();
7880b57cec5SDimitry Andric     break;
7890b57cec5SDimitry Andric   case Expression:
7900b57cec5SDimitry Andric     OS << *getExpr();
7910b57cec5SDimitry Andric     break;
7920b57cec5SDimitry Andric   case TLSRegister:
7930b57cec5SDimitry Andric     OS << *getTLSReg();
7940b57cec5SDimitry Andric     break;
7950b57cec5SDimitry Andric   }
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric static void
7990b57cec5SDimitry Andric addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) {
8000b57cec5SDimitry Andric   if (Op.isImm()) {
8010b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createImm(-Op.getImm()));
8020b57cec5SDimitry Andric     return;
8030b57cec5SDimitry Andric   }
8040b57cec5SDimitry Andric   const MCExpr *Expr = Op.getExpr();
8050b57cec5SDimitry Andric   if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Expr)) {
8060b57cec5SDimitry Andric     if (UnExpr->getOpcode() == MCUnaryExpr::Minus) {
8070b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(UnExpr->getSubExpr()));
8080b57cec5SDimitry Andric       return;
8090b57cec5SDimitry Andric     }
8100b57cec5SDimitry Andric   } else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) {
8110b57cec5SDimitry Andric     if (BinExpr->getOpcode() == MCBinaryExpr::Sub) {
8120b57cec5SDimitry Andric       const MCExpr *NE = MCBinaryExpr::createSub(BinExpr->getRHS(),
8130b57cec5SDimitry Andric                                                  BinExpr->getLHS(), Ctx);
8140b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(NE));
8150b57cec5SDimitry Andric       return;
8160b57cec5SDimitry Andric     }
8170b57cec5SDimitry Andric   }
8180b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createExpr(MCUnaryExpr::createMinus(Expr, Ctx)));
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric void PPCAsmParser::ProcessInstruction(MCInst &Inst,
8220b57cec5SDimitry Andric                                       const OperandVector &Operands) {
8230b57cec5SDimitry Andric   int Opcode = Inst.getOpcode();
8240b57cec5SDimitry Andric   switch (Opcode) {
8250b57cec5SDimitry Andric   case PPC::DCBTx:
8260b57cec5SDimitry Andric   case PPC::DCBTT:
8270b57cec5SDimitry Andric   case PPC::DCBTSTx:
8280b57cec5SDimitry Andric   case PPC::DCBTSTT: {
8290b57cec5SDimitry Andric     MCInst TmpInst;
8300b57cec5SDimitry Andric     TmpInst.setOpcode((Opcode == PPC::DCBTx || Opcode == PPC::DCBTT) ?
8310b57cec5SDimitry Andric                       PPC::DCBT : PPC::DCBTST);
8320b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(
8330b57cec5SDimitry Andric       (Opcode == PPC::DCBTx || Opcode == PPC::DCBTSTx) ? 0 : 16));
8340b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
8350b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
8360b57cec5SDimitry Andric     Inst = TmpInst;
8370b57cec5SDimitry Andric     break;
8380b57cec5SDimitry Andric   }
8390b57cec5SDimitry Andric   case PPC::DCBTCT:
8400b57cec5SDimitry Andric   case PPC::DCBTDS: {
8410b57cec5SDimitry Andric     MCInst TmpInst;
8420b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::DCBT);
8430b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(2));
8440b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
8450b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
8460b57cec5SDimitry Andric     Inst = TmpInst;
8470b57cec5SDimitry Andric     break;
8480b57cec5SDimitry Andric   }
8490b57cec5SDimitry Andric   case PPC::DCBTSTCT:
8500b57cec5SDimitry Andric   case PPC::DCBTSTDS: {
8510b57cec5SDimitry Andric     MCInst TmpInst;
8520b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::DCBTST);
8530b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(2));
8540b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
8550b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
8560b57cec5SDimitry Andric     Inst = TmpInst;
8570b57cec5SDimitry Andric     break;
8580b57cec5SDimitry Andric   }
8590b57cec5SDimitry Andric   case PPC::DCBFx:
8600b57cec5SDimitry Andric   case PPC::DCBFL:
861e8d8bef9SDimitry Andric   case PPC::DCBFLP:
862e8d8bef9SDimitry Andric   case PPC::DCBFPS:
863e8d8bef9SDimitry Andric   case PPC::DCBSTPS: {
8640b57cec5SDimitry Andric     int L = 0;
8650b57cec5SDimitry Andric     if (Opcode == PPC::DCBFL)
8660b57cec5SDimitry Andric       L = 1;
8670b57cec5SDimitry Andric     else if (Opcode == PPC::DCBFLP)
8680b57cec5SDimitry Andric       L = 3;
869e8d8bef9SDimitry Andric     else if (Opcode == PPC::DCBFPS)
870e8d8bef9SDimitry Andric       L = 4;
871e8d8bef9SDimitry Andric     else if (Opcode == PPC::DCBSTPS)
872e8d8bef9SDimitry Andric       L = 6;
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric     MCInst TmpInst;
8750b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::DCBF);
8760b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(L));
8770b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
8780b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
8790b57cec5SDimitry Andric     Inst = TmpInst;
8800b57cec5SDimitry Andric     break;
8810b57cec5SDimitry Andric   }
8820b57cec5SDimitry Andric   case PPC::LAx: {
8830b57cec5SDimitry Andric     MCInst TmpInst;
8840b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::LA);
8850b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
8860b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(2));
8870b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
8880b57cec5SDimitry Andric     Inst = TmpInst;
8890b57cec5SDimitry Andric     break;
8900b57cec5SDimitry Andric   }
8915f757f3fSDimitry Andric   case PPC::PLA8:
8925f757f3fSDimitry Andric   case PPC::PLA: {
8935f757f3fSDimitry Andric     MCInst TmpInst;
8945f757f3fSDimitry Andric     TmpInst.setOpcode(Opcode == PPC::PLA ? PPC::PADDI : PPC::PADDI8);
8955f757f3fSDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
8965f757f3fSDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
8975f757f3fSDimitry Andric     TmpInst.addOperand(Inst.getOperand(2));
8985f757f3fSDimitry Andric     Inst = TmpInst;
8995f757f3fSDimitry Andric     break;
9005f757f3fSDimitry Andric   }
9015f757f3fSDimitry Andric   case PPC::PLA8pc:
9025f757f3fSDimitry Andric   case PPC::PLApc: {
9035f757f3fSDimitry Andric     MCInst TmpInst;
9045f757f3fSDimitry Andric     TmpInst.setOpcode(Opcode == PPC::PLApc ? PPC::PADDIpc : PPC::PADDI8pc);
9055f757f3fSDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9065f757f3fSDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
9075f757f3fSDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9085f757f3fSDimitry Andric     Inst = TmpInst;
9095f757f3fSDimitry Andric     break;
9105f757f3fSDimitry Andric   }
9110b57cec5SDimitry Andric   case PPC::SUBI: {
9120b57cec5SDimitry Andric     MCInst TmpInst;
9130b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::ADDI);
9140b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9150b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9160b57cec5SDimitry Andric     addNegOperand(TmpInst, Inst.getOperand(2), getContext());
9170b57cec5SDimitry Andric     Inst = TmpInst;
9180b57cec5SDimitry Andric     break;
9190b57cec5SDimitry Andric   }
9205f757f3fSDimitry Andric   case PPC::PSUBI: {
9215f757f3fSDimitry Andric     MCInst TmpInst;
9225f757f3fSDimitry Andric     TmpInst.setOpcode(PPC::PADDI);
9235f757f3fSDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9245f757f3fSDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9255f757f3fSDimitry Andric     addNegOperand(TmpInst, Inst.getOperand(2), getContext());
9265f757f3fSDimitry Andric     Inst = TmpInst;
9275f757f3fSDimitry Andric     break;
9285f757f3fSDimitry Andric   }
9290b57cec5SDimitry Andric   case PPC::SUBIS: {
9300b57cec5SDimitry Andric     MCInst TmpInst;
9310b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::ADDIS);
9320b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9330b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9340b57cec5SDimitry Andric     addNegOperand(TmpInst, Inst.getOperand(2), getContext());
9350b57cec5SDimitry Andric     Inst = TmpInst;
9360b57cec5SDimitry Andric     break;
9370b57cec5SDimitry Andric   }
9380b57cec5SDimitry Andric   case PPC::SUBIC: {
9390b57cec5SDimitry Andric     MCInst TmpInst;
9400b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::ADDIC);
9410b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9420b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9430b57cec5SDimitry Andric     addNegOperand(TmpInst, Inst.getOperand(2), getContext());
9440b57cec5SDimitry Andric     Inst = TmpInst;
9450b57cec5SDimitry Andric     break;
9460b57cec5SDimitry Andric   }
947480093f4SDimitry Andric   case PPC::SUBIC_rec: {
9480b57cec5SDimitry Andric     MCInst TmpInst;
949480093f4SDimitry Andric     TmpInst.setOpcode(PPC::ADDIC_rec);
9500b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9510b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9520b57cec5SDimitry Andric     addNegOperand(TmpInst, Inst.getOperand(2), getContext());
9530b57cec5SDimitry Andric     Inst = TmpInst;
9540b57cec5SDimitry Andric     break;
9550b57cec5SDimitry Andric   }
9560b57cec5SDimitry Andric   case PPC::EXTLWI:
957480093f4SDimitry Andric   case PPC::EXTLWI_rec: {
9580b57cec5SDimitry Andric     MCInst TmpInst;
9590b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
9600b57cec5SDimitry Andric     int64_t B = Inst.getOperand(3).getImm();
961480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::EXTLWI ? PPC::RLWINM : PPC::RLWINM_rec);
9620b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9630b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9640b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B));
9650b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
9660b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N - 1));
9670b57cec5SDimitry Andric     Inst = TmpInst;
9680b57cec5SDimitry Andric     break;
9690b57cec5SDimitry Andric   }
9700b57cec5SDimitry Andric   case PPC::EXTRWI:
971480093f4SDimitry Andric   case PPC::EXTRWI_rec: {
9720b57cec5SDimitry Andric     MCInst TmpInst;
9730b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
9740b57cec5SDimitry Andric     int64_t B = Inst.getOperand(3).getImm();
975480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::EXTRWI ? PPC::RLWINM : PPC::RLWINM_rec);
9760b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9770b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9780b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B + N));
9790b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(32 - N));
9800b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(31));
9810b57cec5SDimitry Andric     Inst = TmpInst;
9820b57cec5SDimitry Andric     break;
9830b57cec5SDimitry Andric   }
9840b57cec5SDimitry Andric   case PPC::INSLWI:
985480093f4SDimitry Andric   case PPC::INSLWI_rec: {
9860b57cec5SDimitry Andric     MCInst TmpInst;
9870b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
9880b57cec5SDimitry Andric     int64_t B = Inst.getOperand(3).getImm();
989480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::INSLWI ? PPC::RLWIMI : PPC::RLWIMI_rec);
9900b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9910b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
9920b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
9930b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(32 - B));
9940b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B));
9950b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm((B + N) - 1));
9960b57cec5SDimitry Andric     Inst = TmpInst;
9970b57cec5SDimitry Andric     break;
9980b57cec5SDimitry Andric   }
9990b57cec5SDimitry Andric   case PPC::INSRWI:
1000480093f4SDimitry Andric   case PPC::INSRWI_rec: {
10010b57cec5SDimitry Andric     MCInst TmpInst;
10020b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
10030b57cec5SDimitry Andric     int64_t B = Inst.getOperand(3).getImm();
1004480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::INSRWI ? PPC::RLWIMI : PPC::RLWIMI_rec);
10050b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10060b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10070b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
10080b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(32 - (B + N)));
10090b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B));
10100b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm((B + N) - 1));
10110b57cec5SDimitry Andric     Inst = TmpInst;
10120b57cec5SDimitry Andric     break;
10130b57cec5SDimitry Andric   }
10140b57cec5SDimitry Andric   case PPC::ROTRWI:
1015480093f4SDimitry Andric   case PPC::ROTRWI_rec: {
10160b57cec5SDimitry Andric     MCInst TmpInst;
10170b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1018480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::ROTRWI ? PPC::RLWINM : PPC::RLWINM_rec);
10190b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10200b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
10210b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(32 - N));
10220b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
10230b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(31));
10240b57cec5SDimitry Andric     Inst = TmpInst;
10250b57cec5SDimitry Andric     break;
10260b57cec5SDimitry Andric   }
10270b57cec5SDimitry Andric   case PPC::SLWI:
1028480093f4SDimitry Andric   case PPC::SLWI_rec: {
10290b57cec5SDimitry Andric     MCInst TmpInst;
10300b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1031480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::SLWI ? PPC::RLWINM : PPC::RLWINM_rec);
10320b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10330b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
10340b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N));
10350b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
10360b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(31 - N));
10370b57cec5SDimitry Andric     Inst = TmpInst;
10380b57cec5SDimitry Andric     break;
10390b57cec5SDimitry Andric   }
10400b57cec5SDimitry Andric   case PPC::SRWI:
1041480093f4SDimitry Andric   case PPC::SRWI_rec: {
10420b57cec5SDimitry Andric     MCInst TmpInst;
10430b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1044480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::SRWI ? PPC::RLWINM : PPC::RLWINM_rec);
10450b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10460b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
10470b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(32 - N));
10480b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N));
10490b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(31));
10500b57cec5SDimitry Andric     Inst = TmpInst;
10510b57cec5SDimitry Andric     break;
10520b57cec5SDimitry Andric   }
10530b57cec5SDimitry Andric   case PPC::CLRRWI:
1054480093f4SDimitry Andric   case PPC::CLRRWI_rec: {
10550b57cec5SDimitry Andric     MCInst TmpInst;
10560b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1057480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::CLRRWI ? PPC::RLWINM : PPC::RLWINM_rec);
10580b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10590b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
10600b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
10610b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
10620b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(31 - N));
10630b57cec5SDimitry Andric     Inst = TmpInst;
10640b57cec5SDimitry Andric     break;
10650b57cec5SDimitry Andric   }
10660b57cec5SDimitry Andric   case PPC::CLRLSLWI:
1067480093f4SDimitry Andric   case PPC::CLRLSLWI_rec: {
10680b57cec5SDimitry Andric     MCInst TmpInst;
10690b57cec5SDimitry Andric     int64_t B = Inst.getOperand(2).getImm();
10700b57cec5SDimitry Andric     int64_t N = Inst.getOperand(3).getImm();
1071480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::CLRLSLWI ? PPC::RLWINM : PPC::RLWINM_rec);
10720b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10730b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
10740b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N));
10750b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B - N));
10760b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(31 - N));
10770b57cec5SDimitry Andric     Inst = TmpInst;
10780b57cec5SDimitry Andric     break;
10790b57cec5SDimitry Andric   }
10800b57cec5SDimitry Andric   case PPC::EXTLDI:
1081480093f4SDimitry Andric   case PPC::EXTLDI_rec: {
10820b57cec5SDimitry Andric     MCInst TmpInst;
10830b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
10840b57cec5SDimitry Andric     int64_t B = Inst.getOperand(3).getImm();
1085480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::EXTLDI ? PPC::RLDICR : PPC::RLDICR_rec);
10860b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
10870b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
10880b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B));
10890b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N - 1));
10900b57cec5SDimitry Andric     Inst = TmpInst;
10910b57cec5SDimitry Andric     break;
10920b57cec5SDimitry Andric   }
10930b57cec5SDimitry Andric   case PPC::EXTRDI:
1094480093f4SDimitry Andric   case PPC::EXTRDI_rec: {
10950b57cec5SDimitry Andric     MCInst TmpInst;
10960b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
10970b57cec5SDimitry Andric     int64_t B = Inst.getOperand(3).getImm();
1098480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::EXTRDI ? PPC::RLDICL : PPC::RLDICL_rec);
10990b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11000b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
11010b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B + N));
11020b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(64 - N));
11030b57cec5SDimitry Andric     Inst = TmpInst;
11040b57cec5SDimitry Andric     break;
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric   case PPC::INSRDI:
1107480093f4SDimitry Andric   case PPC::INSRDI_rec: {
11080b57cec5SDimitry Andric     MCInst TmpInst;
11090b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
11100b57cec5SDimitry Andric     int64_t B = Inst.getOperand(3).getImm();
1111480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::INSRDI ? PPC::RLDIMI : PPC::RLDIMI_rec);
11120b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11130b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11140b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
11150b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(64 - (B + N)));
11160b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B));
11170b57cec5SDimitry Andric     Inst = TmpInst;
11180b57cec5SDimitry Andric     break;
11190b57cec5SDimitry Andric   }
11200b57cec5SDimitry Andric   case PPC::ROTRDI:
1121480093f4SDimitry Andric   case PPC::ROTRDI_rec: {
11220b57cec5SDimitry Andric     MCInst TmpInst;
11230b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1124480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::ROTRDI ? PPC::RLDICL : PPC::RLDICL_rec);
11250b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11260b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
11270b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(64 - N));
11280b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
11290b57cec5SDimitry Andric     Inst = TmpInst;
11300b57cec5SDimitry Andric     break;
11310b57cec5SDimitry Andric   }
11320b57cec5SDimitry Andric   case PPC::SLDI:
1133480093f4SDimitry Andric   case PPC::SLDI_rec: {
11340b57cec5SDimitry Andric     MCInst TmpInst;
11350b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1136480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::SLDI ? PPC::RLDICR : PPC::RLDICR_rec);
11370b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11380b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
11390b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N));
11400b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(63 - N));
11410b57cec5SDimitry Andric     Inst = TmpInst;
11420b57cec5SDimitry Andric     break;
11430b57cec5SDimitry Andric   }
11440b57cec5SDimitry Andric   case PPC::SUBPCIS: {
11450b57cec5SDimitry Andric     MCInst TmpInst;
11460b57cec5SDimitry Andric     int64_t N = Inst.getOperand(1).getImm();
11470b57cec5SDimitry Andric     TmpInst.setOpcode(PPC::ADDPCIS);
11480b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11490b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(-N));
11500b57cec5SDimitry Andric     Inst = TmpInst;
11510b57cec5SDimitry Andric     break;
11520b57cec5SDimitry Andric   }
11530b57cec5SDimitry Andric   case PPC::SRDI:
1154480093f4SDimitry Andric   case PPC::SRDI_rec: {
11550b57cec5SDimitry Andric     MCInst TmpInst;
11560b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1157480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::SRDI ? PPC::RLDICL : PPC::RLDICL_rec);
11580b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11590b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
11600b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(64 - N));
11610b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N));
11620b57cec5SDimitry Andric     Inst = TmpInst;
11630b57cec5SDimitry Andric     break;
11640b57cec5SDimitry Andric   }
11650b57cec5SDimitry Andric   case PPC::CLRRDI:
1166480093f4SDimitry Andric   case PPC::CLRRDI_rec: {
11670b57cec5SDimitry Andric     MCInst TmpInst;
11680b57cec5SDimitry Andric     int64_t N = Inst.getOperand(2).getImm();
1169480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::CLRRDI ? PPC::RLDICR : PPC::RLDICR_rec);
11700b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11710b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
11720b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(0));
11730b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(63 - N));
11740b57cec5SDimitry Andric     Inst = TmpInst;
11750b57cec5SDimitry Andric     break;
11760b57cec5SDimitry Andric   }
11770b57cec5SDimitry Andric   case PPC::CLRLSLDI:
1178480093f4SDimitry Andric   case PPC::CLRLSLDI_rec: {
11790b57cec5SDimitry Andric     MCInst TmpInst;
11800b57cec5SDimitry Andric     int64_t B = Inst.getOperand(2).getImm();
11810b57cec5SDimitry Andric     int64_t N = Inst.getOperand(3).getImm();
1182480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::CLRLSLDI ? PPC::RLDIC : PPC::RLDIC_rec);
11830b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
11840b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
11850b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(N));
11860b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(B - N));
11870b57cec5SDimitry Andric     Inst = TmpInst;
11880b57cec5SDimitry Andric     break;
11890b57cec5SDimitry Andric   }
11900b57cec5SDimitry Andric   case PPC::RLWINMbm:
1191480093f4SDimitry Andric   case PPC::RLWINMbm_rec: {
11920b57cec5SDimitry Andric     unsigned MB, ME;
11930b57cec5SDimitry Andric     int64_t BM = Inst.getOperand(3).getImm();
11940b57cec5SDimitry Andric     if (!isRunOfOnes(BM, MB, ME))
11950b57cec5SDimitry Andric       break;
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric     MCInst TmpInst;
1198480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::RLWINMbm ? PPC::RLWINM : PPC::RLWINM_rec);
11990b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
12000b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
12010b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(2));
12020b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(MB));
12030b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ME));
12040b57cec5SDimitry Andric     Inst = TmpInst;
12050b57cec5SDimitry Andric     break;
12060b57cec5SDimitry Andric   }
12070b57cec5SDimitry Andric   case PPC::RLWIMIbm:
1208480093f4SDimitry Andric   case PPC::RLWIMIbm_rec: {
12090b57cec5SDimitry Andric     unsigned MB, ME;
12100b57cec5SDimitry Andric     int64_t BM = Inst.getOperand(3).getImm();
12110b57cec5SDimitry Andric     if (!isRunOfOnes(BM, MB, ME))
12120b57cec5SDimitry Andric       break;
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric     MCInst TmpInst;
1215480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::RLWIMIbm ? PPC::RLWIMI : PPC::RLWIMI_rec);
12160b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
12170b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0)); // The tied operand.
12180b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
12190b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(2));
12200b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(MB));
12210b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ME));
12220b57cec5SDimitry Andric     Inst = TmpInst;
12230b57cec5SDimitry Andric     break;
12240b57cec5SDimitry Andric   }
12250b57cec5SDimitry Andric   case PPC::RLWNMbm:
1226480093f4SDimitry Andric   case PPC::RLWNMbm_rec: {
12270b57cec5SDimitry Andric     unsigned MB, ME;
12280b57cec5SDimitry Andric     int64_t BM = Inst.getOperand(3).getImm();
12290b57cec5SDimitry Andric     if (!isRunOfOnes(BM, MB, ME))
12300b57cec5SDimitry Andric       break;
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric     MCInst TmpInst;
1233480093f4SDimitry Andric     TmpInst.setOpcode(Opcode == PPC::RLWNMbm ? PPC::RLWNM : PPC::RLWNM_rec);
12340b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(0));
12350b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(1));
12360b57cec5SDimitry Andric     TmpInst.addOperand(Inst.getOperand(2));
12370b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(MB));
12380b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ME));
12390b57cec5SDimitry Andric     Inst = TmpInst;
12400b57cec5SDimitry Andric     break;
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric   case PPC::MFTB: {
124306c3fb27SDimitry Andric     if (getSTI().hasFeature(PPC::FeatureMFTB)) {
12440b57cec5SDimitry Andric       assert(Inst.getNumOperands() == 2 && "Expecting two operands");
12450b57cec5SDimitry Andric       Inst.setOpcode(PPC::MFSPR);
12460b57cec5SDimitry Andric     }
12470b57cec5SDimitry Andric     break;
12480b57cec5SDimitry Andric   }
12490b57cec5SDimitry Andric   }
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
12530b57cec5SDimitry Andric                                          unsigned VariantID = 0);
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
12560b57cec5SDimitry Andric                                            OperandVector &Operands,
12570b57cec5SDimitry Andric                                            MCStreamer &Out, uint64_t &ErrorInfo,
12580b57cec5SDimitry Andric                                            bool MatchingInlineAsm) {
12590b57cec5SDimitry Andric   MCInst Inst;
12600b57cec5SDimitry Andric 
12610b57cec5SDimitry Andric   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
12620b57cec5SDimitry Andric   case Match_Success:
12630b57cec5SDimitry Andric     // Post-process instructions (typically extended mnemonics)
12640b57cec5SDimitry Andric     ProcessInstruction(Inst, Operands);
12650b57cec5SDimitry Andric     Inst.setLoc(IDLoc);
12665ffd83dbSDimitry Andric     Out.emitInstruction(Inst, getSTI());
12670b57cec5SDimitry Andric     return false;
12680b57cec5SDimitry Andric   case Match_MissingFeature:
12690b57cec5SDimitry Andric     return Error(IDLoc, "instruction use requires an option to be enabled");
12700b57cec5SDimitry Andric   case Match_MnemonicFail: {
12710b57cec5SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
12720b57cec5SDimitry Andric     std::string Suggestion = PPCMnemonicSpellCheck(
12730b57cec5SDimitry Andric         ((PPCOperand &)*Operands[0]).getToken(), FBS);
12740b57cec5SDimitry Andric     return Error(IDLoc, "invalid instruction" + Suggestion,
12750b57cec5SDimitry Andric                  ((PPCOperand &)*Operands[0]).getLocRange());
12760b57cec5SDimitry Andric   }
12770b57cec5SDimitry Andric   case Match_InvalidOperand: {
12780b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
12790b57cec5SDimitry Andric     if (ErrorInfo != ~0ULL) {
12800b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
12810b57cec5SDimitry Andric         return Error(IDLoc, "too few operands for instruction");
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric       ErrorLoc = ((PPCOperand &)*Operands[ErrorInfo]).getStartLoc();
12840b57cec5SDimitry Andric       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
12850b57cec5SDimitry Andric     }
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
12880b57cec5SDimitry Andric   }
12890b57cec5SDimitry Andric   }
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   llvm_unreachable("Implement any new match types added!");
12920b57cec5SDimitry Andric }
12930b57cec5SDimitry Andric 
1294bdd1243dSDimitry Andric bool PPCAsmParser::MatchRegisterName(MCRegister &RegNo, int64_t &IntVal) {
1295e8d8bef9SDimitry Andric   if (getParser().getTok().is(AsmToken::Percent))
1296e8d8bef9SDimitry Andric     getParser().Lex(); // Eat the '%'.
1297e8d8bef9SDimitry Andric 
1298e8d8bef9SDimitry Andric   if (!getParser().getTok().is(AsmToken::Identifier))
1299e8d8bef9SDimitry Andric     return true;
1300e8d8bef9SDimitry Andric 
13010b57cec5SDimitry Andric   StringRef Name = getParser().getTok().getString();
1302fe6060f1SDimitry Andric   if (Name.equals_insensitive("lr")) {
13030b57cec5SDimitry Andric     RegNo = isPPC64() ? PPC::LR8 : PPC::LR;
13040b57cec5SDimitry Andric     IntVal = 8;
1305fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("ctr")) {
13060b57cec5SDimitry Andric     RegNo = isPPC64() ? PPC::CTR8 : PPC::CTR;
13070b57cec5SDimitry Andric     IntVal = 9;
1308fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("vrsave")) {
13090b57cec5SDimitry Andric     RegNo = PPC::VRSAVE;
13100b57cec5SDimitry Andric     IntVal = 256;
131106c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("r") &&
13120b57cec5SDimitry Andric              !Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) {
13130b57cec5SDimitry Andric     RegNo = isPPC64() ? XRegs[IntVal] : RRegs[IntVal];
131406c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("f") &&
13150b57cec5SDimitry Andric              !Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) {
13160b57cec5SDimitry Andric     RegNo = FRegs[IntVal];
131706c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("vs") &&
13180b57cec5SDimitry Andric              !Name.substr(2).getAsInteger(10, IntVal) && IntVal < 64) {
13190b57cec5SDimitry Andric     RegNo = VSRegs[IntVal];
132006c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("v") &&
13210b57cec5SDimitry Andric              !Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) {
13220b57cec5SDimitry Andric     RegNo = VRegs[IntVal];
132306c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("cr") &&
13240b57cec5SDimitry Andric              !Name.substr(2).getAsInteger(10, IntVal) && IntVal < 8) {
13250b57cec5SDimitry Andric     RegNo = CRRegs[IntVal];
132606c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("acc") &&
1327bdd1243dSDimitry Andric              !Name.substr(3).getAsInteger(10, IntVal) && IntVal < 8) {
1328bdd1243dSDimitry Andric     RegNo = ACCRegs[IntVal];
132906c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("wacc_hi") &&
1330bdd1243dSDimitry Andric              !Name.substr(7).getAsInteger(10, IntVal) && IntVal < 8) {
1331bdd1243dSDimitry Andric     RegNo = ACCRegs[IntVal];
133206c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("wacc") &&
1333bdd1243dSDimitry Andric              !Name.substr(4).getAsInteger(10, IntVal) && IntVal < 8) {
1334bdd1243dSDimitry Andric     RegNo = WACCRegs[IntVal];
133506c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("dmrrowp") &&
1336bdd1243dSDimitry Andric              !Name.substr(7).getAsInteger(10, IntVal) && IntVal < 32) {
1337bdd1243dSDimitry Andric     RegNo = DMRROWpRegs[IntVal];
133806c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("dmrrow") &&
1339bdd1243dSDimitry Andric              !Name.substr(6).getAsInteger(10, IntVal) && IntVal < 64) {
1340bdd1243dSDimitry Andric     RegNo = DMRROWRegs[IntVal];
134106c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("dmrp") &&
1342bdd1243dSDimitry Andric              !Name.substr(4).getAsInteger(10, IntVal) && IntVal < 4) {
1343bdd1243dSDimitry Andric     RegNo = DMRROWpRegs[IntVal];
134406c3fb27SDimitry Andric   } else if (Name.starts_with_insensitive("dmr") &&
1345bdd1243dSDimitry Andric              !Name.substr(3).getAsInteger(10, IntVal) && IntVal < 8) {
1346bdd1243dSDimitry Andric     RegNo = DMRRegs[IntVal];
13470b57cec5SDimitry Andric   } else
13480b57cec5SDimitry Andric     return true;
13490b57cec5SDimitry Andric   getParser().Lex();
13500b57cec5SDimitry Andric   return false;
13510b57cec5SDimitry Andric }
13520b57cec5SDimitry Andric 
13535f757f3fSDimitry Andric bool PPCAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1354bdd1243dSDimitry Andric                                  SMLoc &EndLoc) {
13555f757f3fSDimitry Andric   if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
13565ffd83dbSDimitry Andric     return TokError("invalid register name");
13575ffd83dbSDimitry Andric   return false;
13585ffd83dbSDimitry Andric }
13595ffd83dbSDimitry Andric 
13605f757f3fSDimitry Andric ParseStatus PPCAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
13615ffd83dbSDimitry Andric                                            SMLoc &EndLoc) {
13620b57cec5SDimitry Andric   const AsmToken &Tok = getParser().getTok();
13630b57cec5SDimitry Andric   StartLoc = Tok.getLoc();
13640b57cec5SDimitry Andric   EndLoc = Tok.getEndLoc();
13655f757f3fSDimitry Andric   Reg = PPC::NoRegister;
13660b57cec5SDimitry Andric   int64_t IntVal;
13675f757f3fSDimitry Andric   if (MatchRegisterName(Reg, IntVal))
13685f757f3fSDimitry Andric     return ParseStatus::NoMatch;
13695f757f3fSDimitry Andric   return ParseStatus::Success;
13700b57cec5SDimitry Andric }
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric /// Extract \code @l/@ha \endcode modifier from expression.  Recursively scan
13730b57cec5SDimitry Andric /// the expression and check for VK_PPC_LO/HI/HA
13740b57cec5SDimitry Andric /// symbol variants.  If all symbols with modifier use the same
13750b57cec5SDimitry Andric /// variant, return the corresponding PPCMCExpr::VariantKind,
13760b57cec5SDimitry Andric /// and a modified expression using the default symbol variant.
13770b57cec5SDimitry Andric /// Otherwise, return NULL.
13780b57cec5SDimitry Andric const MCExpr *PPCAsmParser::
13790b57cec5SDimitry Andric ExtractModifierFromExpr(const MCExpr *E,
13800b57cec5SDimitry Andric                         PPCMCExpr::VariantKind &Variant) {
13810b57cec5SDimitry Andric   MCContext &Context = getParser().getContext();
13820b57cec5SDimitry Andric   Variant = PPCMCExpr::VK_PPC_None;
13830b57cec5SDimitry Andric 
13840b57cec5SDimitry Andric   switch (E->getKind()) {
13850b57cec5SDimitry Andric   case MCExpr::Target:
13860b57cec5SDimitry Andric   case MCExpr::Constant:
13870b57cec5SDimitry Andric     return nullptr;
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   case MCExpr::SymbolRef: {
13900b57cec5SDimitry Andric     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric     switch (SRE->getKind()) {
13930b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_LO:
13940b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_LO;
13950b57cec5SDimitry Andric       break;
13960b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HI:
13970b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HI;
13980b57cec5SDimitry Andric       break;
13990b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HA:
14000b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HA;
14010b57cec5SDimitry Andric       break;
14020b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HIGH:
14030b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HIGH;
14040b57cec5SDimitry Andric       break;
14050b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HIGHA:
14060b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HIGHA;
14070b57cec5SDimitry Andric       break;
14080b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HIGHER:
14090b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HIGHER;
14100b57cec5SDimitry Andric       break;
14110b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HIGHERA:
14120b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HIGHERA;
14130b57cec5SDimitry Andric       break;
14140b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HIGHEST:
14150b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HIGHEST;
14160b57cec5SDimitry Andric       break;
14170b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_PPC_HIGHESTA:
14180b57cec5SDimitry Andric       Variant = PPCMCExpr::VK_PPC_HIGHESTA;
14190b57cec5SDimitry Andric       break;
14200b57cec5SDimitry Andric     default:
14210b57cec5SDimitry Andric       return nullptr;
14220b57cec5SDimitry Andric     }
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric     return MCSymbolRefExpr::create(&SRE->getSymbol(), Context);
14250b57cec5SDimitry Andric   }
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric   case MCExpr::Unary: {
14280b57cec5SDimitry Andric     const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
14290b57cec5SDimitry Andric     const MCExpr *Sub = ExtractModifierFromExpr(UE->getSubExpr(), Variant);
14300b57cec5SDimitry Andric     if (!Sub)
14310b57cec5SDimitry Andric       return nullptr;
14320b57cec5SDimitry Andric     return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
14330b57cec5SDimitry Andric   }
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric   case MCExpr::Binary: {
14360b57cec5SDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
14370b57cec5SDimitry Andric     PPCMCExpr::VariantKind LHSVariant, RHSVariant;
14380b57cec5SDimitry Andric     const MCExpr *LHS = ExtractModifierFromExpr(BE->getLHS(), LHSVariant);
14390b57cec5SDimitry Andric     const MCExpr *RHS = ExtractModifierFromExpr(BE->getRHS(), RHSVariant);
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric     if (!LHS && !RHS)
14420b57cec5SDimitry Andric       return nullptr;
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric     if (!LHS) LHS = BE->getLHS();
14450b57cec5SDimitry Andric     if (!RHS) RHS = BE->getRHS();
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric     if (LHSVariant == PPCMCExpr::VK_PPC_None)
14480b57cec5SDimitry Andric       Variant = RHSVariant;
14490b57cec5SDimitry Andric     else if (RHSVariant == PPCMCExpr::VK_PPC_None)
14500b57cec5SDimitry Andric       Variant = LHSVariant;
14510b57cec5SDimitry Andric     else if (LHSVariant == RHSVariant)
14520b57cec5SDimitry Andric       Variant = LHSVariant;
14530b57cec5SDimitry Andric     else
14540b57cec5SDimitry Andric       return nullptr;
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric     return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
14570b57cec5SDimitry Andric   }
14580b57cec5SDimitry Andric   }
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric   llvm_unreachable("Invalid expression kind!");
14610b57cec5SDimitry Andric }
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric /// Find all VK_TLSGD/VK_TLSLD symbol references in expression and replace
14640b57cec5SDimitry Andric /// them by VK_PPC_TLSGD/VK_PPC_TLSLD.  This is necessary to avoid having
14650b57cec5SDimitry Andric /// _GLOBAL_OFFSET_TABLE_ created via ELFObjectWriter::RelocNeedsGOT.
14660b57cec5SDimitry Andric /// FIXME: This is a hack.
14670b57cec5SDimitry Andric const MCExpr *PPCAsmParser::
14680b57cec5SDimitry Andric FixupVariantKind(const MCExpr *E) {
14690b57cec5SDimitry Andric   MCContext &Context = getParser().getContext();
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric   switch (E->getKind()) {
14720b57cec5SDimitry Andric   case MCExpr::Target:
14730b57cec5SDimitry Andric   case MCExpr::Constant:
14740b57cec5SDimitry Andric     return E;
14750b57cec5SDimitry Andric 
14760b57cec5SDimitry Andric   case MCExpr::SymbolRef: {
14770b57cec5SDimitry Andric     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
14780b57cec5SDimitry Andric     MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric     switch (SRE->getKind()) {
14810b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_TLSGD:
14820b57cec5SDimitry Andric       Variant = MCSymbolRefExpr::VK_PPC_TLSGD;
14830b57cec5SDimitry Andric       break;
14840b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_TLSLD:
14850b57cec5SDimitry Andric       Variant = MCSymbolRefExpr::VK_PPC_TLSLD;
14860b57cec5SDimitry Andric       break;
14870b57cec5SDimitry Andric     default:
14880b57cec5SDimitry Andric       return E;
14890b57cec5SDimitry Andric     }
14900b57cec5SDimitry Andric     return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, Context);
14910b57cec5SDimitry Andric   }
14920b57cec5SDimitry Andric 
14930b57cec5SDimitry Andric   case MCExpr::Unary: {
14940b57cec5SDimitry Andric     const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
14950b57cec5SDimitry Andric     const MCExpr *Sub = FixupVariantKind(UE->getSubExpr());
14960b57cec5SDimitry Andric     if (Sub == UE->getSubExpr())
14970b57cec5SDimitry Andric       return E;
14980b57cec5SDimitry Andric     return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
14990b57cec5SDimitry Andric   }
15000b57cec5SDimitry Andric 
15010b57cec5SDimitry Andric   case MCExpr::Binary: {
15020b57cec5SDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
15030b57cec5SDimitry Andric     const MCExpr *LHS = FixupVariantKind(BE->getLHS());
15040b57cec5SDimitry Andric     const MCExpr *RHS = FixupVariantKind(BE->getRHS());
15050b57cec5SDimitry Andric     if (LHS == BE->getLHS() && RHS == BE->getRHS())
15060b57cec5SDimitry Andric       return E;
15070b57cec5SDimitry Andric     return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
15080b57cec5SDimitry Andric   }
15090b57cec5SDimitry Andric   }
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric   llvm_unreachable("Invalid expression kind!");
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric /// ParseExpression.  This differs from the default "parseExpression" in that
15150b57cec5SDimitry Andric /// it handles modifiers.
15160b57cec5SDimitry Andric bool PPCAsmParser::
15170b57cec5SDimitry Andric ParseExpression(const MCExpr *&EVal) {
15180b57cec5SDimitry Andric   // (ELF Platforms)
15190b57cec5SDimitry Andric   // Handle \code @l/@ha \endcode
15200b57cec5SDimitry Andric   if (getParser().parseExpression(EVal))
15210b57cec5SDimitry Andric     return true;
15220b57cec5SDimitry Andric 
15230b57cec5SDimitry Andric   EVal = FixupVariantKind(EVal);
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric   PPCMCExpr::VariantKind Variant;
15260b57cec5SDimitry Andric   const MCExpr *E = ExtractModifierFromExpr(EVal, Variant);
15270b57cec5SDimitry Andric   if (E)
15285ffd83dbSDimitry Andric     EVal = PPCMCExpr::create(Variant, E, getParser().getContext());
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric   return false;
15310b57cec5SDimitry Andric }
15320b57cec5SDimitry Andric 
15330b57cec5SDimitry Andric /// ParseOperand
15340b57cec5SDimitry Andric /// This handles registers in the form 'NN', '%rNN' for ELF platforms and
15350b57cec5SDimitry Andric /// rNN for MachO.
15360b57cec5SDimitry Andric bool PPCAsmParser::ParseOperand(OperandVector &Operands) {
15370b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
15380b57cec5SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
15390b57cec5SDimitry Andric   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
15400b57cec5SDimitry Andric   const MCExpr *EVal;
15410b57cec5SDimitry Andric 
15420b57cec5SDimitry Andric   // Attempt to parse the next token as an immediate
15430b57cec5SDimitry Andric   switch (getLexer().getKind()) {
15440b57cec5SDimitry Andric   // Special handling for register names.  These are interpreted
15450b57cec5SDimitry Andric   // as immediates corresponding to the register number.
1546e8d8bef9SDimitry Andric   case AsmToken::Percent: {
1547bdd1243dSDimitry Andric     MCRegister RegNo;
15480b57cec5SDimitry Andric     int64_t IntVal;
15490b57cec5SDimitry Andric     if (MatchRegisterName(RegNo, IntVal))
15500b57cec5SDimitry Andric       return Error(S, "invalid register name");
15510b57cec5SDimitry Andric 
15520b57cec5SDimitry Andric     Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
15530b57cec5SDimitry Andric     return false;
1554e8d8bef9SDimitry Andric   }
15550b57cec5SDimitry Andric   case AsmToken::Identifier:
15560b57cec5SDimitry Andric   case AsmToken::LParen:
15570b57cec5SDimitry Andric   case AsmToken::Plus:
15580b57cec5SDimitry Andric   case AsmToken::Minus:
15590b57cec5SDimitry Andric   case AsmToken::Integer:
15600b57cec5SDimitry Andric   case AsmToken::Dot:
15610b57cec5SDimitry Andric   case AsmToken::Dollar:
15620b57cec5SDimitry Andric   case AsmToken::Exclaim:
15630b57cec5SDimitry Andric   case AsmToken::Tilde:
15640b57cec5SDimitry Andric     if (!ParseExpression(EVal))
15650b57cec5SDimitry Andric       break;
15660b57cec5SDimitry Andric     // Fall-through
1567bdd1243dSDimitry Andric     [[fallthrough]];
15680b57cec5SDimitry Andric   default:
15690b57cec5SDimitry Andric     return Error(S, "unknown operand");
15700b57cec5SDimitry Andric   }
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric   // Push the parsed operand into the list of operands
15730b57cec5SDimitry Andric   Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64()));
15740b57cec5SDimitry Andric 
15750b57cec5SDimitry Andric   // Check whether this is a TLS call expression
15768a4dda33SDimitry Andric   const char TlsGetAddr[] = "__tls_get_addr";
15778a4dda33SDimitry Andric   bool TlsCall = false;
15788a4dda33SDimitry Andric   const MCExpr *TlsCallAddend = nullptr;
15798a4dda33SDimitry Andric   if (auto *Ref = dyn_cast<MCSymbolRefExpr>(EVal)) {
15808a4dda33SDimitry Andric     TlsCall = Ref->getSymbol().getName() == TlsGetAddr;
15818a4dda33SDimitry Andric   } else if (auto *Bin = dyn_cast<MCBinaryExpr>(EVal);
15828a4dda33SDimitry Andric              Bin && Bin->getOpcode() == MCBinaryExpr::Add) {
15838a4dda33SDimitry Andric     if (auto *Ref = dyn_cast<MCSymbolRefExpr>(Bin->getLHS())) {
15848a4dda33SDimitry Andric       TlsCall = Ref->getSymbol().getName() == TlsGetAddr;
15858a4dda33SDimitry Andric       TlsCallAddend = Bin->getRHS();
15868a4dda33SDimitry Andric     }
15878a4dda33SDimitry Andric   }
15880b57cec5SDimitry Andric 
15898a4dda33SDimitry Andric   if (TlsCall && parseOptionalToken(AsmToken::LParen)) {
15900b57cec5SDimitry Andric     const MCExpr *TLSSym;
15918a4dda33SDimitry Andric     const SMLoc S2 = Parser.getTok().getLoc();
15920b57cec5SDimitry Andric     if (ParseExpression(TLSSym))
15938a4dda33SDimitry Andric       return Error(S2, "invalid TLS call expression");
15948a4dda33SDimitry Andric     E = Parser.getTok().getLoc();
159506c3fb27SDimitry Andric     if (parseToken(AsmToken::RParen, "expected ')'"))
159606c3fb27SDimitry Andric       return true;
15978a4dda33SDimitry Andric     // PPC32 allows bl __tls_get_addr[+a](x@tlsgd)@plt+b. Parse "@plt[+b]".
15988a4dda33SDimitry Andric     if (!isPPC64() && parseOptionalToken(AsmToken::At)) {
15998a4dda33SDimitry Andric       AsmToken Tok = getTok();
16008a4dda33SDimitry Andric       if (!(parseOptionalToken(AsmToken::Identifier) &&
16018a4dda33SDimitry Andric             Tok.getString().compare_insensitive("plt") == 0))
16028a4dda33SDimitry Andric         return Error(Tok.getLoc(), "expected 'plt'");
16038a4dda33SDimitry Andric       EVal = MCSymbolRefExpr::create(TlsGetAddr, MCSymbolRefExpr::VK_PLT,
16048a4dda33SDimitry Andric                                      getContext());
16058a4dda33SDimitry Andric       if (parseOptionalToken(AsmToken::Plus)) {
16068a4dda33SDimitry Andric         const MCExpr *Addend = nullptr;
16078a4dda33SDimitry Andric         SMLoc EndLoc;
16088a4dda33SDimitry Andric         if (parsePrimaryExpr(Addend, EndLoc))
16098a4dda33SDimitry Andric           return true;
16108a4dda33SDimitry Andric         if (TlsCallAddend) // __tls_get_addr+a(x@tlsgd)@plt+b
16118a4dda33SDimitry Andric           TlsCallAddend =
16128a4dda33SDimitry Andric               MCBinaryExpr::createAdd(TlsCallAddend, Addend, getContext());
16138a4dda33SDimitry Andric         else // __tls_get_addr(x@tlsgd)@plt+b
16148a4dda33SDimitry Andric           TlsCallAddend = Addend;
16158a4dda33SDimitry Andric       }
16168a4dda33SDimitry Andric       if (TlsCallAddend)
16178a4dda33SDimitry Andric         EVal = MCBinaryExpr::createAdd(EVal, TlsCallAddend, getContext());
16188a4dda33SDimitry Andric       // Add a __tls_get_addr operand with addend a, b, or a+b.
16198a4dda33SDimitry Andric       Operands.back() = PPCOperand::CreateFromMCExpr(
16208a4dda33SDimitry Andric           EVal, S, Parser.getTok().getLoc(), false);
16218a4dda33SDimitry Andric     }
16220b57cec5SDimitry Andric 
16230b57cec5SDimitry Andric     Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64()));
16240b57cec5SDimitry Andric   }
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric   // Otherwise, check for D-form memory operands
16278a4dda33SDimitry Andric   if (!TlsCall && parseOptionalToken(AsmToken::LParen)) {
16280b57cec5SDimitry Andric     S = Parser.getTok().getLoc();
16290b57cec5SDimitry Andric 
16300b57cec5SDimitry Andric     int64_t IntVal;
16310b57cec5SDimitry Andric     switch (getLexer().getKind()) {
1632e8d8bef9SDimitry Andric     case AsmToken::Percent: {
1633bdd1243dSDimitry Andric       MCRegister RegNo;
16340b57cec5SDimitry Andric       if (MatchRegisterName(RegNo, IntVal))
16350b57cec5SDimitry Andric         return Error(S, "invalid register name");
16360b57cec5SDimitry Andric       break;
1637e8d8bef9SDimitry Andric     }
16380b57cec5SDimitry Andric     case AsmToken::Integer:
1639e8d8bef9SDimitry Andric       if (getParser().parseAbsoluteExpression(IntVal) || IntVal < 0 ||
16400b57cec5SDimitry Andric           IntVal > 31)
16410b57cec5SDimitry Andric         return Error(S, "invalid register number");
16420b57cec5SDimitry Andric       break;
16430b57cec5SDimitry Andric     case AsmToken::Identifier:
16440b57cec5SDimitry Andric     default:
16450b57cec5SDimitry Andric       return Error(S, "invalid memory operand");
16460b57cec5SDimitry Andric     }
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric     E = Parser.getTok().getLoc();
16490b57cec5SDimitry Andric     if (parseToken(AsmToken::RParen, "missing ')'"))
16500b57cec5SDimitry Andric       return true;
16510b57cec5SDimitry Andric     Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
16520b57cec5SDimitry Andric   }
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric   return false;
16550b57cec5SDimitry Andric }
16560b57cec5SDimitry Andric 
16570b57cec5SDimitry Andric /// Parse an instruction mnemonic followed by its operands.
16580b57cec5SDimitry Andric bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
16590b57cec5SDimitry Andric                                     SMLoc NameLoc, OperandVector &Operands) {
16600b57cec5SDimitry Andric   // The first operand is the token for the instruction name.
16610b57cec5SDimitry Andric   // If the next character is a '+' or '-', we need to add it to the
16620b57cec5SDimitry Andric   // instruction name, to match what TableGen is doing.
16630b57cec5SDimitry Andric   std::string NewOpcode;
16640b57cec5SDimitry Andric   if (parseOptionalToken(AsmToken::Plus)) {
16655ffd83dbSDimitry Andric     NewOpcode = std::string(Name);
16660b57cec5SDimitry Andric     NewOpcode += '+';
16670b57cec5SDimitry Andric     Name = NewOpcode;
16680b57cec5SDimitry Andric   }
16690b57cec5SDimitry Andric   if (parseOptionalToken(AsmToken::Minus)) {
16705ffd83dbSDimitry Andric     NewOpcode = std::string(Name);
16710b57cec5SDimitry Andric     NewOpcode += '-';
16720b57cec5SDimitry Andric     Name = NewOpcode;
16730b57cec5SDimitry Andric   }
16740b57cec5SDimitry Andric   // If the instruction ends in a '.', we need to create a separate
16750b57cec5SDimitry Andric   // token for it, to match what TableGen is doing.
16760b57cec5SDimitry Andric   size_t Dot = Name.find('.');
16770b57cec5SDimitry Andric   StringRef Mnemonic = Name.slice(0, Dot);
16780b57cec5SDimitry Andric   if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
16790b57cec5SDimitry Andric     Operands.push_back(
16800b57cec5SDimitry Andric         PPCOperand::CreateTokenWithStringCopy(Mnemonic, NameLoc, isPPC64()));
16810b57cec5SDimitry Andric   else
16820b57cec5SDimitry Andric     Operands.push_back(PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64()));
16830b57cec5SDimitry Andric   if (Dot != StringRef::npos) {
16840b57cec5SDimitry Andric     SMLoc DotLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Dot);
16850b57cec5SDimitry Andric     StringRef DotStr = Name.slice(Dot, StringRef::npos);
16860b57cec5SDimitry Andric     if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
16870b57cec5SDimitry Andric       Operands.push_back(
16880b57cec5SDimitry Andric           PPCOperand::CreateTokenWithStringCopy(DotStr, DotLoc, isPPC64()));
16890b57cec5SDimitry Andric     else
16900b57cec5SDimitry Andric       Operands.push_back(PPCOperand::CreateToken(DotStr, DotLoc, isPPC64()));
16910b57cec5SDimitry Andric   }
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric   // If there are no more operands then finish
16940b57cec5SDimitry Andric   if (parseOptionalToken(AsmToken::EndOfStatement))
16950b57cec5SDimitry Andric     return false;
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric   // Parse the first operand
16980b57cec5SDimitry Andric   if (ParseOperand(Operands))
16990b57cec5SDimitry Andric     return true;
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric   while (!parseOptionalToken(AsmToken::EndOfStatement)) {
17020b57cec5SDimitry Andric     if (parseToken(AsmToken::Comma) || ParseOperand(Operands))
17030b57cec5SDimitry Andric       return true;
17040b57cec5SDimitry Andric   }
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   // We'll now deal with an unfortunate special case: the syntax for the dcbt
17070b57cec5SDimitry Andric   // and dcbtst instructions differs for server vs. embedded cores.
17080b57cec5SDimitry Andric   //  The syntax for dcbt is:
17090b57cec5SDimitry Andric   //    dcbt ra, rb, th [server]
17100b57cec5SDimitry Andric   //    dcbt th, ra, rb [embedded]
17110b57cec5SDimitry Andric   //  where th can be omitted when it is 0. dcbtst is the same. We take the
17120b57cec5SDimitry Andric   //  server form to be the default, so swap the operands if we're parsing for
17130b57cec5SDimitry Andric   //  an embedded core (they'll be swapped again upon printing).
171406c3fb27SDimitry Andric   if (getSTI().hasFeature(PPC::FeatureBookE) &&
17150b57cec5SDimitry Andric       Operands.size() == 4 &&
17160b57cec5SDimitry Andric       (Name == "dcbt" || Name == "dcbtst")) {
17170b57cec5SDimitry Andric     std::swap(Operands[1], Operands[3]);
17180b57cec5SDimitry Andric     std::swap(Operands[2], Operands[1]);
17190b57cec5SDimitry Andric   }
17200b57cec5SDimitry Andric 
17210eae32dcSDimitry Andric   // Handle base mnemonic for atomic loads where the EH bit is zero.
17220eae32dcSDimitry Andric   if (Name == "lqarx" || Name == "ldarx" || Name == "lwarx" ||
17230eae32dcSDimitry Andric       Name == "lharx" || Name == "lbarx") {
17240eae32dcSDimitry Andric     if (Operands.size() != 5)
17250eae32dcSDimitry Andric       return false;
17260eae32dcSDimitry Andric     PPCOperand &EHOp = (PPCOperand &)*Operands[4];
17270eae32dcSDimitry Andric     if (EHOp.isU1Imm() && EHOp.getImm() == 0)
17280eae32dcSDimitry Andric       Operands.pop_back();
17290eae32dcSDimitry Andric   }
17300eae32dcSDimitry Andric 
17310b57cec5SDimitry Andric   return false;
17320b57cec5SDimitry Andric }
17330b57cec5SDimitry Andric 
17340b57cec5SDimitry Andric /// ParseDirective parses the PPC specific directives
17350b57cec5SDimitry Andric bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) {
17360b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getIdentifier();
1737e8d8bef9SDimitry Andric   if (IDVal == ".word")
17380b57cec5SDimitry Andric     ParseDirectiveWord(2, DirectiveID);
17390b57cec5SDimitry Andric   else if (IDVal == ".llong")
17400b57cec5SDimitry Andric     ParseDirectiveWord(8, DirectiveID);
17410b57cec5SDimitry Andric   else if (IDVal == ".tc")
17420b57cec5SDimitry Andric     ParseDirectiveTC(isPPC64() ? 8 : 4, DirectiveID);
17430b57cec5SDimitry Andric   else if (IDVal == ".machine")
17440b57cec5SDimitry Andric     ParseDirectiveMachine(DirectiveID.getLoc());
17450b57cec5SDimitry Andric   else if (IDVal == ".abiversion")
17460b57cec5SDimitry Andric     ParseDirectiveAbiVersion(DirectiveID.getLoc());
17470b57cec5SDimitry Andric   else if (IDVal == ".localentry")
17480b57cec5SDimitry Andric     ParseDirectiveLocalEntry(DirectiveID.getLoc());
17495f757f3fSDimitry Andric   else if (IDVal.starts_with(".gnu_attribute"))
175004eeddc0SDimitry Andric     ParseGNUAttribute(DirectiveID.getLoc());
17510b57cec5SDimitry Andric   else
17520b57cec5SDimitry Andric     return true;
17530b57cec5SDimitry Andric   return false;
17540b57cec5SDimitry Andric }
17550b57cec5SDimitry Andric 
17560b57cec5SDimitry Andric /// ParseDirectiveWord
17570b57cec5SDimitry Andric ///  ::= .word [ expression (, expression)* ]
17580b57cec5SDimitry Andric bool PPCAsmParser::ParseDirectiveWord(unsigned Size, AsmToken ID) {
17590b57cec5SDimitry Andric   auto parseOp = [&]() -> bool {
17600b57cec5SDimitry Andric     const MCExpr *Value;
17610b57cec5SDimitry Andric     SMLoc ExprLoc = getParser().getTok().getLoc();
17620b57cec5SDimitry Andric     if (getParser().parseExpression(Value))
17630b57cec5SDimitry Andric       return true;
17640b57cec5SDimitry Andric     if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) {
17650b57cec5SDimitry Andric       assert(Size <= 8 && "Invalid size");
17660b57cec5SDimitry Andric       uint64_t IntValue = MCE->getValue();
17670b57cec5SDimitry Andric       if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
17680b57cec5SDimitry Andric         return Error(ExprLoc, "literal value out of range for '" +
17690b57cec5SDimitry Andric                                   ID.getIdentifier() + "' directive");
17705ffd83dbSDimitry Andric       getStreamer().emitIntValue(IntValue, Size);
17710b57cec5SDimitry Andric     } else
17725ffd83dbSDimitry Andric       getStreamer().emitValue(Value, Size, ExprLoc);
17730b57cec5SDimitry Andric     return false;
17740b57cec5SDimitry Andric   };
17750b57cec5SDimitry Andric 
17760b57cec5SDimitry Andric   if (parseMany(parseOp))
17770b57cec5SDimitry Andric     return addErrorSuffix(" in '" + ID.getIdentifier() + "' directive");
17780b57cec5SDimitry Andric   return false;
17790b57cec5SDimitry Andric }
17800b57cec5SDimitry Andric 
17810b57cec5SDimitry Andric /// ParseDirectiveTC
17820b57cec5SDimitry Andric ///  ::= .tc [ symbol (, expression)* ]
17830b57cec5SDimitry Andric bool PPCAsmParser::ParseDirectiveTC(unsigned Size, AsmToken ID) {
17840b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
17850b57cec5SDimitry Andric   // Skip TC symbol, which is only used with XCOFF.
17860b57cec5SDimitry Andric   while (getLexer().isNot(AsmToken::EndOfStatement)
17870b57cec5SDimitry Andric          && getLexer().isNot(AsmToken::Comma))
17880b57cec5SDimitry Andric     Parser.Lex();
17890b57cec5SDimitry Andric   if (parseToken(AsmToken::Comma))
17900b57cec5SDimitry Andric     return addErrorSuffix(" in '.tc' directive");
17910b57cec5SDimitry Andric 
17920b57cec5SDimitry Andric   // Align to word size.
1793bdd1243dSDimitry Andric   getParser().getStreamer().emitValueToAlignment(Align(Size));
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric   // Emit expressions.
17960b57cec5SDimitry Andric   return ParseDirectiveWord(Size, ID);
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric /// ParseDirectiveMachine (ELF platforms)
18000b57cec5SDimitry Andric ///  ::= .machine [ cpu | "push" | "pop" ]
18010b57cec5SDimitry Andric bool PPCAsmParser::ParseDirectiveMachine(SMLoc L) {
18020b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
18030b57cec5SDimitry Andric   if (Parser.getTok().isNot(AsmToken::Identifier) &&
18040b57cec5SDimitry Andric       Parser.getTok().isNot(AsmToken::String))
18050b57cec5SDimitry Andric     return Error(L, "unexpected token in '.machine' directive");
18060b57cec5SDimitry Andric 
18070b57cec5SDimitry Andric   StringRef CPU = Parser.getTok().getIdentifier();
18080b57cec5SDimitry Andric 
18090b57cec5SDimitry Andric   // FIXME: Right now, the parser always allows any available
18100b57cec5SDimitry Andric   // instruction, so the .machine directive is not useful.
1811e8d8bef9SDimitry Andric   // In the wild, any/push/pop/ppc64/altivec/power[4-9] are seen.
18120b57cec5SDimitry Andric 
18130b57cec5SDimitry Andric   Parser.Lex();
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
18160b57cec5SDimitry Andric     return addErrorSuffix(" in '.machine' directive");
18170b57cec5SDimitry Andric 
18185ffd83dbSDimitry Andric   PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>(
18190b57cec5SDimitry Andric       getParser().getStreamer().getTargetStreamer());
18205ffd83dbSDimitry Andric   if (TStreamer != nullptr)
18215ffd83dbSDimitry Andric     TStreamer->emitMachine(CPU);
18220b57cec5SDimitry Andric 
18230b57cec5SDimitry Andric   return false;
18240b57cec5SDimitry Andric }
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric /// ParseDirectiveAbiVersion
18270b57cec5SDimitry Andric ///  ::= .abiversion constant-expression
18280b57cec5SDimitry Andric bool PPCAsmParser::ParseDirectiveAbiVersion(SMLoc L) {
18290b57cec5SDimitry Andric   int64_t AbiVersion;
18300b57cec5SDimitry Andric   if (check(getParser().parseAbsoluteExpression(AbiVersion), L,
18310b57cec5SDimitry Andric             "expected constant expression") ||
18320b57cec5SDimitry Andric       parseToken(AsmToken::EndOfStatement))
18330b57cec5SDimitry Andric     return addErrorSuffix(" in '.abiversion' directive");
18340b57cec5SDimitry Andric 
18355ffd83dbSDimitry Andric   PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>(
18360b57cec5SDimitry Andric       getParser().getStreamer().getTargetStreamer());
18375ffd83dbSDimitry Andric   if (TStreamer != nullptr)
18385ffd83dbSDimitry Andric     TStreamer->emitAbiVersion(AbiVersion);
18390b57cec5SDimitry Andric 
18400b57cec5SDimitry Andric   return false;
18410b57cec5SDimitry Andric }
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric /// ParseDirectiveLocalEntry
18440b57cec5SDimitry Andric ///  ::= .localentry symbol, expression
18450b57cec5SDimitry Andric bool PPCAsmParser::ParseDirectiveLocalEntry(SMLoc L) {
18460b57cec5SDimitry Andric   StringRef Name;
18470b57cec5SDimitry Andric   if (getParser().parseIdentifier(Name))
18480b57cec5SDimitry Andric     return Error(L, "expected identifier in '.localentry' directive");
18490b57cec5SDimitry Andric 
18500b57cec5SDimitry Andric   MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
18510b57cec5SDimitry Andric   const MCExpr *Expr;
18520b57cec5SDimitry Andric 
18530b57cec5SDimitry Andric   if (parseToken(AsmToken::Comma) ||
18540b57cec5SDimitry Andric       check(getParser().parseExpression(Expr), L, "expected expression") ||
18550b57cec5SDimitry Andric       parseToken(AsmToken::EndOfStatement))
18560b57cec5SDimitry Andric     return addErrorSuffix(" in '.localentry' directive");
18570b57cec5SDimitry Andric 
18585ffd83dbSDimitry Andric   PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>(
18590b57cec5SDimitry Andric       getParser().getStreamer().getTargetStreamer());
18605ffd83dbSDimitry Andric   if (TStreamer != nullptr)
18615ffd83dbSDimitry Andric     TStreamer->emitLocalEntry(Sym, Expr);
18620b57cec5SDimitry Andric 
18630b57cec5SDimitry Andric   return false;
18640b57cec5SDimitry Andric }
18650b57cec5SDimitry Andric 
186604eeddc0SDimitry Andric bool PPCAsmParser::ParseGNUAttribute(SMLoc L) {
186704eeddc0SDimitry Andric   int64_t Tag;
186804eeddc0SDimitry Andric   int64_t IntegerValue;
186904eeddc0SDimitry Andric   if (!getParser().parseGNUAttribute(L, Tag, IntegerValue))
187004eeddc0SDimitry Andric     return false;
18710b57cec5SDimitry Andric 
187204eeddc0SDimitry Andric   getParser().getStreamer().emitGNUAttribute(Tag, IntegerValue);
187304eeddc0SDimitry Andric 
187404eeddc0SDimitry Andric   return true;
187504eeddc0SDimitry Andric }
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric /// Force static initialization.
1878480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmParser() {
18790b57cec5SDimitry Andric   RegisterMCAsmParser<PPCAsmParser> A(getThePPC32Target());
1880e8d8bef9SDimitry Andric   RegisterMCAsmParser<PPCAsmParser> B(getThePPC32LETarget());
1881e8d8bef9SDimitry Andric   RegisterMCAsmParser<PPCAsmParser> C(getThePPC64Target());
1882e8d8bef9SDimitry Andric   RegisterMCAsmParser<PPCAsmParser> D(getThePPC64LETarget());
18830b57cec5SDimitry Andric }
18840b57cec5SDimitry Andric 
18850b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
18860b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
18870b57cec5SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
18880b57cec5SDimitry Andric #include "PPCGenAsmMatcher.inc"
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric // Define this matcher function after the auto-generated include so we
18910b57cec5SDimitry Andric // have the match class enum definitions.
18920b57cec5SDimitry Andric unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
18930b57cec5SDimitry Andric                                                   unsigned Kind) {
18940b57cec5SDimitry Andric   // If the kind is a token for a literal immediate, check if our asm
18950b57cec5SDimitry Andric   // operand matches. This is for InstAliases which have a fixed-value
18960b57cec5SDimitry Andric   // immediate in the syntax.
18970b57cec5SDimitry Andric   int64_t ImmVal;
18980b57cec5SDimitry Andric   switch (Kind) {
18990b57cec5SDimitry Andric     case MCK_0: ImmVal = 0; break;
19000b57cec5SDimitry Andric     case MCK_1: ImmVal = 1; break;
19010b57cec5SDimitry Andric     case MCK_2: ImmVal = 2; break;
19020b57cec5SDimitry Andric     case MCK_3: ImmVal = 3; break;
19030b57cec5SDimitry Andric     case MCK_4: ImmVal = 4; break;
19040b57cec5SDimitry Andric     case MCK_5: ImmVal = 5; break;
19050b57cec5SDimitry Andric     case MCK_6: ImmVal = 6; break;
19060b57cec5SDimitry Andric     case MCK_7: ImmVal = 7; break;
19070b57cec5SDimitry Andric     default: return Match_InvalidOperand;
19080b57cec5SDimitry Andric   }
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric   PPCOperand &Op = static_cast<PPCOperand &>(AsmOp);
19110eae32dcSDimitry Andric   if (Op.isU3Imm() && Op.getImm() == ImmVal)
19120b57cec5SDimitry Andric     return Match_Success;
19130b57cec5SDimitry Andric 
19140b57cec5SDimitry Andric   return Match_InvalidOperand;
19150b57cec5SDimitry Andric }
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric const MCExpr *
19180b57cec5SDimitry Andric PPCAsmParser::applyModifierToExpr(const MCExpr *E,
19190b57cec5SDimitry Andric                                   MCSymbolRefExpr::VariantKind Variant,
19200b57cec5SDimitry Andric                                   MCContext &Ctx) {
19210b57cec5SDimitry Andric   switch (Variant) {
19220b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_LO:
19235ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_LO, E, Ctx);
19240b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HI:
19255ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HI, E, Ctx);
19260b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HA:
19275ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HA, E, Ctx);
19280b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HIGH:
19295ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGH, E, Ctx);
19300b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HIGHA:
19315ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHA, E, Ctx);
19320b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HIGHER:
19335ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHER, E, Ctx);
19340b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HIGHERA:
19355ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHERA, E, Ctx);
19360b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HIGHEST:
19375ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHEST, E, Ctx);
19380b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_HIGHESTA:
19395ffd83dbSDimitry Andric     return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHESTA, E, Ctx);
19400b57cec5SDimitry Andric   default:
19410b57cec5SDimitry Andric     return nullptr;
19420b57cec5SDimitry Andric   }
19430b57cec5SDimitry Andric }
1944