| Eric Christopher | 87590fa | 2016-06-16 01:00:53 +0000 | [diff] [blame] | 1 | //===-- PPCAsmParser.cpp - Parse PowerPC asm to MCInst instructions -------===// | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | 4 | // See https://llvm.org/LICENSE.txt for license information. | 
|  | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 |  | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 9 | #include "MCTargetDesc/PPCMCExpr.h" | 
| Benjamin Kramer | b3e8a6d | 2016-01-27 10:01:28 +0000 | [diff] [blame] | 10 | #include "MCTargetDesc/PPCMCTargetDesc.h" | 
| Rafael Espindola | 6b9ee9b | 2014-01-25 02:35:56 +0000 | [diff] [blame] | 11 | #include "PPCTargetStreamer.h" | 
| Richard Trieu | ee6ced1 | 2019-05-15 00:09:58 +0000 | [diff] [blame^] | 12 | #include "TargetInfo/PowerPCTargetInfo.h" | 
| Craig Topper | 690d8ea | 2013-07-24 07:33:14 +0000 | [diff] [blame] | 13 | #include "llvm/ADT/STLExtras.h" | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 14 | #include "llvm/ADT/StringSwitch.h" | 
|  | 15 | #include "llvm/ADT/Twine.h" | 
| Ulrich Weigand | bb68610 | 2014-07-20 23:06:03 +0000 | [diff] [blame] | 16 | #include "llvm/MC/MCContext.h" | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 17 | #include "llvm/MC/MCExpr.h" | 
|  | 18 | #include "llvm/MC/MCInst.h" | 
|  | 19 | #include "llvm/MC/MCInstrInfo.h" | 
|  | 20 | #include "llvm/MC/MCParser/MCAsmLexer.h" | 
|  | 21 | #include "llvm/MC/MCParser/MCAsmParser.h" | 
|  | 22 | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" | 
| Benjamin Kramer | b3e8a6d | 2016-01-27 10:01:28 +0000 | [diff] [blame] | 23 | #include "llvm/MC/MCParser/MCTargetAsmParser.h" | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 24 | #include "llvm/MC/MCStreamer.h" | 
|  | 25 | #include "llvm/MC/MCSubtargetInfo.h" | 
| Benjamin Kramer | b3e8a6d | 2016-01-27 10:01:28 +0000 | [diff] [blame] | 26 | #include "llvm/MC/MCSymbolELF.h" | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 27 | #include "llvm/Support/SourceMgr.h" | 
|  | 28 | #include "llvm/Support/TargetRegistry.h" | 
|  | 29 | #include "llvm/Support/raw_ostream.h" | 
|  | 30 |  | 
|  | 31 | using namespace llvm; | 
|  | 32 |  | 
| Nemanja Ivanovic | 0dad994 | 2018-12-29 16:13:11 +0000 | [diff] [blame] | 33 | DEFINE_PPC_REGCLASSES; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 34 |  | 
| Ulrich Weigand | b86cb7d | 2013-07-04 14:24:00 +0000 | [diff] [blame] | 35 | // Evaluate an expression containing condition register | 
|  | 36 | // or condition register field symbols.  Returns positive | 
|  | 37 | // value on success, or -1 on error. | 
|  | 38 | static int64_t | 
|  | 39 | EvaluateCRExpr(const MCExpr *E) { | 
|  | 40 | switch (E->getKind()) { | 
|  | 41 | case MCExpr::Target: | 
|  | 42 | return -1; | 
|  | 43 |  | 
|  | 44 | case MCExpr::Constant: { | 
|  | 45 | int64_t Res = cast<MCConstantExpr>(E)->getValue(); | 
|  | 46 | return Res < 0 ? -1 : Res; | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | case MCExpr::SymbolRef: { | 
|  | 50 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); | 
|  | 51 | StringRef Name = SRE->getSymbol().getName(); | 
|  | 52 |  | 
|  | 53 | if (Name == "lt") return 0; | 
|  | 54 | if (Name == "gt") return 1; | 
|  | 55 | if (Name == "eq") return 2; | 
|  | 56 | if (Name == "so") return 3; | 
|  | 57 | if (Name == "un") return 3; | 
|  | 58 |  | 
|  | 59 | if (Name == "cr0") return 0; | 
|  | 60 | if (Name == "cr1") return 1; | 
|  | 61 | if (Name == "cr2") return 2; | 
|  | 62 | if (Name == "cr3") return 3; | 
|  | 63 | if (Name == "cr4") return 4; | 
|  | 64 | if (Name == "cr5") return 5; | 
|  | 65 | if (Name == "cr6") return 6; | 
|  | 66 | if (Name == "cr7") return 7; | 
|  | 67 |  | 
|  | 68 | return -1; | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | case MCExpr::Unary: | 
|  | 72 | return -1; | 
|  | 73 |  | 
|  | 74 | case MCExpr::Binary: { | 
|  | 75 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); | 
|  | 76 | int64_t LHSVal = EvaluateCRExpr(BE->getLHS()); | 
|  | 77 | int64_t RHSVal = EvaluateCRExpr(BE->getRHS()); | 
|  | 78 | int64_t Res; | 
|  | 79 |  | 
|  | 80 | if (LHSVal < 0 || RHSVal < 0) | 
|  | 81 | return -1; | 
|  | 82 |  | 
|  | 83 | switch (BE->getOpcode()) { | 
|  | 84 | default: return -1; | 
|  | 85 | case MCBinaryExpr::Add: Res = LHSVal + RHSVal; break; | 
|  | 86 | case MCBinaryExpr::Mul: Res = LHSVal * RHSVal; break; | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | return Res < 0 ? -1 : Res; | 
|  | 90 | } | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | llvm_unreachable("Invalid expression kind!"); | 
|  | 94 | } | 
|  | 95 |  | 
| Craig Topper | f7df722 | 2014-12-18 05:02:14 +0000 | [diff] [blame] | 96 | namespace { | 
|  | 97 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 98 | struct PPCOperand; | 
|  | 99 |  | 
|  | 100 | class PPCAsmParser : public MCTargetAsmParser { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 101 | bool IsPPC64; | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 102 | bool IsDarwin; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 103 |  | 
| Rafael Espindola | 961d469 | 2014-11-11 05:18:41 +0000 | [diff] [blame] | 104 | void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 105 |  | 
|  | 106 | bool isPPC64() const { return IsPPC64; } | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 107 | bool isDarwin() const { return IsDarwin; } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 108 |  | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 109 | bool MatchRegisterName(unsigned &RegNo, int64_t &IntVal); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 110 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 111 | bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 112 |  | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 113 | const MCExpr *ExtractModifierFromExpr(const MCExpr *E, | 
|  | 114 | PPCMCExpr::VariantKind &Variant); | 
| Ulrich Weigand | 52cf8e4 | 2013-07-09 16:41:09 +0000 | [diff] [blame] | 115 | const MCExpr *FixupVariantKind(const MCExpr *E); | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 116 | bool ParseExpression(const MCExpr *&EVal); | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 117 | bool ParseDarwinExpression(const MCExpr *&EVal); | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 118 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 119 | bool ParseOperand(OperandVector &Operands); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 120 |  | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 121 | bool ParseDirectiveWord(unsigned Size, AsmToken ID); | 
|  | 122 | bool ParseDirectiveTC(unsigned Size, AsmToken ID); | 
| Ulrich Weigand | 55daa77 | 2013-07-09 10:00:34 +0000 | [diff] [blame] | 123 | bool ParseDirectiveMachine(SMLoc L); | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 124 | bool ParseDarwinDirectiveMachine(SMLoc L); | 
| Ulrich Weigand | 0daa516 | 2014-07-20 22:56:57 +0000 | [diff] [blame] | 125 | bool ParseDirectiveAbiVersion(SMLoc L); | 
| Ulrich Weigand | bb68610 | 2014-07-20 23:06:03 +0000 | [diff] [blame] | 126 | bool ParseDirectiveLocalEntry(SMLoc L); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 127 |  | 
|  | 128 | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 129 | OperandVector &Operands, MCStreamer &Out, | 
| Tim Northover | 26bb14e | 2014-08-18 11:49:42 +0000 | [diff] [blame] | 130 | uint64_t &ErrorInfo, | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 131 | bool MatchingInlineAsm) override; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 132 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 133 | void ProcessInstruction(MCInst &Inst, const OperandVector &Ops); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 134 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 135 | /// @name Auto-generated Match Functions | 
|  | 136 | /// { | 
|  | 137 |  | 
|  | 138 | #define GET_ASSEMBLER_HEADER | 
|  | 139 | #include "PPCGenAsmMatcher.inc" | 
|  | 140 |  | 
|  | 141 | /// } | 
|  | 142 |  | 
|  | 143 |  | 
|  | 144 | public: | 
| Akira Hatanaka | b11ef08 | 2015-11-14 06:35:56 +0000 | [diff] [blame] | 145 | PPCAsmParser(const MCSubtargetInfo &STI, MCAsmParser &, | 
| Akira Hatanaka | bd9fc28 | 2015-11-14 05:20:05 +0000 | [diff] [blame] | 146 | const MCInstrInfo &MII, const MCTargetOptions &Options) | 
| Oliver Stannard | 4191b9e | 2017-10-11 09:17:43 +0000 | [diff] [blame] | 147 | : MCTargetAsmParser(Options, STI, MII) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 148 | // Check for 64-bit vs. 32-bit pointer mode. | 
| Benjamin Kramer | 4fed928 | 2016-05-27 12:30:51 +0000 | [diff] [blame] | 149 | const Triple &TheTriple = STI.getTargetTriple(); | 
| Daniel Sanders | 50f1723 | 2015-09-15 16:17:27 +0000 | [diff] [blame] | 150 | IsPPC64 = (TheTriple.getArch() == Triple::ppc64 || | 
|  | 151 | TheTriple.getArch() == Triple::ppc64le); | 
|  | 152 | IsDarwin = TheTriple.isMacOSX(); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 153 | // Initialize the set of available features. | 
|  | 154 | setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); | 
|  | 155 | } | 
|  | 156 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 157 | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, | 
|  | 158 | SMLoc NameLoc, OperandVector &Operands) override; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 159 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 160 | bool ParseDirective(AsmToken DirectiveID) override; | 
| Ulrich Weigand | c0944b5 | 2013-07-08 14:49:37 +0000 | [diff] [blame] | 161 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 162 | unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 163 | unsigned Kind) override; | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 164 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 165 | const MCExpr *applyModifierToExpr(const MCExpr *E, | 
|  | 166 | MCSymbolRefExpr::VariantKind, | 
|  | 167 | MCContext &Ctx) override; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 168 | }; | 
|  | 169 |  | 
|  | 170 | /// PPCOperand - Instances of this class represent a parsed PowerPC machine | 
|  | 171 | /// instruction. | 
|  | 172 | struct PPCOperand : public MCParsedAsmOperand { | 
|  | 173 | enum KindTy { | 
|  | 174 | Token, | 
|  | 175 | Immediate, | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 176 | ContextImmediate, | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 177 | Expression, | 
|  | 178 | TLSRegister | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 179 | } Kind; | 
|  | 180 |  | 
|  | 181 | SMLoc StartLoc, EndLoc; | 
|  | 182 | bool IsPPC64; | 
|  | 183 |  | 
|  | 184 | struct TokOp { | 
|  | 185 | const char *Data; | 
|  | 186 | unsigned Length; | 
|  | 187 | }; | 
|  | 188 |  | 
|  | 189 | struct ImmOp { | 
|  | 190 | int64_t Val; | 
|  | 191 | }; | 
|  | 192 |  | 
|  | 193 | struct ExprOp { | 
|  | 194 | const MCExpr *Val; | 
| Ulrich Weigand | b86cb7d | 2013-07-04 14:24:00 +0000 | [diff] [blame] | 195 | int64_t CRVal;     // Cached result of EvaluateCRExpr(Val) | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 196 | }; | 
|  | 197 |  | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 198 | struct TLSRegOp { | 
|  | 199 | const MCSymbolRefExpr *Sym; | 
|  | 200 | }; | 
|  | 201 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 202 | union { | 
|  | 203 | struct TokOp Tok; | 
|  | 204 | struct ImmOp Imm; | 
|  | 205 | struct ExprOp Expr; | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 206 | struct TLSRegOp TLSReg; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 207 | }; | 
|  | 208 |  | 
|  | 209 | PPCOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} | 
|  | 210 | public: | 
|  | 211 | PPCOperand(const PPCOperand &o) : MCParsedAsmOperand() { | 
|  | 212 | Kind = o.Kind; | 
|  | 213 | StartLoc = o.StartLoc; | 
|  | 214 | EndLoc = o.EndLoc; | 
|  | 215 | IsPPC64 = o.IsPPC64; | 
|  | 216 | switch (Kind) { | 
|  | 217 | case Token: | 
|  | 218 | Tok = o.Tok; | 
|  | 219 | break; | 
|  | 220 | case Immediate: | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 221 | case ContextImmediate: | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 222 | Imm = o.Imm; | 
|  | 223 | break; | 
|  | 224 | case Expression: | 
|  | 225 | Expr = o.Expr; | 
|  | 226 | break; | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 227 | case TLSRegister: | 
|  | 228 | TLSReg = o.TLSReg; | 
|  | 229 | break; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 230 | } | 
|  | 231 | } | 
|  | 232 |  | 
| Richard Smith | c2a2830 | 2016-03-08 00:59:44 +0000 | [diff] [blame] | 233 | // Disable use of sized deallocation due to overallocation of PPCOperand | 
|  | 234 | // objects in CreateTokenWithStringCopy. | 
|  | 235 | void operator delete(void *p) { ::operator delete(p); } | 
|  | 236 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 237 | /// getStartLoc - Get the location of the first token of this operand. | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 238 | SMLoc getStartLoc() const override { return StartLoc; } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 239 |  | 
|  | 240 | /// getEndLoc - Get the location of the last token of this operand. | 
| Peter Collingbourne | 0da8630 | 2016-10-10 22:49:37 +0000 | [diff] [blame] | 241 | SMLoc getEndLoc() const override { return EndLoc; } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 242 |  | 
| Hal Finkel | e86a8b7 | 2017-12-16 02:42:18 +0000 | [diff] [blame] | 243 | /// getLocRange - Get the range between the first and last token of this | 
|  | 244 | /// operand. | 
|  | 245 | SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } | 
|  | 246 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 247 | /// isPPC64 - True if this operand is for an instruction in 64-bit mode. | 
|  | 248 | bool isPPC64() const { return IsPPC64; } | 
|  | 249 |  | 
|  | 250 | int64_t getImm() const { | 
|  | 251 | assert(Kind == Immediate && "Invalid access!"); | 
|  | 252 | return Imm.Val; | 
|  | 253 | } | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 254 | int64_t getImmS16Context() const { | 
| Eric Christopher | 87590fa | 2016-06-16 01:00:53 +0000 | [diff] [blame] | 255 | assert((Kind == Immediate || Kind == ContextImmediate) && | 
|  | 256 | "Invalid access!"); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 257 | if (Kind == Immediate) | 
|  | 258 | return Imm.Val; | 
|  | 259 | return static_cast<int16_t>(Imm.Val); | 
|  | 260 | } | 
|  | 261 | int64_t getImmU16Context() const { | 
| Eric Christopher | 87590fa | 2016-06-16 01:00:53 +0000 | [diff] [blame] | 262 | assert((Kind == Immediate || Kind == ContextImmediate) && | 
|  | 263 | "Invalid access!"); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 264 | return Imm.Val; | 
|  | 265 | } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 266 |  | 
|  | 267 | const MCExpr *getExpr() const { | 
|  | 268 | assert(Kind == Expression && "Invalid access!"); | 
|  | 269 | return Expr.Val; | 
|  | 270 | } | 
|  | 271 |  | 
| Ulrich Weigand | b86cb7d | 2013-07-04 14:24:00 +0000 | [diff] [blame] | 272 | int64_t getExprCRVal() const { | 
|  | 273 | assert(Kind == Expression && "Invalid access!"); | 
|  | 274 | return Expr.CRVal; | 
|  | 275 | } | 
|  | 276 |  | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 277 | const MCExpr *getTLSReg() const { | 
|  | 278 | assert(Kind == TLSRegister && "Invalid access!"); | 
|  | 279 | return TLSReg.Sym; | 
|  | 280 | } | 
|  | 281 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 282 | unsigned getReg() const override { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 283 | assert(isRegNumber() && "Invalid access!"); | 
|  | 284 | return (unsigned) Imm.Val; | 
|  | 285 | } | 
|  | 286 |  | 
| Hal Finkel | 27774d9 | 2014-03-13 07:58:58 +0000 | [diff] [blame] | 287 | unsigned getVSReg() const { | 
|  | 288 | assert(isVSRegNumber() && "Invalid access!"); | 
|  | 289 | return (unsigned) Imm.Val; | 
|  | 290 | } | 
|  | 291 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 292 | unsigned getCCReg() const { | 
|  | 293 | assert(isCCRegNumber() && "Invalid access!"); | 
| Ulrich Weigand | b86cb7d | 2013-07-04 14:24:00 +0000 | [diff] [blame] | 294 | return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | unsigned getCRBit() const { | 
|  | 298 | assert(isCRBitNumber() && "Invalid access!"); | 
|  | 299 | return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 300 | } | 
|  | 301 |  | 
|  | 302 | unsigned getCRBitMask() const { | 
|  | 303 | assert(isCRBitMask() && "Invalid access!"); | 
| Michael J. Spencer | df1ecbd7 | 2013-05-24 22:23:49 +0000 | [diff] [blame] | 304 | return 7 - countTrailingZeros<uint64_t>(Imm.Val); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 305 | } | 
|  | 306 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 307 | bool isToken() const override { return Kind == Token; } | 
| Eric Christopher | 87590fa | 2016-06-16 01:00:53 +0000 | [diff] [blame] | 308 | bool isImm() const override { | 
|  | 309 | return Kind == Immediate || Kind == Expression; | 
|  | 310 | } | 
| Nemanja Ivanovic | e8effe1 | 2015-03-04 20:44:33 +0000 | [diff] [blame] | 311 | bool isU1Imm() const { return Kind == Immediate && isUInt<1>(getImm()); } | 
| Hal Finkel | 27774d9 | 2014-03-13 07:58:58 +0000 | [diff] [blame] | 312 | bool isU2Imm() const { return Kind == Immediate && isUInt<2>(getImm()); } | 
| Kit Barton | 535e69d | 2015-03-25 19:36:23 +0000 | [diff] [blame] | 313 | bool isU3Imm() const { return Kind == Immediate && isUInt<3>(getImm()); } | 
| Joerg Sonnenberger | 9e9623c | 2014-07-29 22:21:57 +0000 | [diff] [blame] | 314 | bool isU4Imm() const { return Kind == Immediate && isUInt<4>(getImm()); } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 315 | bool isU5Imm() const { return Kind == Immediate && isUInt<5>(getImm()); } | 
|  | 316 | bool isS5Imm() const { return Kind == Immediate && isInt<5>(getImm()); } | 
|  | 317 | bool isU6Imm() const { return Kind == Immediate && isUInt<6>(getImm()); } | 
| Joerg Sonnenberger | 0013b92 | 2014-08-08 16:43:49 +0000 | [diff] [blame] | 318 | bool isU6ImmX2() const { return Kind == Immediate && | 
|  | 319 | isUInt<6>(getImm()) && | 
|  | 320 | (getImm() & 1) == 0; } | 
| Chuang-Yu Cheng | 8072271 | 2016-03-28 08:34:28 +0000 | [diff] [blame] | 321 | bool isU7Imm() const { return Kind == Immediate && isUInt<7>(getImm()); } | 
| Joerg Sonnenberger | 0013b92 | 2014-08-08 16:43:49 +0000 | [diff] [blame] | 322 | bool isU7ImmX4() const { return Kind == Immediate && | 
|  | 323 | isUInt<7>(getImm()) && | 
|  | 324 | (getImm() & 3) == 0; } | 
| Chuang-Yu Cheng | 8072271 | 2016-03-28 08:34:28 +0000 | [diff] [blame] | 325 | bool isU8Imm() const { return Kind == Immediate && isUInt<8>(getImm()); } | 
| Joerg Sonnenberger | 0013b92 | 2014-08-08 16:43:49 +0000 | [diff] [blame] | 326 | bool isU8ImmX8() const { return Kind == Immediate && | 
|  | 327 | isUInt<8>(getImm()) && | 
|  | 328 | (getImm() & 7) == 0; } | 
| Eric Christopher | 87590fa | 2016-06-16 01:00:53 +0000 | [diff] [blame] | 329 |  | 
| Bill Schmidt | e26236e | 2015-05-22 16:44:10 +0000 | [diff] [blame] | 330 | bool isU10Imm() const { return Kind == Immediate && isUInt<10>(getImm()); } | 
| Hal Finkel | c93a9a2 | 2015-02-25 01:06:45 +0000 | [diff] [blame] | 331 | bool isU12Imm() const { return Kind == Immediate && isUInt<12>(getImm()); } | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 332 | bool isU16Imm() const { | 
|  | 333 | switch (Kind) { | 
|  | 334 | case Expression: | 
|  | 335 | return true; | 
|  | 336 | case Immediate: | 
|  | 337 | case ContextImmediate: | 
|  | 338 | return isUInt<16>(getImmU16Context()); | 
|  | 339 | default: | 
|  | 340 | return false; | 
|  | 341 | } | 
|  | 342 | } | 
|  | 343 | bool isS16Imm() const { | 
|  | 344 | switch (Kind) { | 
|  | 345 | case Expression: | 
|  | 346 | return true; | 
|  | 347 | case Immediate: | 
|  | 348 | case ContextImmediate: | 
|  | 349 | return isInt<16>(getImmS16Context()); | 
|  | 350 | default: | 
|  | 351 | return false; | 
|  | 352 | } | 
|  | 353 | } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 354 | bool isS16ImmX4() const { return Kind == Expression || | 
|  | 355 | (Kind == Immediate && isInt<16>(getImm()) && | 
|  | 356 | (getImm() & 3) == 0); } | 
| Kit Barton | ba532dc | 2016-03-08 03:49:13 +0000 | [diff] [blame] | 357 | bool isS16ImmX16() const { return Kind == Expression || | 
|  | 358 | (Kind == Immediate && isInt<16>(getImm()) && | 
|  | 359 | (getImm() & 15) == 0); } | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 360 | bool isS17Imm() const { | 
|  | 361 | switch (Kind) { | 
|  | 362 | case Expression: | 
|  | 363 | return true; | 
|  | 364 | case Immediate: | 
|  | 365 | case ContextImmediate: | 
|  | 366 | return isInt<17>(getImmS16Context()); | 
|  | 367 | default: | 
|  | 368 | return false; | 
|  | 369 | } | 
|  | 370 | } | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 371 | bool isTLSReg() const { return Kind == TLSRegister; } | 
| Joerg Sonnenberger | eb9d13f | 2014-08-08 20:57:58 +0000 | [diff] [blame] | 372 | bool isDirectBr() const { | 
|  | 373 | if (Kind == Expression) | 
|  | 374 | return true; | 
|  | 375 | if (Kind != Immediate) | 
|  | 376 | return false; | 
|  | 377 | // Operand must be 64-bit aligned, signed 27-bit immediate. | 
|  | 378 | if ((getImm() & 3) != 0) | 
|  | 379 | return false; | 
|  | 380 | if (isInt<26>(getImm())) | 
|  | 381 | return true; | 
|  | 382 | if (!IsPPC64) { | 
|  | 383 | // In 32-bit mode, large 32-bit quantities wrap around. | 
|  | 384 | if (isUInt<32>(getImm()) && isInt<26>(static_cast<int32_t>(getImm()))) | 
|  | 385 | return true; | 
|  | 386 | } | 
|  | 387 | return false; | 
|  | 388 | } | 
| Ulrich Weigand | b6a30d1 | 2013-06-24 11:03:33 +0000 | [diff] [blame] | 389 | bool isCondBr() const { return Kind == Expression || | 
|  | 390 | (Kind == Immediate && isInt<16>(getImm()) && | 
|  | 391 | (getImm() & 3) == 0); } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 392 | bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); } | 
| Eric Christopher | 87590fa | 2016-06-16 01:00:53 +0000 | [diff] [blame] | 393 | bool isVSRegNumber() const { | 
|  | 394 | return Kind == Immediate && isUInt<6>(getImm()); | 
|  | 395 | } | 
| Ulrich Weigand | b86cb7d | 2013-07-04 14:24:00 +0000 | [diff] [blame] | 396 | bool isCCRegNumber() const { return (Kind == Expression | 
|  | 397 | && isUInt<3>(getExprCRVal())) || | 
|  | 398 | (Kind == Immediate | 
|  | 399 | && isUInt<3>(getImm())); } | 
|  | 400 | bool isCRBitNumber() const { return (Kind == Expression | 
|  | 401 | && isUInt<5>(getExprCRVal())) || | 
|  | 402 | (Kind == Immediate | 
|  | 403 | && isUInt<5>(getImm())); } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 404 | bool isCRBitMask() const { return Kind == Immediate && isUInt<8>(getImm()) && | 
|  | 405 | isPowerOf2_32(getImm()); } | 
| Hal Finkel | 522e4d9 | 2016-09-03 02:31:44 +0000 | [diff] [blame] | 406 | bool isATBitsAsHint() const { return false; } | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 407 | bool isMem() const override { return false; } | 
|  | 408 | bool isReg() const override { return false; } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 409 |  | 
|  | 410 | void addRegOperands(MCInst &Inst, unsigned N) const { | 
|  | 411 | llvm_unreachable("addRegOperands"); | 
|  | 412 | } | 
|  | 413 |  | 
|  | 414 | void addRegGPRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 415 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 416 | Inst.addOperand(MCOperand::createReg(RRegs[getReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 417 | } | 
|  | 418 |  | 
|  | 419 | void addRegGPRCNoR0Operands(MCInst &Inst, unsigned N) const { | 
|  | 420 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 421 | Inst.addOperand(MCOperand::createReg(RRegsNoR0[getReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 422 | } | 
|  | 423 |  | 
|  | 424 | void addRegG8RCOperands(MCInst &Inst, unsigned N) const { | 
|  | 425 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 426 | Inst.addOperand(MCOperand::createReg(XRegs[getReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 427 | } | 
|  | 428 |  | 
|  | 429 | void addRegG8RCNoX0Operands(MCInst &Inst, unsigned N) const { | 
|  | 430 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 431 | Inst.addOperand(MCOperand::createReg(XRegsNoX0[getReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 432 | } | 
|  | 433 |  | 
|  | 434 | void addRegGxRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 435 | if (isPPC64()) | 
|  | 436 | addRegG8RCOperands(Inst, N); | 
|  | 437 | else | 
|  | 438 | addRegGPRCOperands(Inst, N); | 
|  | 439 | } | 
|  | 440 |  | 
|  | 441 | void addRegGxRCNoR0Operands(MCInst &Inst, unsigned N) const { | 
|  | 442 | if (isPPC64()) | 
|  | 443 | addRegG8RCNoX0Operands(Inst, N); | 
|  | 444 | else | 
|  | 445 | addRegGPRCNoR0Operands(Inst, N); | 
|  | 446 | } | 
|  | 447 |  | 
|  | 448 | void addRegF4RCOperands(MCInst &Inst, unsigned N) const { | 
|  | 449 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 450 | Inst.addOperand(MCOperand::createReg(FRegs[getReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 451 | } | 
|  | 452 |  | 
|  | 453 | void addRegF8RCOperands(MCInst &Inst, unsigned N) const { | 
|  | 454 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 455 | Inst.addOperand(MCOperand::createReg(FRegs[getReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 456 | } | 
|  | 457 |  | 
| Nemanja Ivanovic | 11049f8 | 2016-10-04 06:59:23 +0000 | [diff] [blame] | 458 | void addRegVFRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 459 | assert(N == 1 && "Invalid number of operands!"); | 
|  | 460 | Inst.addOperand(MCOperand::createReg(VFRegs[getReg()])); | 
|  | 461 | } | 
|  | 462 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 463 | void addRegVRRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 464 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 465 | Inst.addOperand(MCOperand::createReg(VRegs[getReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 466 | } | 
|  | 467 |  | 
| Hal Finkel | 27774d9 | 2014-03-13 07:58:58 +0000 | [diff] [blame] | 468 | void addRegVSRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 469 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 470 | Inst.addOperand(MCOperand::createReg(VSRegs[getVSReg()])); | 
| Hal Finkel | 27774d9 | 2014-03-13 07:58:58 +0000 | [diff] [blame] | 471 | } | 
|  | 472 |  | 
| Hal Finkel | 19be506 | 2014-03-29 05:29:01 +0000 | [diff] [blame] | 473 | void addRegVSFRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 474 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 475 | Inst.addOperand(MCOperand::createReg(VSFRegs[getVSReg()])); | 
| Hal Finkel | 19be506 | 2014-03-29 05:29:01 +0000 | [diff] [blame] | 476 | } | 
|  | 477 |  | 
| Nemanja Ivanovic | f3c94b1 | 2015-05-07 18:24:05 +0000 | [diff] [blame] | 478 | void addRegVSSRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 479 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 480 | Inst.addOperand(MCOperand::createReg(VSSRegs[getVSReg()])); | 
| Nemanja Ivanovic | f3c94b1 | 2015-05-07 18:24:05 +0000 | [diff] [blame] | 481 | } | 
|  | 482 |  | 
| Hal Finkel | c93a9a2 | 2015-02-25 01:06:45 +0000 | [diff] [blame] | 483 | void addRegQFRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 484 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 485 | Inst.addOperand(MCOperand::createReg(QFRegs[getReg()])); | 
| Hal Finkel | c93a9a2 | 2015-02-25 01:06:45 +0000 | [diff] [blame] | 486 | } | 
|  | 487 |  | 
|  | 488 | void addRegQSRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 489 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 490 | Inst.addOperand(MCOperand::createReg(QFRegs[getReg()])); | 
| Hal Finkel | c93a9a2 | 2015-02-25 01:06:45 +0000 | [diff] [blame] | 491 | } | 
|  | 492 |  | 
|  | 493 | void addRegQBRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 494 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 495 | Inst.addOperand(MCOperand::createReg(QFRegs[getReg()])); | 
| Hal Finkel | c93a9a2 | 2015-02-25 01:06:45 +0000 | [diff] [blame] | 496 | } | 
|  | 497 |  | 
| Justin Hibbits | d52990c | 2018-07-18 04:25:10 +0000 | [diff] [blame] | 498 | void addRegSPE4RCOperands(MCInst &Inst, unsigned N) const { | 
|  | 499 | assert(N == 1 && "Invalid number of operands!"); | 
|  | 500 | Inst.addOperand(MCOperand::createReg(RRegs[getReg()])); | 
|  | 501 | } | 
|  | 502 |  | 
|  | 503 | void addRegSPERCOperands(MCInst &Inst, unsigned N) const { | 
|  | 504 | assert(N == 1 && "Invalid number of operands!"); | 
|  | 505 | Inst.addOperand(MCOperand::createReg(SPERegs[getReg()])); | 
|  | 506 | } | 
|  | 507 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 508 | void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 509 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 510 | Inst.addOperand(MCOperand::createReg(CRBITRegs[getCRBit()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 511 | } | 
|  | 512 |  | 
|  | 513 | void addRegCRRCOperands(MCInst &Inst, unsigned N) const { | 
|  | 514 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 515 | Inst.addOperand(MCOperand::createReg(CRRegs[getCCReg()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 516 | } | 
|  | 517 |  | 
|  | 518 | void addCRBitMaskOperands(MCInst &Inst, unsigned N) const { | 
|  | 519 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 520 | Inst.addOperand(MCOperand::createReg(CRRegs[getCRBitMask()])); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 521 | } | 
|  | 522 |  | 
|  | 523 | void addImmOperands(MCInst &Inst, unsigned N) const { | 
|  | 524 | assert(N == 1 && "Invalid number of operands!"); | 
|  | 525 | if (Kind == Immediate) | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 526 | Inst.addOperand(MCOperand::createImm(getImm())); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 527 | else | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 528 | Inst.addOperand(MCOperand::createExpr(getExpr())); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 529 | } | 
|  | 530 |  | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 531 | void addS16ImmOperands(MCInst &Inst, unsigned N) const { | 
|  | 532 | assert(N == 1 && "Invalid number of operands!"); | 
|  | 533 | switch (Kind) { | 
|  | 534 | case Immediate: | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 535 | Inst.addOperand(MCOperand::createImm(getImm())); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 536 | break; | 
|  | 537 | case ContextImmediate: | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 538 | Inst.addOperand(MCOperand::createImm(getImmS16Context())); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 539 | break; | 
|  | 540 | default: | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 541 | Inst.addOperand(MCOperand::createExpr(getExpr())); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 542 | break; | 
|  | 543 | } | 
|  | 544 | } | 
|  | 545 |  | 
|  | 546 | void addU16ImmOperands(MCInst &Inst, unsigned N) const { | 
|  | 547 | assert(N == 1 && "Invalid number of operands!"); | 
|  | 548 | switch (Kind) { | 
|  | 549 | case Immediate: | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 550 | Inst.addOperand(MCOperand::createImm(getImm())); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 551 | break; | 
|  | 552 | case ContextImmediate: | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 553 | Inst.addOperand(MCOperand::createImm(getImmU16Context())); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 554 | break; | 
|  | 555 | default: | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 556 | Inst.addOperand(MCOperand::createExpr(getExpr())); | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 557 | break; | 
|  | 558 | } | 
|  | 559 | } | 
|  | 560 |  | 
| Ulrich Weigand | b6a30d1 | 2013-06-24 11:03:33 +0000 | [diff] [blame] | 561 | void addBranchTargetOperands(MCInst &Inst, unsigned N) const { | 
|  | 562 | assert(N == 1 && "Invalid number of operands!"); | 
|  | 563 | if (Kind == Immediate) | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 564 | Inst.addOperand(MCOperand::createImm(getImm() / 4)); | 
| Ulrich Weigand | b6a30d1 | 2013-06-24 11:03:33 +0000 | [diff] [blame] | 565 | else | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 566 | Inst.addOperand(MCOperand::createExpr(getExpr())); | 
| Ulrich Weigand | b6a30d1 | 2013-06-24 11:03:33 +0000 | [diff] [blame] | 567 | } | 
|  | 568 |  | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 569 | void addTLSRegOperands(MCInst &Inst, unsigned N) const { | 
|  | 570 | assert(N == 1 && "Invalid number of operands!"); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 571 | Inst.addOperand(MCOperand::createExpr(getTLSReg())); | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 572 | } | 
|  | 573 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 574 | StringRef getToken() const { | 
|  | 575 | assert(Kind == Token && "Invalid access!"); | 
|  | 576 | return StringRef(Tok.Data, Tok.Length); | 
|  | 577 | } | 
|  | 578 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 579 | void print(raw_ostream &OS) const override; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 580 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 581 | static std::unique_ptr<PPCOperand> CreateToken(StringRef Str, SMLoc S, | 
|  | 582 | bool IsPPC64) { | 
|  | 583 | auto Op = make_unique<PPCOperand>(Token); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 584 | Op->Tok.Data = Str.data(); | 
|  | 585 | Op->Tok.Length = Str.size(); | 
|  | 586 | Op->StartLoc = S; | 
|  | 587 | Op->EndLoc = S; | 
|  | 588 | Op->IsPPC64 = IsPPC64; | 
|  | 589 | return Op; | 
|  | 590 | } | 
|  | 591 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 592 | static std::unique_ptr<PPCOperand> | 
|  | 593 | CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64) { | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 594 | // Allocate extra memory for the string and copy it. | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 595 | // FIXME: This is incorrect, Operands are owned by unique_ptr with a default | 
|  | 596 | // deleter which will destroy them by simply using "delete", not correctly | 
|  | 597 | // calling operator delete on this extra memory after calling the dtor | 
|  | 598 | // explicitly. | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 599 | void *Mem = ::operator new(sizeof(PPCOperand) + Str.size()); | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 600 | std::unique_ptr<PPCOperand> Op(new (Mem) PPCOperand(Token)); | 
| Benjamin Kramer | 769989c | 2014-08-15 11:05:45 +0000 | [diff] [blame] | 601 | Op->Tok.Data = reinterpret_cast<const char *>(Op.get() + 1); | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 602 | Op->Tok.Length = Str.size(); | 
| Benjamin Kramer | 769989c | 2014-08-15 11:05:45 +0000 | [diff] [blame] | 603 | std::memcpy(const_cast<char *>(Op->Tok.Data), Str.data(), Str.size()); | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 604 | Op->StartLoc = S; | 
|  | 605 | Op->EndLoc = S; | 
|  | 606 | Op->IsPPC64 = IsPPC64; | 
|  | 607 | return Op; | 
|  | 608 | } | 
|  | 609 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 610 | static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E, | 
|  | 611 | bool IsPPC64) { | 
|  | 612 | auto Op = make_unique<PPCOperand>(Immediate); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 613 | Op->Imm.Val = Val; | 
|  | 614 | Op->StartLoc = S; | 
|  | 615 | Op->EndLoc = E; | 
|  | 616 | Op->IsPPC64 = IsPPC64; | 
|  | 617 | return Op; | 
|  | 618 | } | 
|  | 619 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 620 | static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S, | 
|  | 621 | SMLoc E, bool IsPPC64) { | 
|  | 622 | auto Op = make_unique<PPCOperand>(Expression); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 623 | Op->Expr.Val = Val; | 
| Ulrich Weigand | b86cb7d | 2013-07-04 14:24:00 +0000 | [diff] [blame] | 624 | Op->Expr.CRVal = EvaluateCRExpr(Val); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 625 | Op->StartLoc = S; | 
|  | 626 | Op->EndLoc = E; | 
|  | 627 | Op->IsPPC64 = IsPPC64; | 
|  | 628 | return Op; | 
|  | 629 | } | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 630 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 631 | static std::unique_ptr<PPCOperand> | 
|  | 632 | CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64) { | 
|  | 633 | auto Op = make_unique<PPCOperand>(TLSRegister); | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 634 | Op->TLSReg.Sym = Sym; | 
|  | 635 | Op->StartLoc = S; | 
|  | 636 | Op->EndLoc = E; | 
|  | 637 | Op->IsPPC64 = IsPPC64; | 
|  | 638 | return Op; | 
|  | 639 | } | 
|  | 640 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 641 | static std::unique_ptr<PPCOperand> | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 642 | CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) { | 
|  | 643 | auto Op = make_unique<PPCOperand>(ContextImmediate); | 
|  | 644 | Op->Imm.Val = Val; | 
|  | 645 | Op->StartLoc = S; | 
|  | 646 | Op->EndLoc = E; | 
|  | 647 | Op->IsPPC64 = IsPPC64; | 
|  | 648 | return Op; | 
|  | 649 | } | 
|  | 650 |  | 
|  | 651 | static std::unique_ptr<PPCOperand> | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 652 | CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) { | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 653 | if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val)) | 
|  | 654 | return CreateImm(CE->getValue(), S, E, IsPPC64); | 
|  | 655 |  | 
|  | 656 | if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val)) | 
|  | 657 | if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS) | 
|  | 658 | return CreateTLSReg(SRE, S, E, IsPPC64); | 
|  | 659 |  | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 660 | if (const PPCMCExpr *TE = dyn_cast<PPCMCExpr>(Val)) { | 
|  | 661 | int64_t Res; | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 662 | if (TE->evaluateAsConstant(Res)) | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 663 | return CreateContextImm(Res, S, E, IsPPC64); | 
|  | 664 | } | 
|  | 665 |  | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 666 | return CreateExpr(Val, S, E, IsPPC64); | 
|  | 667 | } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 668 | }; | 
|  | 669 |  | 
|  | 670 | } // end anonymous namespace. | 
|  | 671 |  | 
|  | 672 | void PPCOperand::print(raw_ostream &OS) const { | 
|  | 673 | switch (Kind) { | 
|  | 674 | case Token: | 
|  | 675 | OS << "'" << getToken() << "'"; | 
|  | 676 | break; | 
|  | 677 | case Immediate: | 
| Joerg Sonnenberger | bfef1dd | 2014-08-10 12:41:50 +0000 | [diff] [blame] | 678 | case ContextImmediate: | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 679 | OS << getImm(); | 
|  | 680 | break; | 
|  | 681 | case Expression: | 
| Rafael Espindola | f4a1365 | 2015-05-27 13:05:42 +0000 | [diff] [blame] | 682 | OS << *getExpr(); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 683 | break; | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 684 | case TLSRegister: | 
| Rafael Espindola | f4a1365 | 2015-05-27 13:05:42 +0000 | [diff] [blame] | 685 | OS << *getTLSReg(); | 
| Ulrich Weigand | 5b42759 | 2013-07-05 12:22:36 +0000 | [diff] [blame] | 686 | break; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 687 | } | 
|  | 688 | } | 
|  | 689 |  | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 690 | static void | 
|  | 691 | addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) { | 
|  | 692 | if (Op.isImm()) { | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 693 | Inst.addOperand(MCOperand::createImm(-Op.getImm())); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 694 | return; | 
|  | 695 | } | 
|  | 696 | const MCExpr *Expr = Op.getExpr(); | 
|  | 697 | if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Expr)) { | 
|  | 698 | if (UnExpr->getOpcode() == MCUnaryExpr::Minus) { | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 699 | Inst.addOperand(MCOperand::createExpr(UnExpr->getSubExpr())); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 700 | return; | 
|  | 701 | } | 
|  | 702 | } else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) { | 
|  | 703 | if (BinExpr->getOpcode() == MCBinaryExpr::Sub) { | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 704 | const MCExpr *NE = MCBinaryExpr::createSub(BinExpr->getRHS(), | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 705 | BinExpr->getLHS(), Ctx); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 706 | Inst.addOperand(MCOperand::createExpr(NE)); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 707 | return; | 
|  | 708 | } | 
|  | 709 | } | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 710 | Inst.addOperand(MCOperand::createExpr(MCUnaryExpr::createMinus(Expr, Ctx))); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 711 | } | 
|  | 712 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 713 | void PPCAsmParser::ProcessInstruction(MCInst &Inst, | 
|  | 714 | const OperandVector &Operands) { | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 715 | int Opcode = Inst.getOpcode(); | 
|  | 716 | switch (Opcode) { | 
| Hal Finkel | fefcfff | 2015-04-23 22:47:57 +0000 | [diff] [blame] | 717 | case PPC::DCBTx: | 
|  | 718 | case PPC::DCBTT: | 
|  | 719 | case PPC::DCBTSTx: | 
|  | 720 | case PPC::DCBTSTT: { | 
|  | 721 | MCInst TmpInst; | 
|  | 722 | TmpInst.setOpcode((Opcode == PPC::DCBTx || Opcode == PPC::DCBTT) ? | 
|  | 723 | PPC::DCBT : PPC::DCBTST); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 724 | TmpInst.addOperand(MCOperand::createImm( | 
| Hal Finkel | fefcfff | 2015-04-23 22:47:57 +0000 | [diff] [blame] | 725 | (Opcode == PPC::DCBTx || Opcode == PPC::DCBTSTx) ? 0 : 16)); | 
|  | 726 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 727 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 728 | Inst = TmpInst; | 
|  | 729 | break; | 
|  | 730 | } | 
|  | 731 | case PPC::DCBTCT: | 
|  | 732 | case PPC::DCBTDS: { | 
|  | 733 | MCInst TmpInst; | 
|  | 734 | TmpInst.setOpcode(PPC::DCBT); | 
|  | 735 | TmpInst.addOperand(Inst.getOperand(2)); | 
|  | 736 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 737 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 738 | Inst = TmpInst; | 
|  | 739 | break; | 
|  | 740 | } | 
|  | 741 | case PPC::DCBTSTCT: | 
|  | 742 | case PPC::DCBTSTDS: { | 
|  | 743 | MCInst TmpInst; | 
|  | 744 | TmpInst.setOpcode(PPC::DCBTST); | 
|  | 745 | TmpInst.addOperand(Inst.getOperand(2)); | 
|  | 746 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 747 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 748 | Inst = TmpInst; | 
|  | 749 | break; | 
|  | 750 | } | 
| Hal Finkel | 277736e | 2016-09-02 23:41:54 +0000 | [diff] [blame] | 751 | case PPC::DCBFx: | 
|  | 752 | case PPC::DCBFL: | 
|  | 753 | case PPC::DCBFLP: { | 
|  | 754 | int L = 0; | 
|  | 755 | if (Opcode == PPC::DCBFL) | 
|  | 756 | L = 1; | 
|  | 757 | else if (Opcode == PPC::DCBFLP) | 
|  | 758 | L = 3; | 
|  | 759 |  | 
|  | 760 | MCInst TmpInst; | 
|  | 761 | TmpInst.setOpcode(PPC::DCBF); | 
|  | 762 | TmpInst.addOperand(MCOperand::createImm(L)); | 
|  | 763 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 764 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 765 | Inst = TmpInst; | 
|  | 766 | break; | 
|  | 767 | } | 
| Ulrich Weigand | 6ca7157 | 2013-06-24 18:08:03 +0000 | [diff] [blame] | 768 | case PPC::LAx: { | 
|  | 769 | MCInst TmpInst; | 
|  | 770 | TmpInst.setOpcode(PPC::LA); | 
|  | 771 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 772 | TmpInst.addOperand(Inst.getOperand(2)); | 
|  | 773 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 774 | Inst = TmpInst; | 
|  | 775 | break; | 
|  | 776 | } | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 777 | case PPC::SUBI: { | 
|  | 778 | MCInst TmpInst; | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 779 | TmpInst.setOpcode(PPC::ADDI); | 
|  | 780 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 781 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 782 | addNegOperand(TmpInst, Inst.getOperand(2), getContext()); | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 783 | Inst = TmpInst; | 
|  | 784 | break; | 
|  | 785 | } | 
|  | 786 | case PPC::SUBIS: { | 
|  | 787 | MCInst TmpInst; | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 788 | TmpInst.setOpcode(PPC::ADDIS); | 
|  | 789 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 790 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 791 | addNegOperand(TmpInst, Inst.getOperand(2), getContext()); | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 792 | Inst = TmpInst; | 
|  | 793 | break; | 
|  | 794 | } | 
|  | 795 | case PPC::SUBIC: { | 
|  | 796 | MCInst TmpInst; | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 797 | TmpInst.setOpcode(PPC::ADDIC); | 
|  | 798 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 799 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 800 | addNegOperand(TmpInst, Inst.getOperand(2), getContext()); | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 801 | Inst = TmpInst; | 
|  | 802 | break; | 
|  | 803 | } | 
|  | 804 | case PPC::SUBICo: { | 
|  | 805 | MCInst TmpInst; | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 806 | TmpInst.setOpcode(PPC::ADDICo); | 
|  | 807 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 808 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Joerg Sonnenberger | 5aab5af | 2014-08-09 17:10:26 +0000 | [diff] [blame] | 809 | addNegOperand(TmpInst, Inst.getOperand(2), getContext()); | 
| Ulrich Weigand | 4069e24 | 2013-06-25 13:16:48 +0000 | [diff] [blame] | 810 | Inst = TmpInst; | 
|  | 811 | break; | 
|  | 812 | } | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 813 | case PPC::EXTLWI: | 
|  | 814 | case PPC::EXTLWIo: { | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 815 | MCInst TmpInst; | 
|  | 816 | int64_t N = Inst.getOperand(2).getImm(); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 817 | int64_t B = Inst.getOperand(3).getImm(); | 
|  | 818 | TmpInst.setOpcode(Opcode == PPC::EXTLWI? PPC::RLWINM : PPC::RLWINMo); | 
|  | 819 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 820 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 821 | TmpInst.addOperand(MCOperand::createImm(B)); | 
|  | 822 | TmpInst.addOperand(MCOperand::createImm(0)); | 
|  | 823 | TmpInst.addOperand(MCOperand::createImm(N - 1)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 824 | Inst = TmpInst; | 
|  | 825 | break; | 
|  | 826 | } | 
|  | 827 | case PPC::EXTRWI: | 
|  | 828 | case PPC::EXTRWIo: { | 
|  | 829 | MCInst TmpInst; | 
|  | 830 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 831 | int64_t B = Inst.getOperand(3).getImm(); | 
|  | 832 | TmpInst.setOpcode(Opcode == PPC::EXTRWI? PPC::RLWINM : PPC::RLWINMo); | 
|  | 833 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 834 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 835 | TmpInst.addOperand(MCOperand::createImm(B + N)); | 
|  | 836 | TmpInst.addOperand(MCOperand::createImm(32 - N)); | 
|  | 837 | TmpInst.addOperand(MCOperand::createImm(31)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 838 | Inst = TmpInst; | 
|  | 839 | break; | 
|  | 840 | } | 
|  | 841 | case PPC::INSLWI: | 
|  | 842 | case PPC::INSLWIo: { | 
|  | 843 | MCInst TmpInst; | 
|  | 844 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 845 | int64_t B = Inst.getOperand(3).getImm(); | 
|  | 846 | TmpInst.setOpcode(Opcode == PPC::INSLWI? PPC::RLWIMI : PPC::RLWIMIo); | 
|  | 847 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 848 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 849 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 850 | TmpInst.addOperand(MCOperand::createImm(32 - B)); | 
|  | 851 | TmpInst.addOperand(MCOperand::createImm(B)); | 
|  | 852 | TmpInst.addOperand(MCOperand::createImm((B + N) - 1)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 853 | Inst = TmpInst; | 
|  | 854 | break; | 
|  | 855 | } | 
|  | 856 | case PPC::INSRWI: | 
|  | 857 | case PPC::INSRWIo: { | 
|  | 858 | MCInst TmpInst; | 
|  | 859 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 860 | int64_t B = Inst.getOperand(3).getImm(); | 
|  | 861 | TmpInst.setOpcode(Opcode == PPC::INSRWI? PPC::RLWIMI : PPC::RLWIMIo); | 
|  | 862 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 863 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 864 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 865 | TmpInst.addOperand(MCOperand::createImm(32 - (B + N))); | 
|  | 866 | TmpInst.addOperand(MCOperand::createImm(B)); | 
|  | 867 | TmpInst.addOperand(MCOperand::createImm((B + N) - 1)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 868 | Inst = TmpInst; | 
|  | 869 | break; | 
|  | 870 | } | 
|  | 871 | case PPC::ROTRWI: | 
|  | 872 | case PPC::ROTRWIo: { | 
|  | 873 | MCInst TmpInst; | 
|  | 874 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 875 | TmpInst.setOpcode(Opcode == PPC::ROTRWI? PPC::RLWINM : PPC::RLWINMo); | 
|  | 876 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 877 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 878 | TmpInst.addOperand(MCOperand::createImm(32 - N)); | 
|  | 879 | TmpInst.addOperand(MCOperand::createImm(0)); | 
|  | 880 | TmpInst.addOperand(MCOperand::createImm(31)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 881 | Inst = TmpInst; | 
|  | 882 | break; | 
|  | 883 | } | 
|  | 884 | case PPC::SLWI: | 
|  | 885 | case PPC::SLWIo: { | 
|  | 886 | MCInst TmpInst; | 
|  | 887 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 888 | TmpInst.setOpcode(Opcode == PPC::SLWI? PPC::RLWINM : PPC::RLWINMo); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 889 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 890 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 891 | TmpInst.addOperand(MCOperand::createImm(N)); | 
|  | 892 | TmpInst.addOperand(MCOperand::createImm(0)); | 
|  | 893 | TmpInst.addOperand(MCOperand::createImm(31 - N)); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 894 | Inst = TmpInst; | 
|  | 895 | break; | 
|  | 896 | } | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 897 | case PPC::SRWI: | 
|  | 898 | case PPC::SRWIo: { | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 899 | MCInst TmpInst; | 
|  | 900 | int64_t N = Inst.getOperand(2).getImm(); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 901 | TmpInst.setOpcode(Opcode == PPC::SRWI? PPC::RLWINM : PPC::RLWINMo); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 902 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 903 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 904 | TmpInst.addOperand(MCOperand::createImm(32 - N)); | 
|  | 905 | TmpInst.addOperand(MCOperand::createImm(N)); | 
|  | 906 | TmpInst.addOperand(MCOperand::createImm(31)); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 907 | Inst = TmpInst; | 
|  | 908 | break; | 
|  | 909 | } | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 910 | case PPC::CLRRWI: | 
|  | 911 | case PPC::CLRRWIo: { | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 912 | MCInst TmpInst; | 
|  | 913 | int64_t N = Inst.getOperand(2).getImm(); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 914 | TmpInst.setOpcode(Opcode == PPC::CLRRWI? PPC::RLWINM : PPC::RLWINMo); | 
|  | 915 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 916 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 917 | TmpInst.addOperand(MCOperand::createImm(0)); | 
|  | 918 | TmpInst.addOperand(MCOperand::createImm(0)); | 
|  | 919 | TmpInst.addOperand(MCOperand::createImm(31 - N)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 920 | Inst = TmpInst; | 
|  | 921 | break; | 
|  | 922 | } | 
|  | 923 | case PPC::CLRLSLWI: | 
|  | 924 | case PPC::CLRLSLWIo: { | 
|  | 925 | MCInst TmpInst; | 
|  | 926 | int64_t B = Inst.getOperand(2).getImm(); | 
|  | 927 | int64_t N = Inst.getOperand(3).getImm(); | 
|  | 928 | TmpInst.setOpcode(Opcode == PPC::CLRLSLWI? PPC::RLWINM : PPC::RLWINMo); | 
|  | 929 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 930 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 931 | TmpInst.addOperand(MCOperand::createImm(N)); | 
|  | 932 | TmpInst.addOperand(MCOperand::createImm(B - N)); | 
|  | 933 | TmpInst.addOperand(MCOperand::createImm(31 - N)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 934 | Inst = TmpInst; | 
|  | 935 | break; | 
|  | 936 | } | 
|  | 937 | case PPC::EXTLDI: | 
|  | 938 | case PPC::EXTLDIo: { | 
|  | 939 | MCInst TmpInst; | 
|  | 940 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 941 | int64_t B = Inst.getOperand(3).getImm(); | 
|  | 942 | TmpInst.setOpcode(Opcode == PPC::EXTLDI? PPC::RLDICR : PPC::RLDICRo); | 
|  | 943 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 944 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 945 | TmpInst.addOperand(MCOperand::createImm(B)); | 
|  | 946 | TmpInst.addOperand(MCOperand::createImm(N - 1)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 947 | Inst = TmpInst; | 
|  | 948 | break; | 
|  | 949 | } | 
|  | 950 | case PPC::EXTRDI: | 
|  | 951 | case PPC::EXTRDIo: { | 
|  | 952 | MCInst TmpInst; | 
|  | 953 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 954 | int64_t B = Inst.getOperand(3).getImm(); | 
|  | 955 | TmpInst.setOpcode(Opcode == PPC::EXTRDI? PPC::RLDICL : PPC::RLDICLo); | 
|  | 956 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 957 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 958 | TmpInst.addOperand(MCOperand::createImm(B + N)); | 
|  | 959 | TmpInst.addOperand(MCOperand::createImm(64 - N)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 960 | Inst = TmpInst; | 
|  | 961 | break; | 
|  | 962 | } | 
|  | 963 | case PPC::INSRDI: | 
|  | 964 | case PPC::INSRDIo: { | 
|  | 965 | MCInst TmpInst; | 
|  | 966 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 967 | int64_t B = Inst.getOperand(3).getImm(); | 
|  | 968 | TmpInst.setOpcode(Opcode == PPC::INSRDI? PPC::RLDIMI : PPC::RLDIMIo); | 
|  | 969 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 970 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 971 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 972 | TmpInst.addOperand(MCOperand::createImm(64 - (B + N))); | 
|  | 973 | TmpInst.addOperand(MCOperand::createImm(B)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 974 | Inst = TmpInst; | 
|  | 975 | break; | 
|  | 976 | } | 
|  | 977 | case PPC::ROTRDI: | 
|  | 978 | case PPC::ROTRDIo: { | 
|  | 979 | MCInst TmpInst; | 
|  | 980 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 981 | TmpInst.setOpcode(Opcode == PPC::ROTRDI? PPC::RLDICL : PPC::RLDICLo); | 
|  | 982 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 983 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 984 | TmpInst.addOperand(MCOperand::createImm(64 - N)); | 
|  | 985 | TmpInst.addOperand(MCOperand::createImm(0)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 986 | Inst = TmpInst; | 
|  | 987 | break; | 
|  | 988 | } | 
|  | 989 | case PPC::SLDI: | 
|  | 990 | case PPC::SLDIo: { | 
|  | 991 | MCInst TmpInst; | 
|  | 992 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 993 | TmpInst.setOpcode(Opcode == PPC::SLDI? PPC::RLDICR : PPC::RLDICRo); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 994 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 995 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 996 | TmpInst.addOperand(MCOperand::createImm(N)); | 
|  | 997 | TmpInst.addOperand(MCOperand::createImm(63 - N)); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 998 | Inst = TmpInst; | 
|  | 999 | break; | 
|  | 1000 | } | 
| Tony Jiang | 425071e | 2017-09-19 15:22:36 +0000 | [diff] [blame] | 1001 | case PPC::SUBPCIS: { | 
|  | 1002 | MCInst TmpInst; | 
|  | 1003 | int64_t N = Inst.getOperand(1).getImm(); | 
|  | 1004 | TmpInst.setOpcode(PPC::ADDPCIS); | 
|  | 1005 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1006 | TmpInst.addOperand(MCOperand::createImm(-N)); | 
|  | 1007 | Inst = TmpInst; | 
|  | 1008 | break; | 
|  | 1009 | } | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 1010 | case PPC::SRDI: | 
|  | 1011 | case PPC::SRDIo: { | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 1012 | MCInst TmpInst; | 
|  | 1013 | int64_t N = Inst.getOperand(2).getImm(); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 1014 | TmpInst.setOpcode(Opcode == PPC::SRDI? PPC::RLDICL : PPC::RLDICLo); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 1015 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1016 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 1017 | TmpInst.addOperand(MCOperand::createImm(64 - N)); | 
|  | 1018 | TmpInst.addOperand(MCOperand::createImm(N)); | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 1019 | Inst = TmpInst; | 
|  | 1020 | break; | 
|  | 1021 | } | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 1022 | case PPC::CLRRDI: | 
|  | 1023 | case PPC::CLRRDIo: { | 
|  | 1024 | MCInst TmpInst; | 
|  | 1025 | int64_t N = Inst.getOperand(2).getImm(); | 
|  | 1026 | TmpInst.setOpcode(Opcode == PPC::CLRRDI? PPC::RLDICR : PPC::RLDICRo); | 
|  | 1027 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1028 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 1029 | TmpInst.addOperand(MCOperand::createImm(0)); | 
|  | 1030 | TmpInst.addOperand(MCOperand::createImm(63 - N)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 1031 | Inst = TmpInst; | 
|  | 1032 | break; | 
|  | 1033 | } | 
|  | 1034 | case PPC::CLRLSLDI: | 
|  | 1035 | case PPC::CLRLSLDIo: { | 
|  | 1036 | MCInst TmpInst; | 
|  | 1037 | int64_t B = Inst.getOperand(2).getImm(); | 
|  | 1038 | int64_t N = Inst.getOperand(3).getImm(); | 
|  | 1039 | TmpInst.setOpcode(Opcode == PPC::CLRLSLDI? PPC::RLDIC : PPC::RLDICo); | 
|  | 1040 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1041 | TmpInst.addOperand(Inst.getOperand(1)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 1042 | TmpInst.addOperand(MCOperand::createImm(N)); | 
|  | 1043 | TmpInst.addOperand(MCOperand::createImm(B - N)); | 
| Ulrich Weigand | ad873cd | 2013-06-25 13:17:41 +0000 | [diff] [blame] | 1044 | Inst = TmpInst; | 
|  | 1045 | break; | 
|  | 1046 | } | 
| Hal Finkel | 6e9110a | 2015-03-28 19:42:41 +0000 | [diff] [blame] | 1047 | case PPC::RLWINMbm: | 
|  | 1048 | case PPC::RLWINMobm: { | 
|  | 1049 | unsigned MB, ME; | 
|  | 1050 | int64_t BM = Inst.getOperand(3).getImm(); | 
|  | 1051 | if (!isRunOfOnes(BM, MB, ME)) | 
|  | 1052 | break; | 
|  | 1053 |  | 
|  | 1054 | MCInst TmpInst; | 
|  | 1055 | TmpInst.setOpcode(Opcode == PPC::RLWINMbm ? PPC::RLWINM : PPC::RLWINMo); | 
|  | 1056 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1057 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 1058 | TmpInst.addOperand(Inst.getOperand(2)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 1059 | TmpInst.addOperand(MCOperand::createImm(MB)); | 
|  | 1060 | TmpInst.addOperand(MCOperand::createImm(ME)); | 
| Hal Finkel | 6e9110a | 2015-03-28 19:42:41 +0000 | [diff] [blame] | 1061 | Inst = TmpInst; | 
|  | 1062 | break; | 
|  | 1063 | } | 
|  | 1064 | case PPC::RLWIMIbm: | 
|  | 1065 | case PPC::RLWIMIobm: { | 
|  | 1066 | unsigned MB, ME; | 
|  | 1067 | int64_t BM = Inst.getOperand(3).getImm(); | 
|  | 1068 | if (!isRunOfOnes(BM, MB, ME)) | 
|  | 1069 | break; | 
|  | 1070 |  | 
|  | 1071 | MCInst TmpInst; | 
|  | 1072 | TmpInst.setOpcode(Opcode == PPC::RLWIMIbm ? PPC::RLWIMI : PPC::RLWIMIo); | 
|  | 1073 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1074 | TmpInst.addOperand(Inst.getOperand(0)); // The tied operand. | 
|  | 1075 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 1076 | TmpInst.addOperand(Inst.getOperand(2)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 1077 | TmpInst.addOperand(MCOperand::createImm(MB)); | 
|  | 1078 | TmpInst.addOperand(MCOperand::createImm(ME)); | 
| Hal Finkel | 6e9110a | 2015-03-28 19:42:41 +0000 | [diff] [blame] | 1079 | Inst = TmpInst; | 
|  | 1080 | break; | 
|  | 1081 | } | 
|  | 1082 | case PPC::RLWNMbm: | 
|  | 1083 | case PPC::RLWNMobm: { | 
|  | 1084 | unsigned MB, ME; | 
|  | 1085 | int64_t BM = Inst.getOperand(3).getImm(); | 
|  | 1086 | if (!isRunOfOnes(BM, MB, ME)) | 
|  | 1087 | break; | 
|  | 1088 |  | 
|  | 1089 | MCInst TmpInst; | 
|  | 1090 | TmpInst.setOpcode(Opcode == PPC::RLWNMbm ? PPC::RLWNM : PPC::RLWNMo); | 
|  | 1091 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1092 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 1093 | TmpInst.addOperand(Inst.getOperand(2)); | 
| Jim Grosbach | e9119e4 | 2015-05-13 18:37:00 +0000 | [diff] [blame] | 1094 | TmpInst.addOperand(MCOperand::createImm(MB)); | 
|  | 1095 | TmpInst.addOperand(MCOperand::createImm(ME)); | 
| Hal Finkel | 6e9110a | 2015-03-28 19:42:41 +0000 | [diff] [blame] | 1096 | Inst = TmpInst; | 
|  | 1097 | break; | 
|  | 1098 | } | 
| Kit Barton | 4f79f96 | 2015-06-16 16:01:15 +0000 | [diff] [blame] | 1099 | case PPC::MFTB: { | 
| Akira Hatanaka | bd9fc28 | 2015-11-14 05:20:05 +0000 | [diff] [blame] | 1100 | if (getSTI().getFeatureBits()[PPC::FeatureMFTB]) { | 
| Kit Barton | 4f79f96 | 2015-06-16 16:01:15 +0000 | [diff] [blame] | 1101 | assert(Inst.getNumOperands() == 2 && "Expecting two operands"); | 
|  | 1102 | Inst.setOpcode(PPC::MFSPR); | 
|  | 1103 | } | 
|  | 1104 | break; | 
|  | 1105 | } | 
| Chuang-Yu Cheng | eaf4b3d | 2016-04-06 01:46:45 +0000 | [diff] [blame] | 1106 | case PPC::CP_COPYx: | 
|  | 1107 | case PPC::CP_COPY_FIRST: { | 
|  | 1108 | MCInst TmpInst; | 
|  | 1109 | TmpInst.setOpcode(PPC::CP_COPY); | 
|  | 1110 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1111 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 1112 | TmpInst.addOperand(MCOperand::createImm(Opcode == PPC::CP_COPYx ? 0 : 1)); | 
|  | 1113 |  | 
|  | 1114 | Inst = TmpInst; | 
|  | 1115 | break; | 
|  | 1116 | } | 
|  | 1117 | case PPC::CP_PASTEx : | 
|  | 1118 | case PPC::CP_PASTE_LAST: { | 
|  | 1119 | MCInst TmpInst; | 
|  | 1120 | TmpInst.setOpcode(Opcode == PPC::CP_PASTEx ? | 
|  | 1121 | PPC::CP_PASTE : PPC::CP_PASTEo); | 
|  | 1122 | TmpInst.addOperand(Inst.getOperand(0)); | 
|  | 1123 | TmpInst.addOperand(Inst.getOperand(1)); | 
|  | 1124 | TmpInst.addOperand(MCOperand::createImm(Opcode == PPC::CP_PASTEx ? 0 : 1)); | 
|  | 1125 |  | 
|  | 1126 | Inst = TmpInst; | 
|  | 1127 | break; | 
|  | 1128 | } | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 1129 | } | 
|  | 1130 | } | 
|  | 1131 |  | 
| Stanislav Mekhanoshin | e98944e | 2019-03-11 17:04:35 +0000 | [diff] [blame] | 1132 | static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, | 
| Hal Finkel | e86a8b7 | 2017-12-16 02:42:18 +0000 | [diff] [blame] | 1133 | unsigned VariantID = 0); | 
|  | 1134 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1135 | bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | 
|  | 1136 | OperandVector &Operands, | 
| Tim Northover | 26bb14e | 2014-08-18 11:49:42 +0000 | [diff] [blame] | 1137 | MCStreamer &Out, uint64_t &ErrorInfo, | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1138 | bool MatchingInlineAsm) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1139 | MCInst Inst; | 
|  | 1140 |  | 
| Ranjeet Singh | 86ecbb7 | 2015-06-30 12:32:53 +0000 | [diff] [blame] | 1141 | switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1142 | case Match_Success: | 
| Ulrich Weigand | d839490 | 2013-05-03 19:50:27 +0000 | [diff] [blame] | 1143 | // Post-process instructions (typically extended mnemonics) | 
|  | 1144 | ProcessInstruction(Inst, Operands); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1145 | Inst.setLoc(IDLoc); | 
| Akira Hatanaka | bd9fc28 | 2015-11-14 05:20:05 +0000 | [diff] [blame] | 1146 | Out.EmitInstruction(Inst, getSTI()); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1147 | return false; | 
|  | 1148 | case Match_MissingFeature: | 
|  | 1149 | return Error(IDLoc, "instruction use requires an option to be enabled"); | 
| Hal Finkel | e86a8b7 | 2017-12-16 02:42:18 +0000 | [diff] [blame] | 1150 | case Match_MnemonicFail: { | 
| Stanislav Mekhanoshin | e98944e | 2019-03-11 17:04:35 +0000 | [diff] [blame] | 1151 | FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); | 
| Hal Finkel | e86a8b7 | 2017-12-16 02:42:18 +0000 | [diff] [blame] | 1152 | std::string Suggestion = PPCMnemonicSpellCheck( | 
|  | 1153 | ((PPCOperand &)*Operands[0]).getToken(), FBS); | 
|  | 1154 | return Error(IDLoc, "invalid instruction" + Suggestion, | 
|  | 1155 | ((PPCOperand &)*Operands[0]).getLocRange()); | 
|  | 1156 | } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1157 | case Match_InvalidOperand: { | 
|  | 1158 | SMLoc ErrorLoc = IDLoc; | 
| Tim Northover | 26bb14e | 2014-08-18 11:49:42 +0000 | [diff] [blame] | 1159 | if (ErrorInfo != ~0ULL) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1160 | if (ErrorInfo >= Operands.size()) | 
|  | 1161 | return Error(IDLoc, "too few operands for instruction"); | 
|  | 1162 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1163 | ErrorLoc = ((PPCOperand &)*Operands[ErrorInfo]).getStartLoc(); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1164 | if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; | 
|  | 1165 | } | 
|  | 1166 |  | 
|  | 1167 | return Error(ErrorLoc, "invalid operand for instruction"); | 
|  | 1168 | } | 
|  | 1169 | } | 
|  | 1170 |  | 
|  | 1171 | llvm_unreachable("Implement any new match types added!"); | 
|  | 1172 | } | 
|  | 1173 |  | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1174 | bool PPCAsmParser::MatchRegisterName(unsigned &RegNo, int64_t &IntVal) { | 
|  | 1175 | if (getParser().getTok().is(AsmToken::Identifier)) { | 
|  | 1176 | StringRef Name = getParser().getTok().getString(); | 
| Ulrich Weigand | 509c240 | 2013-05-06 11:16:57 +0000 | [diff] [blame] | 1177 | if (Name.equals_lower("lr")) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1178 | RegNo = isPPC64()? PPC::LR8 : PPC::LR; | 
|  | 1179 | IntVal = 8; | 
| Ulrich Weigand | 509c240 | 2013-05-06 11:16:57 +0000 | [diff] [blame] | 1180 | } else if (Name.equals_lower("ctr")) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1181 | RegNo = isPPC64()? PPC::CTR8 : PPC::CTR; | 
|  | 1182 | IntVal = 9; | 
| Hal Finkel | 52727c6 | 2013-07-02 03:39:34 +0000 | [diff] [blame] | 1183 | } else if (Name.equals_lower("vrsave")) { | 
|  | 1184 | RegNo = PPC::VRSAVE; | 
|  | 1185 | IntVal = 256; | 
| Rui Ueyama | 29d2910 | 2013-10-31 19:59:55 +0000 | [diff] [blame] | 1186 | } else if (Name.startswith_lower("r") && | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1187 | !Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) { | 
|  | 1188 | RegNo = isPPC64()? XRegs[IntVal] : RRegs[IntVal]; | 
| Rui Ueyama | 29d2910 | 2013-10-31 19:59:55 +0000 | [diff] [blame] | 1189 | } else if (Name.startswith_lower("f") && | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1190 | !Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) { | 
|  | 1191 | RegNo = FRegs[IntVal]; | 
| Hal Finkel | 4dc8fcc | 2015-04-23 23:16:22 +0000 | [diff] [blame] | 1192 | } else if (Name.startswith_lower("vs") && | 
|  | 1193 | !Name.substr(2).getAsInteger(10, IntVal) && IntVal < 64) { | 
|  | 1194 | RegNo = VSRegs[IntVal]; | 
| Rui Ueyama | 29d2910 | 2013-10-31 19:59:55 +0000 | [diff] [blame] | 1195 | } else if (Name.startswith_lower("v") && | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1196 | !Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) { | 
|  | 1197 | RegNo = VRegs[IntVal]; | 
| Hal Finkel | 4dc8fcc | 2015-04-23 23:16:22 +0000 | [diff] [blame] | 1198 | } else if (Name.startswith_lower("q") && | 
|  | 1199 | !Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) { | 
|  | 1200 | RegNo = QFRegs[IntVal]; | 
| Rui Ueyama | 29d2910 | 2013-10-31 19:59:55 +0000 | [diff] [blame] | 1201 | } else if (Name.startswith_lower("cr") && | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1202 | !Name.substr(2).getAsInteger(10, IntVal) && IntVal < 8) { | 
|  | 1203 | RegNo = CRRegs[IntVal]; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1204 | } else | 
|  | 1205 | return true; | 
|  | 1206 | getParser().Lex(); | 
|  | 1207 | return false; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1208 | } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1209 | return true; | 
|  | 1210 | } | 
|  | 1211 |  | 
|  | 1212 | bool PPCAsmParser:: | 
|  | 1213 | ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1214 | const AsmToken &Tok = getParser().getTok(); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1215 | StartLoc = Tok.getLoc(); | 
|  | 1216 | EndLoc = Tok.getEndLoc(); | 
|  | 1217 | RegNo = 0; | 
|  | 1218 | int64_t IntVal; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1219 | if (MatchRegisterName(RegNo, IntVal)) | 
|  | 1220 | return TokError("invalid register name"); | 
|  | 1221 | return false; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1222 | } | 
|  | 1223 |  | 
| NAKAMURA Takumi | 36c17ee | 2013-06-25 01:14:20 +0000 | [diff] [blame] | 1224 | /// Extract \code @l/@ha \endcode modifier from expression.  Recursively scan | 
| Ulrich Weigand | e67c565 | 2013-06-21 14:42:49 +0000 | [diff] [blame] | 1225 | /// the expression and check for VK_PPC_LO/HI/HA | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1226 | /// symbol variants.  If all symbols with modifier use the same | 
|  | 1227 | /// variant, return the corresponding PPCMCExpr::VariantKind, | 
|  | 1228 | /// and a modified expression using the default symbol variant. | 
|  | 1229 | /// Otherwise, return NULL. | 
|  | 1230 | const MCExpr *PPCAsmParser:: | 
|  | 1231 | ExtractModifierFromExpr(const MCExpr *E, | 
|  | 1232 | PPCMCExpr::VariantKind &Variant) { | 
|  | 1233 | MCContext &Context = getParser().getContext(); | 
|  | 1234 | Variant = PPCMCExpr::VK_PPC_None; | 
|  | 1235 |  | 
|  | 1236 | switch (E->getKind()) { | 
|  | 1237 | case MCExpr::Target: | 
|  | 1238 | case MCExpr::Constant: | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 1239 | return nullptr; | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1240 |  | 
|  | 1241 | case MCExpr::SymbolRef: { | 
|  | 1242 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); | 
|  | 1243 |  | 
|  | 1244 | switch (SRE->getKind()) { | 
| Ulrich Weigand | d51c09f | 2013-06-21 14:42:20 +0000 | [diff] [blame] | 1245 | case MCSymbolRefExpr::VK_PPC_LO: | 
|  | 1246 | Variant = PPCMCExpr::VK_PPC_LO; | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1247 | break; | 
| Ulrich Weigand | e67c565 | 2013-06-21 14:42:49 +0000 | [diff] [blame] | 1248 | case MCSymbolRefExpr::VK_PPC_HI: | 
|  | 1249 | Variant = PPCMCExpr::VK_PPC_HI; | 
|  | 1250 | break; | 
| Ulrich Weigand | d51c09f | 2013-06-21 14:42:20 +0000 | [diff] [blame] | 1251 | case MCSymbolRefExpr::VK_PPC_HA: | 
|  | 1252 | Variant = PPCMCExpr::VK_PPC_HA; | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1253 | break; | 
| Sean Fertile | 80b8f82 | 2018-06-15 19:47:11 +0000 | [diff] [blame] | 1254 | case MCSymbolRefExpr::VK_PPC_HIGH: | 
|  | 1255 | Variant = PPCMCExpr::VK_PPC_HIGH; | 
|  | 1256 | break; | 
|  | 1257 | case MCSymbolRefExpr::VK_PPC_HIGHA: | 
|  | 1258 | Variant = PPCMCExpr::VK_PPC_HIGHA; | 
|  | 1259 | break; | 
| Ulrich Weigand | e9126f5 | 2013-06-21 14:43:42 +0000 | [diff] [blame] | 1260 | case MCSymbolRefExpr::VK_PPC_HIGHER: | 
|  | 1261 | Variant = PPCMCExpr::VK_PPC_HIGHER; | 
|  | 1262 | break; | 
|  | 1263 | case MCSymbolRefExpr::VK_PPC_HIGHERA: | 
|  | 1264 | Variant = PPCMCExpr::VK_PPC_HIGHERA; | 
|  | 1265 | break; | 
|  | 1266 | case MCSymbolRefExpr::VK_PPC_HIGHEST: | 
|  | 1267 | Variant = PPCMCExpr::VK_PPC_HIGHEST; | 
|  | 1268 | break; | 
|  | 1269 | case MCSymbolRefExpr::VK_PPC_HIGHESTA: | 
|  | 1270 | Variant = PPCMCExpr::VK_PPC_HIGHESTA; | 
|  | 1271 | break; | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1272 | default: | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 1273 | return nullptr; | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1274 | } | 
|  | 1275 |  | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1276 | return MCSymbolRefExpr::create(&SRE->getSymbol(), Context); | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1277 | } | 
|  | 1278 |  | 
|  | 1279 | case MCExpr::Unary: { | 
|  | 1280 | const MCUnaryExpr *UE = cast<MCUnaryExpr>(E); | 
|  | 1281 | const MCExpr *Sub = ExtractModifierFromExpr(UE->getSubExpr(), Variant); | 
|  | 1282 | if (!Sub) | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 1283 | return nullptr; | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1284 | return MCUnaryExpr::create(UE->getOpcode(), Sub, Context); | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1285 | } | 
|  | 1286 |  | 
|  | 1287 | case MCExpr::Binary: { | 
|  | 1288 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); | 
|  | 1289 | PPCMCExpr::VariantKind LHSVariant, RHSVariant; | 
|  | 1290 | const MCExpr *LHS = ExtractModifierFromExpr(BE->getLHS(), LHSVariant); | 
|  | 1291 | const MCExpr *RHS = ExtractModifierFromExpr(BE->getRHS(), RHSVariant); | 
|  | 1292 |  | 
|  | 1293 | if (!LHS && !RHS) | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 1294 | return nullptr; | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1295 |  | 
|  | 1296 | if (!LHS) LHS = BE->getLHS(); | 
|  | 1297 | if (!RHS) RHS = BE->getRHS(); | 
|  | 1298 |  | 
|  | 1299 | if (LHSVariant == PPCMCExpr::VK_PPC_None) | 
|  | 1300 | Variant = RHSVariant; | 
|  | 1301 | else if (RHSVariant == PPCMCExpr::VK_PPC_None) | 
|  | 1302 | Variant = LHSVariant; | 
|  | 1303 | else if (LHSVariant == RHSVariant) | 
|  | 1304 | Variant = LHSVariant; | 
|  | 1305 | else | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 1306 | return nullptr; | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1307 |  | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1308 | return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context); | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1309 | } | 
|  | 1310 | } | 
|  | 1311 |  | 
|  | 1312 | llvm_unreachable("Invalid expression kind!"); | 
|  | 1313 | } | 
|  | 1314 |  | 
| Ulrich Weigand | 52cf8e4 | 2013-07-09 16:41:09 +0000 | [diff] [blame] | 1315 | /// Find all VK_TLSGD/VK_TLSLD symbol references in expression and replace | 
|  | 1316 | /// them by VK_PPC_TLSGD/VK_PPC_TLSLD.  This is necessary to avoid having | 
|  | 1317 | /// _GLOBAL_OFFSET_TABLE_ created via ELFObjectWriter::RelocNeedsGOT. | 
|  | 1318 | /// FIXME: This is a hack. | 
|  | 1319 | const MCExpr *PPCAsmParser:: | 
|  | 1320 | FixupVariantKind(const MCExpr *E) { | 
|  | 1321 | MCContext &Context = getParser().getContext(); | 
|  | 1322 |  | 
|  | 1323 | switch (E->getKind()) { | 
|  | 1324 | case MCExpr::Target: | 
|  | 1325 | case MCExpr::Constant: | 
|  | 1326 | return E; | 
|  | 1327 |  | 
|  | 1328 | case MCExpr::SymbolRef: { | 
|  | 1329 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); | 
|  | 1330 | MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; | 
|  | 1331 |  | 
|  | 1332 | switch (SRE->getKind()) { | 
|  | 1333 | case MCSymbolRefExpr::VK_TLSGD: | 
|  | 1334 | Variant = MCSymbolRefExpr::VK_PPC_TLSGD; | 
|  | 1335 | break; | 
|  | 1336 | case MCSymbolRefExpr::VK_TLSLD: | 
|  | 1337 | Variant = MCSymbolRefExpr::VK_PPC_TLSLD; | 
|  | 1338 | break; | 
|  | 1339 | default: | 
|  | 1340 | return E; | 
|  | 1341 | } | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1342 | return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, Context); | 
| Ulrich Weigand | 52cf8e4 | 2013-07-09 16:41:09 +0000 | [diff] [blame] | 1343 | } | 
|  | 1344 |  | 
|  | 1345 | case MCExpr::Unary: { | 
|  | 1346 | const MCUnaryExpr *UE = cast<MCUnaryExpr>(E); | 
|  | 1347 | const MCExpr *Sub = FixupVariantKind(UE->getSubExpr()); | 
|  | 1348 | if (Sub == UE->getSubExpr()) | 
|  | 1349 | return E; | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1350 | return MCUnaryExpr::create(UE->getOpcode(), Sub, Context); | 
| Ulrich Weigand | 52cf8e4 | 2013-07-09 16:41:09 +0000 | [diff] [blame] | 1351 | } | 
|  | 1352 |  | 
|  | 1353 | case MCExpr::Binary: { | 
|  | 1354 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); | 
|  | 1355 | const MCExpr *LHS = FixupVariantKind(BE->getLHS()); | 
|  | 1356 | const MCExpr *RHS = FixupVariantKind(BE->getRHS()); | 
|  | 1357 | if (LHS == BE->getLHS() && RHS == BE->getRHS()) | 
|  | 1358 | return E; | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1359 | return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context); | 
| Ulrich Weigand | 52cf8e4 | 2013-07-09 16:41:09 +0000 | [diff] [blame] | 1360 | } | 
|  | 1361 | } | 
|  | 1362 |  | 
|  | 1363 | llvm_unreachable("Invalid expression kind!"); | 
|  | 1364 | } | 
|  | 1365 |  | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1366 | /// ParseExpression.  This differs from the default "parseExpression" in that | 
|  | 1367 | /// it handles modifiers. | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1368 | bool PPCAsmParser:: | 
|  | 1369 | ParseExpression(const MCExpr *&EVal) { | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1370 |  | 
|  | 1371 | if (isDarwin()) | 
|  | 1372 | return ParseDarwinExpression(EVal); | 
|  | 1373 |  | 
|  | 1374 | // (ELF Platforms) | 
|  | 1375 | // Handle \code @l/@ha \endcode | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1376 | if (getParser().parseExpression(EVal)) | 
|  | 1377 | return true; | 
|  | 1378 |  | 
| Ulrich Weigand | 52cf8e4 | 2013-07-09 16:41:09 +0000 | [diff] [blame] | 1379 | EVal = FixupVariantKind(EVal); | 
|  | 1380 |  | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1381 | PPCMCExpr::VariantKind Variant; | 
|  | 1382 | const MCExpr *E = ExtractModifierFromExpr(EVal, Variant); | 
|  | 1383 | if (E) | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1384 | EVal = PPCMCExpr::create(Variant, E, false, getParser().getContext()); | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1385 |  | 
|  | 1386 | return false; | 
|  | 1387 | } | 
|  | 1388 |  | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1389 | /// ParseDarwinExpression.  (MachO Platforms) | 
|  | 1390 | /// This differs from the default "parseExpression" in that it handles detection | 
|  | 1391 | /// of the \code hi16(), ha16() and lo16() \endcode modifiers.  At present, | 
|  | 1392 | /// parseExpression() doesn't recognise the modifiers when in the Darwin/MachO | 
| Eric Christopher | 87590fa | 2016-06-16 01:00:53 +0000 | [diff] [blame] | 1393 | /// syntax form so it is done here.  TODO: Determine if there is merit in | 
|  | 1394 | /// arranging for this to be done at a higher level. | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1395 | bool PPCAsmParser:: | 
|  | 1396 | ParseDarwinExpression(const MCExpr *&EVal) { | 
| Rafael Espindola | 961d469 | 2014-11-11 05:18:41 +0000 | [diff] [blame] | 1397 | MCAsmParser &Parser = getParser(); | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1398 | PPCMCExpr::VariantKind Variant = PPCMCExpr::VK_PPC_None; | 
|  | 1399 | switch (getLexer().getKind()) { | 
|  | 1400 | default: | 
|  | 1401 | break; | 
|  | 1402 | case AsmToken::Identifier: | 
|  | 1403 | // Compiler-generated Darwin identifiers begin with L,l,_ or "; thus | 
|  | 1404 | // something starting with any other char should be part of the | 
|  | 1405 | // asm syntax.  If handwritten asm includes an identifier like lo16, | 
|  | 1406 | // then all bets are off - but no-one would do that, right? | 
|  | 1407 | StringRef poss = Parser.getTok().getString(); | 
|  | 1408 | if (poss.equals_lower("lo16")) { | 
|  | 1409 | Variant = PPCMCExpr::VK_PPC_LO; | 
|  | 1410 | } else if (poss.equals_lower("hi16")) { | 
|  | 1411 | Variant = PPCMCExpr::VK_PPC_HI; | 
|  | 1412 | } else if (poss.equals_lower("ha16")) { | 
|  | 1413 | Variant = PPCMCExpr::VK_PPC_HA; | 
|  | 1414 | } | 
|  | 1415 | if (Variant != PPCMCExpr::VK_PPC_None) { | 
|  | 1416 | Parser.Lex(); // Eat the xx16 | 
|  | 1417 | if (getLexer().isNot(AsmToken::LParen)) | 
|  | 1418 | return Error(Parser.getTok().getLoc(), "expected '('"); | 
|  | 1419 | Parser.Lex(); // Eat the '(' | 
|  | 1420 | } | 
|  | 1421 | break; | 
|  | 1422 | } | 
|  | 1423 |  | 
|  | 1424 | if (getParser().parseExpression(EVal)) | 
|  | 1425 | return true; | 
|  | 1426 |  | 
|  | 1427 | if (Variant != PPCMCExpr::VK_PPC_None) { | 
|  | 1428 | if (getLexer().isNot(AsmToken::RParen)) | 
|  | 1429 | return Error(Parser.getTok().getLoc(), "expected ')'"); | 
|  | 1430 | Parser.Lex(); // Eat the ')' | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1431 | EVal = PPCMCExpr::create(Variant, EVal, false, getParser().getContext()); | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1432 | } | 
|  | 1433 | return false; | 
|  | 1434 | } | 
|  | 1435 |  | 
|  | 1436 | /// ParseOperand | 
|  | 1437 | /// This handles registers in the form 'NN', '%rNN' for ELF platforms and | 
|  | 1438 | /// rNN for MachO. | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1439 | bool PPCAsmParser::ParseOperand(OperandVector &Operands) { | 
| Rafael Espindola | 961d469 | 2014-11-11 05:18:41 +0000 | [diff] [blame] | 1440 | MCAsmParser &Parser = getParser(); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1441 | SMLoc S = Parser.getTok().getLoc(); | 
|  | 1442 | SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | 
|  | 1443 | const MCExpr *EVal; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1444 |  | 
|  | 1445 | // Attempt to parse the next token as an immediate | 
|  | 1446 | switch (getLexer().getKind()) { | 
|  | 1447 | // Special handling for register names.  These are interpreted | 
|  | 1448 | // as immediates corresponding to the register number. | 
|  | 1449 | case AsmToken::Percent: | 
|  | 1450 | Parser.Lex(); // Eat the '%'. | 
|  | 1451 | unsigned RegNo; | 
|  | 1452 | int64_t IntVal; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1453 | if (MatchRegisterName(RegNo, IntVal)) | 
|  | 1454 | return Error(S, "invalid register name"); | 
|  | 1455 |  | 
|  | 1456 | Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64())); | 
|  | 1457 | return false; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1458 |  | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1459 | case AsmToken::Identifier: | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1460 | case AsmToken::LParen: | 
|  | 1461 | case AsmToken::Plus: | 
|  | 1462 | case AsmToken::Minus: | 
|  | 1463 | case AsmToken::Integer: | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1464 | case AsmToken::Dot: | 
|  | 1465 | case AsmToken::Dollar: | 
| Roman Divacky | a26f9a6 | 2014-03-12 19:25:57 +0000 | [diff] [blame] | 1466 | case AsmToken::Exclaim: | 
|  | 1467 | case AsmToken::Tilde: | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1468 | // Note that non-register-name identifiers from the compiler will begin | 
|  | 1469 | // with '_', 'L'/'l' or '"'.  Of course, handwritten asm could include | 
|  | 1470 | // identifiers like r31foo - so we fall through in the event that parsing | 
|  | 1471 | // a register name fails. | 
|  | 1472 | if (isDarwin()) { | 
|  | 1473 | unsigned RegNo; | 
|  | 1474 | int64_t IntVal; | 
|  | 1475 | if (!MatchRegisterName(RegNo, IntVal)) { | 
|  | 1476 | Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64())); | 
|  | 1477 | return false; | 
|  | 1478 | } | 
|  | 1479 | } | 
|  | 1480 | // All other expressions | 
|  | 1481 |  | 
| Ulrich Weigand | 96e6578 | 2013-06-20 16:23:52 +0000 | [diff] [blame] | 1482 | if (!ParseExpression(EVal)) | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1483 | break; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1484 | // Fall-through | 
|  | 1485 | LLVM_FALLTHROUGH; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1486 | default: | 
|  | 1487 | return Error(S, "unknown operand"); | 
|  | 1488 | } | 
|  | 1489 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1490 | // Push the parsed operand into the list of operands | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1491 | Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64())); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1492 |  | 
| Ulrich Weigand | 42a09dc | 2013-07-02 21:31:59 +0000 | [diff] [blame] | 1493 | // Check whether this is a TLS call expression | 
|  | 1494 | bool TLSCall = false; | 
|  | 1495 | if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(EVal)) | 
|  | 1496 | TLSCall = Ref->getSymbol().getName() == "__tls_get_addr"; | 
|  | 1497 |  | 
|  | 1498 | if (TLSCall && getLexer().is(AsmToken::LParen)) { | 
|  | 1499 | const MCExpr *TLSSym; | 
|  | 1500 |  | 
|  | 1501 | Parser.Lex(); // Eat the '('. | 
|  | 1502 | S = Parser.getTok().getLoc(); | 
|  | 1503 | if (ParseExpression(TLSSym)) | 
|  | 1504 | return Error(S, "invalid TLS call expression"); | 
|  | 1505 | if (getLexer().isNot(AsmToken::RParen)) | 
|  | 1506 | return Error(Parser.getTok().getLoc(), "missing ')'"); | 
|  | 1507 | E = Parser.getTok().getLoc(); | 
|  | 1508 | Parser.Lex(); // Eat the ')'. | 
|  | 1509 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1510 | Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64())); | 
| Ulrich Weigand | 42a09dc | 2013-07-02 21:31:59 +0000 | [diff] [blame] | 1511 | } | 
|  | 1512 |  | 
|  | 1513 | // Otherwise, check for D-form memory operands | 
|  | 1514 | if (!TLSCall && getLexer().is(AsmToken::LParen)) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1515 | Parser.Lex(); // Eat the '('. | 
|  | 1516 | S = Parser.getTok().getLoc(); | 
|  | 1517 |  | 
|  | 1518 | int64_t IntVal; | 
|  | 1519 | switch (getLexer().getKind()) { | 
|  | 1520 | case AsmToken::Percent: | 
|  | 1521 | Parser.Lex(); // Eat the '%'. | 
|  | 1522 | unsigned RegNo; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1523 | if (MatchRegisterName(RegNo, IntVal)) | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1524 | return Error(S, "invalid register name"); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1525 | break; | 
|  | 1526 |  | 
|  | 1527 | case AsmToken::Integer: | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1528 | if (isDarwin()) | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1529 | return Error(S, "unexpected integer value"); | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1530 | else if (getParser().parseAbsoluteExpression(IntVal) || IntVal < 0 || | 
|  | 1531 | IntVal > 31) | 
|  | 1532 | return Error(S, "invalid register number"); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1533 | break; | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1534 | case AsmToken::Identifier: | 
|  | 1535 | if (isDarwin()) { | 
|  | 1536 | unsigned RegNo; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1537 | if (!MatchRegisterName(RegNo, IntVal)) { | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1538 | break; | 
|  | 1539 | } | 
|  | 1540 | } | 
| Justin Bogner | b03fd12 | 2016-08-17 05:10:15 +0000 | [diff] [blame] | 1541 | LLVM_FALLTHROUGH; | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1542 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1543 | default: | 
|  | 1544 | return Error(S, "invalid memory operand"); | 
|  | 1545 | } | 
|  | 1546 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1547 | E = Parser.getTok().getLoc(); | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1548 | if (parseToken(AsmToken::RParen, "missing ')'")) | 
|  | 1549 | return true; | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1550 | Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64())); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1551 | } | 
|  | 1552 |  | 
|  | 1553 | return false; | 
|  | 1554 | } | 
|  | 1555 |  | 
|  | 1556 | /// Parse an instruction mnemonic followed by its operands. | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1557 | bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, | 
|  | 1558 | SMLoc NameLoc, OperandVector &Operands) { | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1559 | // The first operand is the token for the instruction name. | 
| Ulrich Weigand | 86247b6 | 2013-06-24 16:52:04 +0000 | [diff] [blame] | 1560 | // If the next character is a '+' or '-', we need to add it to the | 
|  | 1561 | // instruction name, to match what TableGen is doing. | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 1562 | std::string NewOpcode; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1563 | if (parseOptionalToken(AsmToken::Plus)) { | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 1564 | NewOpcode = Name; | 
|  | 1565 | NewOpcode += '+'; | 
|  | 1566 | Name = NewOpcode; | 
| Ulrich Weigand | 86247b6 | 2013-06-24 16:52:04 +0000 | [diff] [blame] | 1567 | } | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1568 | if (parseOptionalToken(AsmToken::Minus)) { | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 1569 | NewOpcode = Name; | 
|  | 1570 | NewOpcode += '-'; | 
|  | 1571 | Name = NewOpcode; | 
| Ulrich Weigand | 86247b6 | 2013-06-24 16:52:04 +0000 | [diff] [blame] | 1572 | } | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1573 | // If the instruction ends in a '.', we need to create a separate | 
|  | 1574 | // token for it, to match what TableGen is doing. | 
|  | 1575 | size_t Dot = Name.find('.'); | 
|  | 1576 | StringRef Mnemonic = Name.slice(0, Dot); | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 1577 | if (!NewOpcode.empty()) // Underlying memory for Name is volatile. | 
|  | 1578 | Operands.push_back( | 
|  | 1579 | PPCOperand::CreateTokenWithStringCopy(Mnemonic, NameLoc, isPPC64())); | 
|  | 1580 | else | 
|  | 1581 | Operands.push_back(PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64())); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1582 | if (Dot != StringRef::npos) { | 
|  | 1583 | SMLoc DotLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Dot); | 
|  | 1584 | StringRef DotStr = Name.slice(Dot, StringRef::npos); | 
| Benjamin Kramer | 72d45cc | 2013-08-03 22:43:29 +0000 | [diff] [blame] | 1585 | if (!NewOpcode.empty()) // Underlying memory for Name is volatile. | 
|  | 1586 | Operands.push_back( | 
|  | 1587 | PPCOperand::CreateTokenWithStringCopy(DotStr, DotLoc, isPPC64())); | 
|  | 1588 | else | 
|  | 1589 | Operands.push_back(PPCOperand::CreateToken(DotStr, DotLoc, isPPC64())); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1590 | } | 
|  | 1591 |  | 
|  | 1592 | // If there are no more operands then finish | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1593 | if (parseOptionalToken(AsmToken::EndOfStatement)) | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1594 | return false; | 
|  | 1595 |  | 
|  | 1596 | // Parse the first operand | 
|  | 1597 | if (ParseOperand(Operands)) | 
|  | 1598 | return true; | 
|  | 1599 |  | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1600 | while (!parseOptionalToken(AsmToken::EndOfStatement)) { | 
|  | 1601 | if (parseToken(AsmToken::Comma) || ParseOperand(Operands)) | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1602 | return true; | 
|  | 1603 | } | 
|  | 1604 |  | 
| Hal Finkel | fefcfff | 2015-04-23 22:47:57 +0000 | [diff] [blame] | 1605 | // We'll now deal with an unfortunate special case: the syntax for the dcbt | 
|  | 1606 | // and dcbtst instructions differs for server vs. embedded cores. | 
|  | 1607 | //  The syntax for dcbt is: | 
|  | 1608 | //    dcbt ra, rb, th [server] | 
|  | 1609 | //    dcbt th, ra, rb [embedded] | 
|  | 1610 | //  where th can be omitted when it is 0. dcbtst is the same. We take the | 
|  | 1611 | //  server form to be the default, so swap the operands if we're parsing for | 
|  | 1612 | //  an embedded core (they'll be swapped again upon printing). | 
| Akira Hatanaka | bd9fc28 | 2015-11-14 05:20:05 +0000 | [diff] [blame] | 1613 | if (getSTI().getFeatureBits()[PPC::FeatureBookE] && | 
| Hal Finkel | fefcfff | 2015-04-23 22:47:57 +0000 | [diff] [blame] | 1614 | Operands.size() == 4 && | 
|  | 1615 | (Name == "dcbt" || Name == "dcbtst")) { | 
|  | 1616 | std::swap(Operands[1], Operands[3]); | 
|  | 1617 | std::swap(Operands[2], Operands[1]); | 
|  | 1618 | } | 
|  | 1619 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1620 | return false; | 
|  | 1621 | } | 
|  | 1622 |  | 
|  | 1623 | /// ParseDirective parses the PPC specific directives | 
|  | 1624 | bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) { | 
|  | 1625 | StringRef IDVal = DirectiveID.getIdentifier(); | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1626 | if (isDarwin()) { | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1627 | if (IDVal == ".machine") | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1628 | ParseDarwinDirectiveMachine(DirectiveID.getLoc()); | 
|  | 1629 | else | 
|  | 1630 | return true; | 
|  | 1631 | } else if (IDVal == ".word") | 
|  | 1632 | ParseDirectiveWord(2, DirectiveID); | 
|  | 1633 | else if (IDVal == ".llong") | 
|  | 1634 | ParseDirectiveWord(8, DirectiveID); | 
|  | 1635 | else if (IDVal == ".tc") | 
|  | 1636 | ParseDirectiveTC(isPPC64() ? 8 : 4, DirectiveID); | 
|  | 1637 | else if (IDVal == ".machine") | 
|  | 1638 | ParseDirectiveMachine(DirectiveID.getLoc()); | 
|  | 1639 | else if (IDVal == ".abiversion") | 
|  | 1640 | ParseDirectiveAbiVersion(DirectiveID.getLoc()); | 
|  | 1641 | else if (IDVal == ".localentry") | 
|  | 1642 | ParseDirectiveLocalEntry(DirectiveID.getLoc()); | 
|  | 1643 | else | 
|  | 1644 | return true; | 
|  | 1645 | return false; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1646 | } | 
|  | 1647 |  | 
|  | 1648 | /// ParseDirectiveWord | 
|  | 1649 | ///  ::= .word [ expression (, expression)* ] | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1650 | bool PPCAsmParser::ParseDirectiveWord(unsigned Size, AsmToken ID) { | 
|  | 1651 | auto parseOp = [&]() -> bool { | 
|  | 1652 | const MCExpr *Value; | 
|  | 1653 | SMLoc ExprLoc = getParser().getTok().getLoc(); | 
|  | 1654 | if (getParser().parseExpression(Value)) | 
|  | 1655 | return true; | 
|  | 1656 | if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) { | 
|  | 1657 | assert(Size <= 8 && "Invalid size"); | 
|  | 1658 | uint64_t IntValue = MCE->getValue(); | 
|  | 1659 | if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) | 
|  | 1660 | return Error(ExprLoc, "literal value out of range for '" + | 
|  | 1661 | ID.getIdentifier() + "' directive"); | 
|  | 1662 | getStreamer().EmitIntValue(IntValue, Size); | 
|  | 1663 | } else | 
|  | 1664 | getStreamer().EmitValue(Value, Size, ExprLoc); | 
|  | 1665 | return false; | 
|  | 1666 | }; | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1667 |  | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1668 | if (parseMany(parseOp)) | 
|  | 1669 | return addErrorSuffix(" in '" + ID.getIdentifier() + "' directive"); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1670 | return false; | 
|  | 1671 | } | 
|  | 1672 |  | 
|  | 1673 | /// ParseDirectiveTC | 
|  | 1674 | ///  ::= .tc [ symbol (, expression)* ] | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1675 | bool PPCAsmParser::ParseDirectiveTC(unsigned Size, AsmToken ID) { | 
| Rafael Espindola | 961d469 | 2014-11-11 05:18:41 +0000 | [diff] [blame] | 1676 | MCAsmParser &Parser = getParser(); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1677 | // Skip TC symbol, which is only used with XCOFF. | 
|  | 1678 | while (getLexer().isNot(AsmToken::EndOfStatement) | 
|  | 1679 | && getLexer().isNot(AsmToken::Comma)) | 
|  | 1680 | Parser.Lex(); | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1681 | if (parseToken(AsmToken::Comma)) | 
|  | 1682 | return addErrorSuffix(" in '.tc' directive"); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1683 |  | 
|  | 1684 | // Align to word size. | 
|  | 1685 | getParser().getStreamer().EmitValueToAlignment(Size); | 
|  | 1686 |  | 
|  | 1687 | // Emit expressions. | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1688 | return ParseDirectiveWord(Size, ID); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1689 | } | 
|  | 1690 |  | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1691 | /// ParseDirectiveMachine (ELF platforms) | 
| Ulrich Weigand | 55daa77 | 2013-07-09 10:00:34 +0000 | [diff] [blame] | 1692 | ///  ::= .machine [ cpu | "push" | "pop" ] | 
|  | 1693 | bool PPCAsmParser::ParseDirectiveMachine(SMLoc L) { | 
| Rafael Espindola | 961d469 | 2014-11-11 05:18:41 +0000 | [diff] [blame] | 1694 | MCAsmParser &Parser = getParser(); | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1695 | if (Parser.getTok().isNot(AsmToken::Identifier) && | 
|  | 1696 | Parser.getTok().isNot(AsmToken::String)) | 
|  | 1697 | return Error(L, "unexpected token in '.machine' directive"); | 
| Ulrich Weigand | 55daa77 | 2013-07-09 10:00:34 +0000 | [diff] [blame] | 1698 |  | 
|  | 1699 | StringRef CPU = Parser.getTok().getIdentifier(); | 
| Ulrich Weigand | 55daa77 | 2013-07-09 10:00:34 +0000 | [diff] [blame] | 1700 |  | 
|  | 1701 | // FIXME: Right now, the parser always allows any available | 
|  | 1702 | // instruction, so the .machine directive is not useful. | 
|  | 1703 | // Implement ".machine any" (by doing nothing) for the benefit | 
|  | 1704 | // of existing assembler code.  Likewise, we can then implement | 
|  | 1705 | // ".machine push" and ".machine pop" as no-op. | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1706 | if (CPU != "any" && CPU != "push" && CPU != "pop") | 
|  | 1707 | return TokError("unrecognized machine type"); | 
| Ulrich Weigand | 55daa77 | 2013-07-09 10:00:34 +0000 | [diff] [blame] | 1708 |  | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1709 | Parser.Lex(); | 
|  | 1710 |  | 
|  | 1711 | if (parseToken(AsmToken::EndOfStatement)) | 
|  | 1712 | return addErrorSuffix(" in '.machine' directive"); | 
|  | 1713 |  | 
| Rafael Espindola | 6b9ee9b | 2014-01-25 02:35:56 +0000 | [diff] [blame] | 1714 | PPCTargetStreamer &TStreamer = | 
|  | 1715 | *static_cast<PPCTargetStreamer *>( | 
|  | 1716 | getParser().getStreamer().getTargetStreamer()); | 
|  | 1717 | TStreamer.emitMachine(CPU); | 
| Ulrich Weigand | 55daa77 | 2013-07-09 10:00:34 +0000 | [diff] [blame] | 1718 |  | 
|  | 1719 | return false; | 
|  | 1720 | } | 
|  | 1721 |  | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1722 | /// ParseDarwinDirectiveMachine (Mach-o platforms) | 
|  | 1723 | ///  ::= .machine cpu-identifier | 
|  | 1724 | bool PPCAsmParser::ParseDarwinDirectiveMachine(SMLoc L) { | 
| Rafael Espindola | 961d469 | 2014-11-11 05:18:41 +0000 | [diff] [blame] | 1725 | MCAsmParser &Parser = getParser(); | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1726 | if (Parser.getTok().isNot(AsmToken::Identifier) && | 
|  | 1727 | Parser.getTok().isNot(AsmToken::String)) | 
|  | 1728 | return Error(L, "unexpected token in directive"); | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1729 |  | 
|  | 1730 | StringRef CPU = Parser.getTok().getIdentifier(); | 
|  | 1731 | Parser.Lex(); | 
|  | 1732 |  | 
|  | 1733 | // FIXME: this is only the 'default' set of cpu variants. | 
|  | 1734 | // However we don't act on this information at present, this is simply | 
|  | 1735 | // allowing parsing to proceed with minimal sanity checking. | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1736 | if (check(CPU != "ppc7400" && CPU != "ppc" && CPU != "ppc64", L, | 
|  | 1737 | "unrecognized cpu type") || | 
|  | 1738 | check(isPPC64() && (CPU == "ppc7400" || CPU == "ppc"), L, | 
|  | 1739 | "wrong cpu type specified for 64bit") || | 
|  | 1740 | check(!isPPC64() && CPU == "ppc64", L, | 
|  | 1741 | "wrong cpu type specified for 32bit") || | 
|  | 1742 | parseToken(AsmToken::EndOfStatement)) | 
|  | 1743 | return addErrorSuffix(" in '.machine' directive"); | 
| Iain Sandoe | e0b4cb6 | 2013-12-14 13:34:02 +0000 | [diff] [blame] | 1744 | return false; | 
|  | 1745 | } | 
|  | 1746 |  | 
| Ulrich Weigand | 0daa516 | 2014-07-20 22:56:57 +0000 | [diff] [blame] | 1747 | /// ParseDirectiveAbiVersion | 
|  | 1748 | ///  ::= .abiversion constant-expression | 
|  | 1749 | bool PPCAsmParser::ParseDirectiveAbiVersion(SMLoc L) { | 
|  | 1750 | int64_t AbiVersion; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1751 | if (check(getParser().parseAbsoluteExpression(AbiVersion), L, | 
|  | 1752 | "expected constant expression") || | 
|  | 1753 | parseToken(AsmToken::EndOfStatement)) | 
|  | 1754 | return addErrorSuffix(" in '.abiversion' directive"); | 
| Ulrich Weigand | 0daa516 | 2014-07-20 22:56:57 +0000 | [diff] [blame] | 1755 |  | 
|  | 1756 | PPCTargetStreamer &TStreamer = | 
|  | 1757 | *static_cast<PPCTargetStreamer *>( | 
|  | 1758 | getParser().getStreamer().getTargetStreamer()); | 
|  | 1759 | TStreamer.emitAbiVersion(AbiVersion); | 
|  | 1760 |  | 
|  | 1761 | return false; | 
|  | 1762 | } | 
|  | 1763 |  | 
| Ulrich Weigand | bb68610 | 2014-07-20 23:06:03 +0000 | [diff] [blame] | 1764 | /// ParseDirectiveLocalEntry | 
|  | 1765 | ///  ::= .localentry symbol, expression | 
|  | 1766 | bool PPCAsmParser::ParseDirectiveLocalEntry(SMLoc L) { | 
|  | 1767 | StringRef Name; | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1768 | if (getParser().parseIdentifier(Name)) | 
|  | 1769 | return Error(L, "expected identifier in '.localentry' directive"); | 
|  | 1770 |  | 
| Rafael Espindola | 95fb9b9 | 2015-06-02 20:38:46 +0000 | [diff] [blame] | 1771 | MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name)); | 
| Ulrich Weigand | bb68610 | 2014-07-20 23:06:03 +0000 | [diff] [blame] | 1772 | const MCExpr *Expr; | 
| Ulrich Weigand | bb68610 | 2014-07-20 23:06:03 +0000 | [diff] [blame] | 1773 |  | 
| Nirav Dave | d6642c1 | 2016-12-05 14:11:03 +0000 | [diff] [blame] | 1774 | if (parseToken(AsmToken::Comma) || | 
|  | 1775 | check(getParser().parseExpression(Expr), L, "expected expression") || | 
|  | 1776 | parseToken(AsmToken::EndOfStatement)) | 
|  | 1777 | return addErrorSuffix(" in '.localentry' directive"); | 
| Ulrich Weigand | bb68610 | 2014-07-20 23:06:03 +0000 | [diff] [blame] | 1778 |  | 
|  | 1779 | PPCTargetStreamer &TStreamer = | 
|  | 1780 | *static_cast<PPCTargetStreamer *>( | 
|  | 1781 | getParser().getStreamer().getTargetStreamer()); | 
|  | 1782 | TStreamer.emitLocalEntry(Sym, Expr); | 
|  | 1783 |  | 
|  | 1784 | return false; | 
|  | 1785 | } | 
|  | 1786 |  | 
|  | 1787 |  | 
|  | 1788 |  | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1789 | /// Force static initialization. | 
|  | 1790 | extern "C" void LLVMInitializePowerPCAsmParser() { | 
| Mehdi Amini | f42454b | 2016-10-09 23:00:34 +0000 | [diff] [blame] | 1791 | RegisterMCAsmParser<PPCAsmParser> A(getThePPC32Target()); | 
|  | 1792 | RegisterMCAsmParser<PPCAsmParser> B(getThePPC64Target()); | 
|  | 1793 | RegisterMCAsmParser<PPCAsmParser> C(getThePPC64LETarget()); | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1794 | } | 
|  | 1795 |  | 
|  | 1796 | #define GET_REGISTER_MATCHER | 
|  | 1797 | #define GET_MATCHER_IMPLEMENTATION | 
| Hal Finkel | e86a8b7 | 2017-12-16 02:42:18 +0000 | [diff] [blame] | 1798 | #define GET_MNEMONIC_SPELL_CHECKER | 
| Ulrich Weigand | 640192d | 2013-05-03 19:49:39 +0000 | [diff] [blame] | 1799 | #include "PPCGenAsmMatcher.inc" | 
| Ulrich Weigand | c0944b5 | 2013-07-08 14:49:37 +0000 | [diff] [blame] | 1800 |  | 
|  | 1801 | // Define this matcher function after the auto-generated include so we | 
|  | 1802 | // have the match class enum definitions. | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1803 | unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, | 
| Ulrich Weigand | c0944b5 | 2013-07-08 14:49:37 +0000 | [diff] [blame] | 1804 | unsigned Kind) { | 
|  | 1805 | // If the kind is a token for a literal immediate, check if our asm | 
|  | 1806 | // operand matches. This is for InstAliases which have a fixed-value | 
|  | 1807 | // immediate in the syntax. | 
|  | 1808 | int64_t ImmVal; | 
|  | 1809 | switch (Kind) { | 
|  | 1810 | case MCK_0: ImmVal = 0; break; | 
|  | 1811 | case MCK_1: ImmVal = 1; break; | 
| Roman Divacky | 62cb635 | 2013-09-12 17:50:54 +0000 | [diff] [blame] | 1812 | case MCK_2: ImmVal = 2; break; | 
|  | 1813 | case MCK_3: ImmVal = 3; break; | 
| Joerg Sonnenberger | dda8e78 | 2014-07-30 09:24:37 +0000 | [diff] [blame] | 1814 | case MCK_4: ImmVal = 4; break; | 
|  | 1815 | case MCK_5: ImmVal = 5; break; | 
|  | 1816 | case MCK_6: ImmVal = 6; break; | 
|  | 1817 | case MCK_7: ImmVal = 7; break; | 
| Ulrich Weigand | c0944b5 | 2013-07-08 14:49:37 +0000 | [diff] [blame] | 1818 | default: return Match_InvalidOperand; | 
|  | 1819 | } | 
|  | 1820 |  | 
| David Blaikie | 960ea3f | 2014-06-08 16:18:35 +0000 | [diff] [blame] | 1821 | PPCOperand &Op = static_cast<PPCOperand &>(AsmOp); | 
|  | 1822 | if (Op.isImm() && Op.getImm() == ImmVal) | 
| Ulrich Weigand | c0944b5 | 2013-07-08 14:49:37 +0000 | [diff] [blame] | 1823 | return Match_Success; | 
|  | 1824 |  | 
|  | 1825 | return Match_InvalidOperand; | 
|  | 1826 | } | 
|  | 1827 |  | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1828 | const MCExpr * | 
|  | 1829 | PPCAsmParser::applyModifierToExpr(const MCExpr *E, | 
|  | 1830 | MCSymbolRefExpr::VariantKind Variant, | 
|  | 1831 | MCContext &Ctx) { | 
|  | 1832 | switch (Variant) { | 
|  | 1833 | case MCSymbolRefExpr::VK_PPC_LO: | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1834 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_LO, E, false, Ctx); | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1835 | case MCSymbolRefExpr::VK_PPC_HI: | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1836 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HI, E, false, Ctx); | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1837 | case MCSymbolRefExpr::VK_PPC_HA: | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1838 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HA, E, false, Ctx); | 
| Sean Fertile | 80b8f82 | 2018-06-15 19:47:11 +0000 | [diff] [blame] | 1839 | case MCSymbolRefExpr::VK_PPC_HIGH: | 
|  | 1840 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGH, E, false, Ctx); | 
|  | 1841 | case MCSymbolRefExpr::VK_PPC_HIGHA: | 
|  | 1842 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHA, E, false, Ctx); | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1843 | case MCSymbolRefExpr::VK_PPC_HIGHER: | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1844 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHER, E, false, Ctx); | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1845 | case MCSymbolRefExpr::VK_PPC_HIGHERA: | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1846 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHERA, E, false, Ctx); | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1847 | case MCSymbolRefExpr::VK_PPC_HIGHEST: | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1848 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHEST, E, false, Ctx); | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1849 | case MCSymbolRefExpr::VK_PPC_HIGHESTA: | 
| Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 1850 | return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHESTA, E, false, Ctx); | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1851 | default: | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 1852 | return nullptr; | 
| Joerg Sonnenberger | b822af4 | 2013-08-27 20:23:19 +0000 | [diff] [blame] | 1853 | } | 
|  | 1854 | } |