1 | //===-- PPCAsmParser.cpp - Parse PowerPC asm to MCInst instructions -------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "MCTargetDesc/PPCMCAsmInfo.h" |
10 | #include "MCTargetDesc/PPCMCTargetDesc.h" |
11 | #include "MCTargetDesc/PPCTargetStreamer.h" |
12 | #include "PPCInstrInfo.h" |
13 | #include "TargetInfo/PowerPCTargetInfo.h" |
14 | #include "llvm/ADT/Twine.h" |
15 | #include "llvm/MC/MCContext.h" |
16 | #include "llvm/MC/MCExpr.h" |
17 | #include "llvm/MC/MCInst.h" |
18 | #include "llvm/MC/MCInstrInfo.h" |
19 | #include "llvm/MC/MCParser/AsmLexer.h" |
20 | #include "llvm/MC/MCParser/MCAsmParser.h" |
21 | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
22 | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
23 | #include "llvm/MC/MCStreamer.h" |
24 | #include "llvm/MC/MCSubtargetInfo.h" |
25 | #include "llvm/MC/MCSymbolELF.h" |
26 | #include "llvm/MC/TargetRegistry.h" |
27 | #include "llvm/Support/Compiler.h" |
28 | #include "llvm/Support/SourceMgr.h" |
29 | #include "llvm/Support/raw_ostream.h" |
30 | |
31 | using namespace llvm; |
32 | |
33 | DEFINE_PPC_REGCLASSES |
34 | |
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::Constant: { |
42 | int64_t Res = cast<MCConstantExpr>(Val: E)->getValue(); |
43 | return Res < 0 ? -1 : Res; |
44 | } |
45 | |
46 | case MCExpr::SymbolRef: { |
47 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: E); |
48 | StringRef Name = SRE->getSymbol().getName(); |
49 | |
50 | if (Name == "lt" ) return 0; |
51 | if (Name == "gt" ) return 1; |
52 | if (Name == "eq" ) return 2; |
53 | if (Name == "so" ) return 3; |
54 | if (Name == "un" ) return 3; |
55 | |
56 | if (Name == "cr0" ) return 0; |
57 | if (Name == "cr1" ) return 1; |
58 | if (Name == "cr2" ) return 2; |
59 | if (Name == "cr3" ) return 3; |
60 | if (Name == "cr4" ) return 4; |
61 | if (Name == "cr5" ) return 5; |
62 | if (Name == "cr6" ) return 6; |
63 | if (Name == "cr7" ) return 7; |
64 | |
65 | return -1; |
66 | } |
67 | |
68 | case MCExpr::Unary: |
69 | return -1; |
70 | |
71 | case MCExpr::Binary: { |
72 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: E); |
73 | int64_t LHSVal = EvaluateCRExpr(E: BE->getLHS()); |
74 | int64_t RHSVal = EvaluateCRExpr(E: BE->getRHS()); |
75 | int64_t Res; |
76 | |
77 | if (LHSVal < 0 || RHSVal < 0) |
78 | return -1; |
79 | |
80 | switch (BE->getOpcode()) { |
81 | default: return -1; |
82 | case MCBinaryExpr::Add: Res = LHSVal + RHSVal; break; |
83 | case MCBinaryExpr::Mul: Res = LHSVal * RHSVal; break; |
84 | } |
85 | |
86 | return Res < 0 ? -1 : Res; |
87 | } |
88 | case MCExpr::Specifier: |
89 | return -1; |
90 | case MCExpr::Target: |
91 | llvm_unreachable("unused by this backend" ); |
92 | } |
93 | |
94 | llvm_unreachable("Invalid expression kind!" ); |
95 | } |
96 | |
97 | namespace { |
98 | |
99 | struct PPCOperand; |
100 | |
101 | class PPCAsmParser : public MCTargetAsmParser { |
102 | const bool IsPPC64; |
103 | |
104 | void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); } |
105 | |
106 | bool isPPC64() const { return IsPPC64; } |
107 | |
108 | MCRegister matchRegisterName(int64_t &IntVal); |
109 | |
110 | bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; |
111 | ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, |
112 | SMLoc &EndLoc) override; |
113 | |
114 | const MCExpr *extractSpecifier(const MCExpr *E, |
115 | PPCMCExpr::Specifier &Variant); |
116 | bool parseExpression(const MCExpr *&EVal); |
117 | |
118 | bool parseOperand(OperandVector &Operands); |
119 | |
120 | bool parseDirectiveWord(unsigned Size, AsmToken ID); |
121 | bool parseDirectiveTC(unsigned Size, AsmToken ID); |
122 | bool parseDirectiveMachine(SMLoc L); |
123 | bool parseDirectiveAbiVersion(SMLoc L); |
124 | bool parseDirectiveLocalEntry(SMLoc L); |
125 | bool parseGNUAttribute(SMLoc L); |
126 | |
127 | bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
128 | OperandVector &Operands, MCStreamer &Out, |
129 | uint64_t &ErrorInfo, |
130 | bool MatchingInlineAsm) override; |
131 | |
132 | void processInstruction(MCInst &Inst, const OperandVector &Ops); |
133 | |
134 | /// @name Auto-generated Match Functions |
135 | /// { |
136 | |
137 | #define |
138 | #include "PPCGenAsmMatcher.inc" |
139 | |
140 | /// } |
141 | |
142 | |
143 | public: |
144 | PPCAsmParser(const MCSubtargetInfo &STI, MCAsmParser &, |
145 | const MCInstrInfo &MII, const MCTargetOptions &Options) |
146 | : MCTargetAsmParser(Options, STI, MII), |
147 | IsPPC64(STI.getTargetTriple().isPPC64()) { |
148 | // Initialize the set of available features. |
149 | setAvailableFeatures(ComputeAvailableFeatures(FB: STI.getFeatureBits())); |
150 | } |
151 | |
152 | bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, |
153 | SMLoc NameLoc, OperandVector &Operands) override; |
154 | |
155 | bool ParseDirective(AsmToken DirectiveID) override; |
156 | |
157 | unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, |
158 | unsigned Kind) override; |
159 | |
160 | const MCExpr *applySpecifier(const MCExpr *E, uint32_t, |
161 | MCContext &Ctx) override; |
162 | }; |
163 | |
164 | /// PPCOperand - Instances of this class represent a parsed PowerPC machine |
165 | /// instruction. |
166 | struct PPCOperand : public MCParsedAsmOperand { |
167 | enum KindTy { |
168 | Token, |
169 | Immediate, |
170 | ContextImmediate, |
171 | Expression, |
172 | TLSRegister |
173 | } Kind; |
174 | |
175 | SMLoc StartLoc, EndLoc; |
176 | bool IsPPC64; |
177 | |
178 | struct TokOp { |
179 | const char *Data; |
180 | unsigned Length; |
181 | }; |
182 | |
183 | struct ImmOp { |
184 | int64_t Val; |
185 | bool IsMemOpBase; |
186 | }; |
187 | |
188 | struct ExprOp { |
189 | const MCExpr *Val; |
190 | int64_t CRVal; // Cached result of EvaluateCRExpr(Val) |
191 | }; |
192 | |
193 | struct TLSRegOp { |
194 | const MCSymbolRefExpr *Sym; |
195 | }; |
196 | |
197 | union { |
198 | struct TokOp Tok; |
199 | struct ImmOp Imm; |
200 | struct ExprOp Expr; |
201 | struct TLSRegOp TLSReg; |
202 | }; |
203 | |
204 | PPCOperand(KindTy K) : Kind(K) {} |
205 | |
206 | public: |
207 | PPCOperand(const PPCOperand &o) : MCParsedAsmOperand() { |
208 | Kind = o.Kind; |
209 | StartLoc = o.StartLoc; |
210 | EndLoc = o.EndLoc; |
211 | IsPPC64 = o.IsPPC64; |
212 | switch (Kind) { |
213 | case Token: |
214 | Tok = o.Tok; |
215 | break; |
216 | case Immediate: |
217 | case ContextImmediate: |
218 | Imm = o.Imm; |
219 | break; |
220 | case Expression: |
221 | Expr = o.Expr; |
222 | break; |
223 | case TLSRegister: |
224 | TLSReg = o.TLSReg; |
225 | break; |
226 | } |
227 | } |
228 | |
229 | // Disable use of sized deallocation due to overallocation of PPCOperand |
230 | // objects in CreateTokenWithStringCopy. |
231 | void operator delete(void *p) { ::operator delete(p); } |
232 | |
233 | /// getStartLoc - Get the location of the first token of this operand. |
234 | SMLoc getStartLoc() const override { return StartLoc; } |
235 | |
236 | /// getEndLoc - Get the location of the last token of this operand. |
237 | SMLoc getEndLoc() const override { return EndLoc; } |
238 | |
239 | /// getLocRange - Get the range between the first and last token of this |
240 | /// operand. |
241 | SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } |
242 | |
243 | /// isPPC64 - True if this operand is for an instruction in 64-bit mode. |
244 | bool isPPC64() const { return IsPPC64; } |
245 | |
246 | /// isMemOpBase - True if this operand is the base of a memory operand. |
247 | bool isMemOpBase() const { return Kind == Immediate && Imm.IsMemOpBase; } |
248 | |
249 | int64_t getImm() const { |
250 | assert(Kind == Immediate && "Invalid access!" ); |
251 | return Imm.Val; |
252 | } |
253 | int64_t getImmS16Context() const { |
254 | assert((Kind == Immediate || Kind == ContextImmediate) && |
255 | "Invalid access!" ); |
256 | if (Kind == Immediate) |
257 | return Imm.Val; |
258 | return static_cast<int16_t>(Imm.Val); |
259 | } |
260 | int64_t getImmU16Context() const { |
261 | assert((Kind == Immediate || Kind == ContextImmediate) && |
262 | "Invalid access!" ); |
263 | return Imm.Val; |
264 | } |
265 | |
266 | const MCExpr *getExpr() const { |
267 | assert(Kind == Expression && "Invalid access!" ); |
268 | return Expr.Val; |
269 | } |
270 | |
271 | int64_t getExprCRVal() const { |
272 | assert(Kind == Expression && "Invalid access!" ); |
273 | return Expr.CRVal; |
274 | } |
275 | |
276 | const MCExpr *getTLSReg() const { |
277 | assert(Kind == TLSRegister && "Invalid access!" ); |
278 | return TLSReg.Sym; |
279 | } |
280 | |
281 | MCRegister getReg() const override { llvm_unreachable("Not implemented" ); } |
282 | |
283 | unsigned getRegNum() const { |
284 | assert(isRegNumber() && "Invalid access!" ); |
285 | return (unsigned)Imm.Val; |
286 | } |
287 | |
288 | unsigned getFpReg() const { |
289 | assert(isEvenRegNumber() && "Invalid access!" ); |
290 | return (unsigned)(Imm.Val >> 1); |
291 | } |
292 | |
293 | unsigned getVSReg() const { |
294 | assert(isVSRegNumber() && "Invalid access!" ); |
295 | return (unsigned) Imm.Val; |
296 | } |
297 | |
298 | unsigned getACCReg() const { |
299 | assert(isACCRegNumber() && "Invalid access!" ); |
300 | return (unsigned) Imm.Val; |
301 | } |
302 | |
303 | unsigned getDMRROWReg() const { |
304 | assert(isDMRROWRegNumber() && "Invalid access!" ); |
305 | return (unsigned)Imm.Val; |
306 | } |
307 | |
308 | unsigned getDMRROWpReg() const { |
309 | assert(isDMRROWpRegNumber() && "Invalid access!" ); |
310 | return (unsigned)Imm.Val; |
311 | } |
312 | |
313 | unsigned getDMRReg() const { |
314 | assert(isDMRRegNumber() && "Invalid access!" ); |
315 | return (unsigned)Imm.Val; |
316 | } |
317 | |
318 | unsigned getDMRpReg() const { |
319 | assert(isDMRpRegNumber() && "Invalid access!" ); |
320 | return (unsigned)Imm.Val; |
321 | } |
322 | |
323 | unsigned getVSRpEvenReg() const { |
324 | assert(isVSRpEvenRegNumber() && "Invalid access!" ); |
325 | return (unsigned) Imm.Val >> 1; |
326 | } |
327 | |
328 | unsigned getG8pReg() const { |
329 | assert(isEvenRegNumber() && "Invalid access!" ); |
330 | return (unsigned)Imm.Val; |
331 | } |
332 | |
333 | unsigned getCCReg() const { |
334 | assert(isCCRegNumber() && "Invalid access!" ); |
335 | return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); |
336 | } |
337 | |
338 | unsigned getCRBit() const { |
339 | assert(isCRBitNumber() && "Invalid access!" ); |
340 | return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); |
341 | } |
342 | |
343 | unsigned getCRBitMask() const { |
344 | assert(isCRBitMask() && "Invalid access!" ); |
345 | return 7 - llvm::countr_zero<uint64_t>(Val: Imm.Val); |
346 | } |
347 | |
348 | bool isToken() const override { return Kind == Token; } |
349 | bool isImm() const override { |
350 | return Kind == Immediate || Kind == Expression; |
351 | } |
352 | bool isU1Imm() const { return Kind == Immediate && isUInt<1>(x: getImm()); } |
353 | bool isU2Imm() const { return Kind == Immediate && isUInt<2>(x: getImm()); } |
354 | bool isU3Imm() const { return Kind == Immediate && isUInt<3>(x: getImm()); } |
355 | bool isU4Imm() const { return Kind == Immediate && isUInt<4>(x: getImm()); } |
356 | bool isU5Imm() const { return Kind == Immediate && isUInt<5>(x: getImm()); } |
357 | bool isS5Imm() const { return Kind == Immediate && isInt<5>(x: getImm()); } |
358 | bool isU6Imm() const { return Kind == Immediate && isUInt<6>(x: getImm()); } |
359 | bool isU6ImmX2() const { return Kind == Immediate && |
360 | isUInt<6>(x: getImm()) && |
361 | (getImm() & 1) == 0; } |
362 | bool isU7Imm() const { return Kind == Immediate && isUInt<7>(x: getImm()); } |
363 | bool isU7ImmX4() const { return Kind == Immediate && |
364 | isUInt<7>(x: getImm()) && |
365 | (getImm() & 3) == 0; } |
366 | bool isU8Imm() const { return Kind == Immediate && isUInt<8>(x: getImm()); } |
367 | bool isU8ImmX8() const { return Kind == Immediate && |
368 | isUInt<8>(x: getImm()) && |
369 | (getImm() & 7) == 0; } |
370 | |
371 | bool isU10Imm() const { return Kind == Immediate && isUInt<10>(x: getImm()); } |
372 | bool isU12Imm() const { return Kind == Immediate && isUInt<12>(x: getImm()); } |
373 | bool isU16Imm() const { return isExtImm<16>(/*Signed*/ false, Multiple: 1); } |
374 | bool isS16Imm() const { return isExtImm<16>(/*Signed*/ true, Multiple: 1); } |
375 | bool isS16ImmX4() const { return isExtImm<16>(/*Signed*/ true, Multiple: 4); } |
376 | bool isS16ImmX16() const { return isExtImm<16>(/*Signed*/ true, Multiple: 16); } |
377 | bool isS17Imm() const { return isExtImm<17>(/*Signed*/ true, Multiple: 1); } |
378 | |
379 | bool isHashImmX8() const { |
380 | // The Hash Imm form is used for instructions that check or store a hash. |
381 | // These instructions have a small immediate range that spans between |
382 | // -8 and -512. |
383 | return (Kind == Immediate && getImm() <= -8 && getImm() >= -512 && |
384 | (getImm() & 7) == 0); |
385 | } |
386 | |
387 | bool isS34ImmX16() const { |
388 | return Kind == Expression || |
389 | (Kind == Immediate && isInt<34>(x: getImm()) && (getImm() & 15) == 0); |
390 | } |
391 | bool isS34Imm() const { |
392 | // Once the PC-Rel ABI is finalized, evaluate whether a 34-bit |
393 | // ContextImmediate is needed. |
394 | return Kind == Expression || (Kind == Immediate && isInt<34>(x: getImm())); |
395 | } |
396 | |
397 | bool isTLSReg() const { return Kind == TLSRegister; } |
398 | bool isDirectBr() const { |
399 | if (Kind == Expression) |
400 | return true; |
401 | if (Kind != Immediate) |
402 | return false; |
403 | // Operand must be 64-bit aligned, signed 27-bit immediate. |
404 | if ((getImm() & 3) != 0) |
405 | return false; |
406 | if (isInt<26>(x: getImm())) |
407 | return true; |
408 | if (!IsPPC64) { |
409 | // In 32-bit mode, large 32-bit quantities wrap around. |
410 | if (isUInt<32>(x: getImm()) && isInt<26>(x: static_cast<int32_t>(getImm()))) |
411 | return true; |
412 | } |
413 | return false; |
414 | } |
415 | bool isCondBr() const { return Kind == Expression || |
416 | (Kind == Immediate && isInt<16>(x: getImm()) && |
417 | (getImm() & 3) == 0); } |
418 | bool isImmZero() const { return Kind == Immediate && getImm() == 0; } |
419 | bool isRegNumber() const { return Kind == Immediate && isUInt<5>(x: getImm()); } |
420 | bool isACCRegNumber() const { |
421 | return Kind == Immediate && isUInt<3>(x: getImm()); |
422 | } |
423 | bool isDMRROWRegNumber() const { |
424 | return Kind == Immediate && isUInt<6>(x: getImm()); |
425 | } |
426 | bool isDMRROWpRegNumber() const { |
427 | return Kind == Immediate && isUInt<5>(x: getImm()); |
428 | } |
429 | bool isDMRRegNumber() const { |
430 | return Kind == Immediate && isUInt<3>(x: getImm()); |
431 | } |
432 | bool isDMRpRegNumber() const { |
433 | return Kind == Immediate && isUInt<2>(x: getImm()); |
434 | } |
435 | bool isVSRpEvenRegNumber() const { |
436 | return Kind == Immediate && isUInt<6>(x: getImm()) && ((getImm() & 1) == 0); |
437 | } |
438 | bool isVSRegNumber() const { |
439 | return Kind == Immediate && isUInt<6>(x: getImm()); |
440 | } |
441 | bool isCCRegNumber() const { return (Kind == Expression |
442 | && isUInt<3>(x: getExprCRVal())) || |
443 | (Kind == Immediate |
444 | && isUInt<3>(x: getImm())); } |
445 | bool isCRBitNumber() const { return (Kind == Expression |
446 | && isUInt<5>(x: getExprCRVal())) || |
447 | (Kind == Immediate |
448 | && isUInt<5>(x: getImm())); } |
449 | |
450 | bool isEvenRegNumber() const { return isRegNumber() && (getImm() & 1) == 0; } |
451 | |
452 | bool isCRBitMask() const { |
453 | return Kind == Immediate && isUInt<8>(x: getImm()) && |
454 | llvm::has_single_bit<uint32_t>(Value: getImm()); |
455 | } |
456 | bool isATBitsAsHint() const { return false; } |
457 | bool isMem() const override { return false; } |
458 | bool isReg() const override { return false; } |
459 | |
460 | void addRegOperands(MCInst &Inst, unsigned N) const { |
461 | llvm_unreachable("addRegOperands" ); |
462 | } |
463 | |
464 | void addRegGPRCOperands(MCInst &Inst, unsigned N) const { |
465 | assert(N == 1 && "Invalid number of operands!" ); |
466 | Inst.addOperand(Op: MCOperand::createReg(Reg: RRegs[getRegNum()])); |
467 | } |
468 | |
469 | void addRegGPRCNoR0Operands(MCInst &Inst, unsigned N) const { |
470 | assert(N == 1 && "Invalid number of operands!" ); |
471 | Inst.addOperand(Op: MCOperand::createReg(Reg: RRegsNoR0[getRegNum()])); |
472 | } |
473 | |
474 | void addRegG8RCOperands(MCInst &Inst, unsigned N) const { |
475 | assert(N == 1 && "Invalid number of operands!" ); |
476 | Inst.addOperand(Op: MCOperand::createReg(Reg: XRegs[getRegNum()])); |
477 | } |
478 | |
479 | void addRegG8RCNoX0Operands(MCInst &Inst, unsigned N) const { |
480 | assert(N == 1 && "Invalid number of operands!" ); |
481 | Inst.addOperand(Op: MCOperand::createReg(Reg: XRegsNoX0[getRegNum()])); |
482 | } |
483 | |
484 | void addRegG8pRCOperands(MCInst &Inst, unsigned N) const { |
485 | assert(N == 1 && "Invalid number of operands!" ); |
486 | Inst.addOperand(Op: MCOperand::createReg(Reg: XRegs[getG8pReg()])); |
487 | } |
488 | |
489 | void addRegGxRCOperands(MCInst &Inst, unsigned N) const { |
490 | if (isPPC64()) |
491 | addRegG8RCOperands(Inst, N); |
492 | else |
493 | addRegGPRCOperands(Inst, N); |
494 | } |
495 | |
496 | void addRegGxRCNoR0Operands(MCInst &Inst, unsigned N) const { |
497 | if (isPPC64()) |
498 | addRegG8RCNoX0Operands(Inst, N); |
499 | else |
500 | addRegGPRCNoR0Operands(Inst, N); |
501 | } |
502 | |
503 | void addRegF4RCOperands(MCInst &Inst, unsigned N) const { |
504 | assert(N == 1 && "Invalid number of operands!" ); |
505 | Inst.addOperand(Op: MCOperand::createReg(Reg: FRegs[getRegNum()])); |
506 | } |
507 | |
508 | void addRegF8RCOperands(MCInst &Inst, unsigned N) const { |
509 | assert(N == 1 && "Invalid number of operands!" ); |
510 | Inst.addOperand(Op: MCOperand::createReg(Reg: FRegs[getRegNum()])); |
511 | } |
512 | |
513 | void addRegFpRCOperands(MCInst &Inst, unsigned N) const { |
514 | assert(N == 1 && "Invalid number of operands!" ); |
515 | Inst.addOperand(Op: MCOperand::createReg(Reg: FpRegs[getFpReg()])); |
516 | } |
517 | |
518 | void addRegVFRCOperands(MCInst &Inst, unsigned N) const { |
519 | assert(N == 1 && "Invalid number of operands!" ); |
520 | Inst.addOperand(Op: MCOperand::createReg(Reg: VFRegs[getRegNum()])); |
521 | } |
522 | |
523 | void addRegVRRCOperands(MCInst &Inst, unsigned N) const { |
524 | assert(N == 1 && "Invalid number of operands!" ); |
525 | Inst.addOperand(Op: MCOperand::createReg(Reg: VRegs[getRegNum()])); |
526 | } |
527 | |
528 | void addRegVSRCOperands(MCInst &Inst, unsigned N) const { |
529 | assert(N == 1 && "Invalid number of operands!" ); |
530 | Inst.addOperand(Op: MCOperand::createReg(Reg: VSRegs[getVSReg()])); |
531 | } |
532 | |
533 | void addRegVSFRCOperands(MCInst &Inst, unsigned N) const { |
534 | assert(N == 1 && "Invalid number of operands!" ); |
535 | Inst.addOperand(Op: MCOperand::createReg(Reg: VSFRegs[getVSReg()])); |
536 | } |
537 | |
538 | void addRegVSSRCOperands(MCInst &Inst, unsigned N) const { |
539 | assert(N == 1 && "Invalid number of operands!" ); |
540 | Inst.addOperand(Op: MCOperand::createReg(Reg: VSSRegs[getVSReg()])); |
541 | } |
542 | |
543 | void addRegSPE4RCOperands(MCInst &Inst, unsigned N) const { |
544 | assert(N == 1 && "Invalid number of operands!" ); |
545 | Inst.addOperand(Op: MCOperand::createReg(Reg: RRegs[getRegNum()])); |
546 | } |
547 | |
548 | void addRegSPERCOperands(MCInst &Inst, unsigned N) const { |
549 | assert(N == 1 && "Invalid number of operands!" ); |
550 | Inst.addOperand(Op: MCOperand::createReg(Reg: SPERegs[getRegNum()])); |
551 | } |
552 | |
553 | void addRegACCRCOperands(MCInst &Inst, unsigned N) const { |
554 | assert(N == 1 && "Invalid number of operands!" ); |
555 | Inst.addOperand(Op: MCOperand::createReg(Reg: ACCRegs[getACCReg()])); |
556 | } |
557 | |
558 | void addRegDMRROWRCOperands(MCInst &Inst, unsigned N) const { |
559 | assert(N == 1 && "Invalid number of operands!" ); |
560 | Inst.addOperand(Op: MCOperand::createReg(Reg: DMRROWRegs[getDMRROWReg()])); |
561 | } |
562 | |
563 | void addRegDMRROWpRCOperands(MCInst &Inst, unsigned N) const { |
564 | assert(N == 1 && "Invalid number of operands!" ); |
565 | Inst.addOperand(Op: MCOperand::createReg(Reg: DMRROWpRegs[getDMRROWpReg()])); |
566 | } |
567 | |
568 | void addRegDMRRCOperands(MCInst &Inst, unsigned N) const { |
569 | assert(N == 1 && "Invalid number of operands!" ); |
570 | Inst.addOperand(Op: MCOperand::createReg(Reg: DMRRegs[getDMRReg()])); |
571 | } |
572 | |
573 | void addRegDMRpRCOperands(MCInst &Inst, unsigned N) const { |
574 | assert(N == 1 && "Invalid number of operands!" ); |
575 | Inst.addOperand(Op: MCOperand::createReg(Reg: DMRpRegs[getDMRpReg()])); |
576 | } |
577 | |
578 | void addRegWACCRCOperands(MCInst &Inst, unsigned N) const { |
579 | assert(N == 1 && "Invalid number of operands!" ); |
580 | Inst.addOperand(Op: MCOperand::createReg(Reg: WACCRegs[getACCReg()])); |
581 | } |
582 | |
583 | void addRegWACC_HIRCOperands(MCInst &Inst, unsigned N) const { |
584 | assert(N == 1 && "Invalid number of operands!" ); |
585 | Inst.addOperand(Op: MCOperand::createReg(Reg: WACC_HIRegs[getACCReg()])); |
586 | } |
587 | |
588 | void addRegVSRpRCOperands(MCInst &Inst, unsigned N) const { |
589 | assert(N == 1 && "Invalid number of operands!" ); |
590 | Inst.addOperand(Op: MCOperand::createReg(Reg: VSRpRegs[getVSRpEvenReg()])); |
591 | } |
592 | |
593 | void addRegVSRpEvenRCOperands(MCInst &Inst, unsigned N) const { |
594 | assert(N == 1 && "Invalid number of operands!" ); |
595 | Inst.addOperand(Op: MCOperand::createReg(Reg: VSRpRegs[getVSRpEvenReg()])); |
596 | } |
597 | |
598 | void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const { |
599 | assert(N == 1 && "Invalid number of operands!" ); |
600 | Inst.addOperand(Op: MCOperand::createReg(Reg: CRBITRegs[getCRBit()])); |
601 | } |
602 | |
603 | void addRegCRRCOperands(MCInst &Inst, unsigned N) const { |
604 | assert(N == 1 && "Invalid number of operands!" ); |
605 | Inst.addOperand(Op: MCOperand::createReg(Reg: CRRegs[getCCReg()])); |
606 | } |
607 | |
608 | void addCRBitMaskOperands(MCInst &Inst, unsigned N) const { |
609 | assert(N == 1 && "Invalid number of operands!" ); |
610 | Inst.addOperand(Op: MCOperand::createReg(Reg: CRRegs[getCRBitMask()])); |
611 | } |
612 | |
613 | void addImmOperands(MCInst &Inst, unsigned N) const { |
614 | assert(N == 1 && "Invalid number of operands!" ); |
615 | if (Kind == Immediate) |
616 | Inst.addOperand(Op: MCOperand::createImm(Val: getImm())); |
617 | else |
618 | Inst.addOperand(Op: MCOperand::createExpr(Val: getExpr())); |
619 | } |
620 | |
621 | void addS16ImmOperands(MCInst &Inst, unsigned N) const { |
622 | assert(N == 1 && "Invalid number of operands!" ); |
623 | switch (Kind) { |
624 | case Immediate: |
625 | Inst.addOperand(Op: MCOperand::createImm(Val: getImm())); |
626 | break; |
627 | case ContextImmediate: |
628 | Inst.addOperand(Op: MCOperand::createImm(Val: getImmS16Context())); |
629 | break; |
630 | default: |
631 | Inst.addOperand(Op: MCOperand::createExpr(Val: getExpr())); |
632 | break; |
633 | } |
634 | } |
635 | |
636 | void addU16ImmOperands(MCInst &Inst, unsigned N) const { |
637 | assert(N == 1 && "Invalid number of operands!" ); |
638 | switch (Kind) { |
639 | case Immediate: |
640 | Inst.addOperand(Op: MCOperand::createImm(Val: getImm())); |
641 | break; |
642 | case ContextImmediate: |
643 | Inst.addOperand(Op: MCOperand::createImm(Val: getImmU16Context())); |
644 | break; |
645 | default: |
646 | Inst.addOperand(Op: MCOperand::createExpr(Val: getExpr())); |
647 | break; |
648 | } |
649 | } |
650 | |
651 | void addBranchTargetOperands(MCInst &Inst, unsigned N) const { |
652 | assert(N == 1 && "Invalid number of operands!" ); |
653 | if (Kind == Immediate) |
654 | Inst.addOperand(Op: MCOperand::createImm(Val: getImm() / 4)); |
655 | else |
656 | Inst.addOperand(Op: MCOperand::createExpr(Val: getExpr())); |
657 | } |
658 | |
659 | void addTLSRegOperands(MCInst &Inst, unsigned N) const { |
660 | assert(N == 1 && "Invalid number of operands!" ); |
661 | Inst.addOperand(Op: MCOperand::createExpr(Val: getTLSReg())); |
662 | } |
663 | |
664 | StringRef getToken() const { |
665 | assert(Kind == Token && "Invalid access!" ); |
666 | return StringRef(Tok.Data, Tok.Length); |
667 | } |
668 | |
669 | void print(raw_ostream &OS, const MCAsmInfo &MAI) const override; |
670 | |
671 | static std::unique_ptr<PPCOperand> CreateToken(StringRef Str, SMLoc S, |
672 | bool IsPPC64) { |
673 | auto Op = std::make_unique<PPCOperand>(args: Token); |
674 | Op->Tok.Data = Str.data(); |
675 | Op->Tok.Length = Str.size(); |
676 | Op->StartLoc = S; |
677 | Op->EndLoc = S; |
678 | Op->IsPPC64 = IsPPC64; |
679 | return Op; |
680 | } |
681 | |
682 | static std::unique_ptr<PPCOperand> |
683 | CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64) { |
684 | // Allocate extra memory for the string and copy it. |
685 | // FIXME: This is incorrect, Operands are owned by unique_ptr with a default |
686 | // deleter which will destroy them by simply using "delete", not correctly |
687 | // calling operator delete on this extra memory after calling the dtor |
688 | // explicitly. |
689 | void *Mem = ::operator new(sizeof(PPCOperand) + Str.size()); |
690 | std::unique_ptr<PPCOperand> Op(new (Mem) PPCOperand(Token)); |
691 | Op->Tok.Data = reinterpret_cast<const char *>(Op.get() + 1); |
692 | Op->Tok.Length = Str.size(); |
693 | std::memcpy(dest: const_cast<char *>(Op->Tok.Data), src: Str.data(), n: Str.size()); |
694 | Op->StartLoc = S; |
695 | Op->EndLoc = S; |
696 | Op->IsPPC64 = IsPPC64; |
697 | return Op; |
698 | } |
699 | |
700 | static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E, |
701 | bool IsPPC64, |
702 | bool IsMemOpBase = false) { |
703 | auto Op = std::make_unique<PPCOperand>(args: Immediate); |
704 | Op->Imm.Val = Val; |
705 | Op->Imm.IsMemOpBase = IsMemOpBase; |
706 | Op->StartLoc = S; |
707 | Op->EndLoc = E; |
708 | Op->IsPPC64 = IsPPC64; |
709 | return Op; |
710 | } |
711 | |
712 | static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S, |
713 | SMLoc E, bool IsPPC64) { |
714 | auto Op = std::make_unique<PPCOperand>(args: Expression); |
715 | Op->Expr.Val = Val; |
716 | Op->Expr.CRVal = EvaluateCRExpr(E: Val); |
717 | Op->StartLoc = S; |
718 | Op->EndLoc = E; |
719 | Op->IsPPC64 = IsPPC64; |
720 | return Op; |
721 | } |
722 | |
723 | static std::unique_ptr<PPCOperand> |
724 | CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64) { |
725 | auto Op = std::make_unique<PPCOperand>(args: TLSRegister); |
726 | Op->TLSReg.Sym = Sym; |
727 | Op->StartLoc = S; |
728 | Op->EndLoc = E; |
729 | Op->IsPPC64 = IsPPC64; |
730 | return Op; |
731 | } |
732 | |
733 | static std::unique_ptr<PPCOperand> |
734 | CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) { |
735 | auto Op = std::make_unique<PPCOperand>(args: ContextImmediate); |
736 | Op->Imm.Val = Val; |
737 | Op->StartLoc = S; |
738 | Op->EndLoc = E; |
739 | Op->IsPPC64 = IsPPC64; |
740 | return Op; |
741 | } |
742 | |
743 | static std::unique_ptr<PPCOperand> |
744 | CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) { |
745 | if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val)) |
746 | return CreateImm(Val: CE->getValue(), S, E, IsPPC64); |
747 | |
748 | if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val)) |
749 | if (getSpecifier(SRE) == PPC::S_TLS || |
750 | getSpecifier(SRE) == PPC::S_TLS_PCREL) |
751 | return CreateTLSReg(Sym: SRE, S, E, IsPPC64); |
752 | |
753 | if (const auto *SE = dyn_cast<MCSpecifierExpr>(Val)) { |
754 | int64_t Res; |
755 | if (PPC::evaluateAsConstant(Expr: *SE, Res)) |
756 | return CreateContextImm(Val: Res, S, E, IsPPC64); |
757 | } |
758 | |
759 | return CreateExpr(Val, S, E, IsPPC64); |
760 | } |
761 | |
762 | private: |
763 | template <unsigned Width> |
764 | bool isExtImm(bool Signed, unsigned Multiple) const { |
765 | switch (Kind) { |
766 | default: |
767 | return false; |
768 | case Expression: |
769 | return true; |
770 | case Immediate: |
771 | case ContextImmediate: |
772 | if (Signed) |
773 | return isInt<Width>(getImmS16Context()) && |
774 | (getImmS16Context() & (Multiple - 1)) == 0; |
775 | else |
776 | return isUInt<Width>(getImmU16Context()) && |
777 | (getImmU16Context() & (Multiple - 1)) == 0; |
778 | } |
779 | } |
780 | }; |
781 | |
782 | } // end anonymous namespace. |
783 | |
784 | void PPCOperand::print(raw_ostream &OS, const MCAsmInfo &MAI) const { |
785 | switch (Kind) { |
786 | case Token: |
787 | OS << "'" << getToken() << "'" ; |
788 | break; |
789 | case Immediate: |
790 | case ContextImmediate: |
791 | OS << getImm(); |
792 | break; |
793 | case Expression: |
794 | MAI.printExpr(OS, *getExpr()); |
795 | break; |
796 | case TLSRegister: |
797 | MAI.printExpr(OS, *getTLSReg()); |
798 | break; |
799 | } |
800 | } |
801 | |
802 | static void |
803 | addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) { |
804 | if (Op.isImm()) { |
805 | Inst.addOperand(Op: MCOperand::createImm(Val: -Op.getImm())); |
806 | return; |
807 | } |
808 | const MCExpr *Expr = Op.getExpr(); |
809 | if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Val: Expr)) { |
810 | if (UnExpr->getOpcode() == MCUnaryExpr::Minus) { |
811 | Inst.addOperand(Op: MCOperand::createExpr(Val: UnExpr->getSubExpr())); |
812 | return; |
813 | } |
814 | } else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Val: Expr)) { |
815 | if (BinExpr->getOpcode() == MCBinaryExpr::Sub) { |
816 | const MCExpr *NE = MCBinaryExpr::createSub(LHS: BinExpr->getRHS(), |
817 | RHS: BinExpr->getLHS(), Ctx); |
818 | Inst.addOperand(Op: MCOperand::createExpr(Val: NE)); |
819 | return; |
820 | } |
821 | } |
822 | Inst.addOperand(Op: MCOperand::createExpr(Val: MCUnaryExpr::createMinus(Expr, Ctx))); |
823 | } |
824 | |
825 | void PPCAsmParser::processInstruction(MCInst &Inst, |
826 | const OperandVector &Operands) { |
827 | int Opcode = Inst.getOpcode(); |
828 | switch (Opcode) { |
829 | case PPC::DCBTx: |
830 | case PPC::DCBTT: |
831 | case PPC::DCBTSTx: |
832 | case PPC::DCBTSTT: { |
833 | MCInst TmpInst; |
834 | TmpInst.setOpcode((Opcode == PPC::DCBTx || Opcode == PPC::DCBTT) ? |
835 | PPC::DCBT : PPC::DCBTST); |
836 | TmpInst.addOperand(Op: MCOperand::createImm( |
837 | Val: (Opcode == PPC::DCBTx || Opcode == PPC::DCBTSTx) ? 0 : 16)); |
838 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
839 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
840 | Inst = TmpInst; |
841 | break; |
842 | } |
843 | case PPC::DCBTCT: |
844 | case PPC::DCBTDS: { |
845 | MCInst TmpInst; |
846 | TmpInst.setOpcode(PPC::DCBT); |
847 | TmpInst.addOperand(Op: Inst.getOperand(i: 2)); |
848 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
849 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
850 | Inst = TmpInst; |
851 | break; |
852 | } |
853 | case PPC::DCBTSTCT: |
854 | case PPC::DCBTSTDS: { |
855 | MCInst TmpInst; |
856 | TmpInst.setOpcode(PPC::DCBTST); |
857 | TmpInst.addOperand(Op: Inst.getOperand(i: 2)); |
858 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
859 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
860 | Inst = TmpInst; |
861 | break; |
862 | } |
863 | case PPC::DCBFx: |
864 | case PPC::DCBFL: |
865 | case PPC::DCBFLP: |
866 | case PPC::DCBFPS: |
867 | case PPC::DCBSTPS: { |
868 | int L = 0; |
869 | if (Opcode == PPC::DCBFL) |
870 | L = 1; |
871 | else if (Opcode == PPC::DCBFLP) |
872 | L = 3; |
873 | else if (Opcode == PPC::DCBFPS) |
874 | L = 4; |
875 | else if (Opcode == PPC::DCBSTPS) |
876 | L = 6; |
877 | |
878 | MCInst TmpInst; |
879 | TmpInst.setOpcode(PPC::DCBF); |
880 | TmpInst.addOperand(Op: MCOperand::createImm(Val: L)); |
881 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
882 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
883 | Inst = TmpInst; |
884 | break; |
885 | } |
886 | case PPC::LAx: { |
887 | MCInst TmpInst; |
888 | TmpInst.setOpcode(PPC::LA); |
889 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
890 | TmpInst.addOperand(Op: Inst.getOperand(i: 2)); |
891 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
892 | Inst = TmpInst; |
893 | break; |
894 | } |
895 | case PPC::PLA8: |
896 | case PPC::PLA: { |
897 | MCInst TmpInst; |
898 | TmpInst.setOpcode(Opcode == PPC::PLA ? PPC::PADDI : PPC::PADDI8); |
899 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
900 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
901 | TmpInst.addOperand(Op: Inst.getOperand(i: 2)); |
902 | Inst = TmpInst; |
903 | break; |
904 | } |
905 | case PPC::PLA8pc: |
906 | case PPC::PLApc: { |
907 | MCInst TmpInst; |
908 | TmpInst.setOpcode(Opcode == PPC::PLApc ? PPC::PADDIpc : PPC::PADDI8pc); |
909 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
910 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
911 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
912 | Inst = TmpInst; |
913 | break; |
914 | } |
915 | case PPC::SUBI: { |
916 | MCInst TmpInst; |
917 | TmpInst.setOpcode(PPC::ADDI); |
918 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
919 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
920 | addNegOperand(Inst&: TmpInst, Op&: Inst.getOperand(i: 2), Ctx&: getContext()); |
921 | Inst = TmpInst; |
922 | break; |
923 | } |
924 | case PPC::PSUBI: { |
925 | MCInst TmpInst; |
926 | TmpInst.setOpcode(PPC::PADDI); |
927 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
928 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
929 | addNegOperand(Inst&: TmpInst, Op&: Inst.getOperand(i: 2), Ctx&: getContext()); |
930 | Inst = TmpInst; |
931 | break; |
932 | } |
933 | case PPC::SUBIS: { |
934 | MCInst TmpInst; |
935 | TmpInst.setOpcode(PPC::ADDIS); |
936 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
937 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
938 | addNegOperand(Inst&: TmpInst, Op&: Inst.getOperand(i: 2), Ctx&: getContext()); |
939 | Inst = TmpInst; |
940 | break; |
941 | } |
942 | case PPC::SUBIC: { |
943 | MCInst TmpInst; |
944 | TmpInst.setOpcode(PPC::ADDIC); |
945 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
946 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
947 | addNegOperand(Inst&: TmpInst, Op&: Inst.getOperand(i: 2), Ctx&: getContext()); |
948 | Inst = TmpInst; |
949 | break; |
950 | } |
951 | case PPC::SUBIC_rec: { |
952 | MCInst TmpInst; |
953 | TmpInst.setOpcode(PPC::ADDIC_rec); |
954 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
955 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
956 | addNegOperand(Inst&: TmpInst, Op&: Inst.getOperand(i: 2), Ctx&: getContext()); |
957 | Inst = TmpInst; |
958 | break; |
959 | } |
960 | case PPC::EXTLWI: |
961 | case PPC::EXTLWI_rec: { |
962 | MCInst TmpInst; |
963 | int64_t N = Inst.getOperand(i: 2).getImm(); |
964 | int64_t B = Inst.getOperand(i: 3).getImm(); |
965 | TmpInst.setOpcode(Opcode == PPC::EXTLWI ? PPC::RLWINM : PPC::RLWINM_rec); |
966 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
967 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
968 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B)); |
969 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
970 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N - 1)); |
971 | Inst = TmpInst; |
972 | break; |
973 | } |
974 | case PPC::EXTRWI: |
975 | case PPC::EXTRWI_rec: { |
976 | MCInst TmpInst; |
977 | int64_t N = Inst.getOperand(i: 2).getImm(); |
978 | int64_t B = Inst.getOperand(i: 3).getImm(); |
979 | TmpInst.setOpcode(Opcode == PPC::EXTRWI ? PPC::RLWINM : PPC::RLWINM_rec); |
980 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
981 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
982 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B + N)); |
983 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 32 - N)); |
984 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 31)); |
985 | Inst = TmpInst; |
986 | break; |
987 | } |
988 | case PPC::INSLWI: |
989 | case PPC::INSLWI_rec: { |
990 | MCInst TmpInst; |
991 | int64_t N = Inst.getOperand(i: 2).getImm(); |
992 | int64_t B = Inst.getOperand(i: 3).getImm(); |
993 | TmpInst.setOpcode(Opcode == PPC::INSLWI ? PPC::RLWIMI : PPC::RLWIMI_rec); |
994 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
995 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
996 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
997 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 32 - B)); |
998 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B)); |
999 | TmpInst.addOperand(Op: MCOperand::createImm(Val: (B + N) - 1)); |
1000 | Inst = TmpInst; |
1001 | break; |
1002 | } |
1003 | case PPC::INSRWI: |
1004 | case PPC::INSRWI_rec: { |
1005 | MCInst TmpInst; |
1006 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1007 | int64_t B = Inst.getOperand(i: 3).getImm(); |
1008 | TmpInst.setOpcode(Opcode == PPC::INSRWI ? PPC::RLWIMI : PPC::RLWIMI_rec); |
1009 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1010 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1011 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1012 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 32 - (B + N))); |
1013 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B)); |
1014 | TmpInst.addOperand(Op: MCOperand::createImm(Val: (B + N) - 1)); |
1015 | Inst = TmpInst; |
1016 | break; |
1017 | } |
1018 | case PPC::ROTRWI: |
1019 | case PPC::ROTRWI_rec: { |
1020 | MCInst TmpInst; |
1021 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1022 | TmpInst.setOpcode(Opcode == PPC::ROTRWI ? PPC::RLWINM : PPC::RLWINM_rec); |
1023 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1024 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1025 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 32 - N)); |
1026 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
1027 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 31)); |
1028 | Inst = TmpInst; |
1029 | break; |
1030 | } |
1031 | case PPC::SLWI: |
1032 | case PPC::SLWI_rec: { |
1033 | MCInst TmpInst; |
1034 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1035 | TmpInst.setOpcode(Opcode == PPC::SLWI ? PPC::RLWINM : PPC::RLWINM_rec); |
1036 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1037 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1038 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N)); |
1039 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
1040 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 31 - N)); |
1041 | Inst = TmpInst; |
1042 | break; |
1043 | } |
1044 | case PPC::SRWI: |
1045 | case PPC::SRWI_rec: { |
1046 | MCInst TmpInst; |
1047 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1048 | TmpInst.setOpcode(Opcode == PPC::SRWI ? PPC::RLWINM : PPC::RLWINM_rec); |
1049 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1050 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1051 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 32 - N)); |
1052 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N)); |
1053 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 31)); |
1054 | Inst = TmpInst; |
1055 | break; |
1056 | } |
1057 | case PPC::CLRRWI: |
1058 | case PPC::CLRRWI_rec: { |
1059 | MCInst TmpInst; |
1060 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1061 | TmpInst.setOpcode(Opcode == PPC::CLRRWI ? PPC::RLWINM : PPC::RLWINM_rec); |
1062 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1063 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1064 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
1065 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
1066 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 31 - N)); |
1067 | Inst = TmpInst; |
1068 | break; |
1069 | } |
1070 | case PPC::CLRLSLWI: |
1071 | case PPC::CLRLSLWI_rec: { |
1072 | MCInst TmpInst; |
1073 | int64_t B = Inst.getOperand(i: 2).getImm(); |
1074 | int64_t N = Inst.getOperand(i: 3).getImm(); |
1075 | TmpInst.setOpcode(Opcode == PPC::CLRLSLWI ? PPC::RLWINM : PPC::RLWINM_rec); |
1076 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1077 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1078 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N)); |
1079 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B - N)); |
1080 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 31 - N)); |
1081 | Inst = TmpInst; |
1082 | break; |
1083 | } |
1084 | case PPC::EXTLDI: |
1085 | case PPC::EXTLDI_rec: { |
1086 | MCInst TmpInst; |
1087 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1088 | int64_t B = Inst.getOperand(i: 3).getImm(); |
1089 | TmpInst.setOpcode(Opcode == PPC::EXTLDI ? PPC::RLDICR : PPC::RLDICR_rec); |
1090 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1091 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1092 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B)); |
1093 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N - 1)); |
1094 | Inst = TmpInst; |
1095 | break; |
1096 | } |
1097 | case PPC::EXTRDI: |
1098 | case PPC::EXTRDI_rec: { |
1099 | MCInst TmpInst; |
1100 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1101 | int64_t B = Inst.getOperand(i: 3).getImm(); |
1102 | TmpInst.setOpcode(Opcode == PPC::EXTRDI ? PPC::RLDICL : PPC::RLDICL_rec); |
1103 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1104 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1105 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B + N)); |
1106 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 64 - N)); |
1107 | Inst = TmpInst; |
1108 | break; |
1109 | } |
1110 | case PPC::INSRDI: |
1111 | case PPC::INSRDI_rec: { |
1112 | MCInst TmpInst; |
1113 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1114 | int64_t B = Inst.getOperand(i: 3).getImm(); |
1115 | TmpInst.setOpcode(Opcode == PPC::INSRDI ? PPC::RLDIMI : PPC::RLDIMI_rec); |
1116 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1117 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1118 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1119 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 64 - (B + N))); |
1120 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B)); |
1121 | Inst = TmpInst; |
1122 | break; |
1123 | } |
1124 | case PPC::ROTRDI: |
1125 | case PPC::ROTRDI_rec: { |
1126 | MCInst TmpInst; |
1127 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1128 | TmpInst.setOpcode(Opcode == PPC::ROTRDI ? PPC::RLDICL : PPC::RLDICL_rec); |
1129 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1130 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1131 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 64 - N)); |
1132 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
1133 | Inst = TmpInst; |
1134 | break; |
1135 | } |
1136 | case PPC::SLDI: |
1137 | case PPC::SLDI_rec: { |
1138 | MCInst TmpInst; |
1139 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1140 | TmpInst.setOpcode(Opcode == PPC::SLDI ? PPC::RLDICR : PPC::RLDICR_rec); |
1141 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1142 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1143 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N)); |
1144 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 63 - N)); |
1145 | Inst = TmpInst; |
1146 | break; |
1147 | } |
1148 | case PPC::SUBPCIS: { |
1149 | MCInst TmpInst; |
1150 | int64_t N = Inst.getOperand(i: 1).getImm(); |
1151 | TmpInst.setOpcode(PPC::ADDPCIS); |
1152 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1153 | TmpInst.addOperand(Op: MCOperand::createImm(Val: -N)); |
1154 | Inst = TmpInst; |
1155 | break; |
1156 | } |
1157 | case PPC::SRDI: |
1158 | case PPC::SRDI_rec: { |
1159 | MCInst TmpInst; |
1160 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1161 | TmpInst.setOpcode(Opcode == PPC::SRDI ? PPC::RLDICL : PPC::RLDICL_rec); |
1162 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1163 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1164 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 64 - N)); |
1165 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N)); |
1166 | Inst = TmpInst; |
1167 | break; |
1168 | } |
1169 | case PPC::CLRRDI: |
1170 | case PPC::CLRRDI_rec: { |
1171 | MCInst TmpInst; |
1172 | int64_t N = Inst.getOperand(i: 2).getImm(); |
1173 | TmpInst.setOpcode(Opcode == PPC::CLRRDI ? PPC::RLDICR : PPC::RLDICR_rec); |
1174 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1175 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1176 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 0)); |
1177 | TmpInst.addOperand(Op: MCOperand::createImm(Val: 63 - N)); |
1178 | Inst = TmpInst; |
1179 | break; |
1180 | } |
1181 | case PPC::CLRLSLDI: |
1182 | case PPC::CLRLSLDI_rec: { |
1183 | MCInst TmpInst; |
1184 | int64_t B = Inst.getOperand(i: 2).getImm(); |
1185 | int64_t N = Inst.getOperand(i: 3).getImm(); |
1186 | TmpInst.setOpcode(Opcode == PPC::CLRLSLDI ? PPC::RLDIC : PPC::RLDIC_rec); |
1187 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1188 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1189 | TmpInst.addOperand(Op: MCOperand::createImm(Val: N)); |
1190 | TmpInst.addOperand(Op: MCOperand::createImm(Val: B - N)); |
1191 | Inst = TmpInst; |
1192 | break; |
1193 | } |
1194 | case PPC::RLWINMbm: |
1195 | case PPC::RLWINMbm_rec: { |
1196 | unsigned MB, ME; |
1197 | int64_t BM = Inst.getOperand(i: 3).getImm(); |
1198 | if (!isRunOfOnes(Val: BM, MB, ME)) |
1199 | break; |
1200 | |
1201 | MCInst TmpInst; |
1202 | TmpInst.setOpcode(Opcode == PPC::RLWINMbm ? PPC::RLWINM : PPC::RLWINM_rec); |
1203 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1204 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1205 | TmpInst.addOperand(Op: Inst.getOperand(i: 2)); |
1206 | TmpInst.addOperand(Op: MCOperand::createImm(Val: MB)); |
1207 | TmpInst.addOperand(Op: MCOperand::createImm(Val: ME)); |
1208 | Inst = TmpInst; |
1209 | break; |
1210 | } |
1211 | case PPC::RLWIMIbm: |
1212 | case PPC::RLWIMIbm_rec: { |
1213 | unsigned MB, ME; |
1214 | int64_t BM = Inst.getOperand(i: 3).getImm(); |
1215 | if (!isRunOfOnes(Val: BM, MB, ME)) |
1216 | break; |
1217 | |
1218 | MCInst TmpInst; |
1219 | TmpInst.setOpcode(Opcode == PPC::RLWIMIbm ? PPC::RLWIMI : PPC::RLWIMI_rec); |
1220 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1221 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); // The tied operand. |
1222 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1223 | TmpInst.addOperand(Op: Inst.getOperand(i: 2)); |
1224 | TmpInst.addOperand(Op: MCOperand::createImm(Val: MB)); |
1225 | TmpInst.addOperand(Op: MCOperand::createImm(Val: ME)); |
1226 | Inst = TmpInst; |
1227 | break; |
1228 | } |
1229 | case PPC::RLWNMbm: |
1230 | case PPC::RLWNMbm_rec: { |
1231 | unsigned MB, ME; |
1232 | int64_t BM = Inst.getOperand(i: 3).getImm(); |
1233 | if (!isRunOfOnes(Val: BM, MB, ME)) |
1234 | break; |
1235 | |
1236 | MCInst TmpInst; |
1237 | TmpInst.setOpcode(Opcode == PPC::RLWNMbm ? PPC::RLWNM : PPC::RLWNM_rec); |
1238 | TmpInst.addOperand(Op: Inst.getOperand(i: 0)); |
1239 | TmpInst.addOperand(Op: Inst.getOperand(i: 1)); |
1240 | TmpInst.addOperand(Op: Inst.getOperand(i: 2)); |
1241 | TmpInst.addOperand(Op: MCOperand::createImm(Val: MB)); |
1242 | TmpInst.addOperand(Op: MCOperand::createImm(Val: ME)); |
1243 | Inst = TmpInst; |
1244 | break; |
1245 | } |
1246 | case PPC::MFTB: { |
1247 | if (getSTI().hasFeature(Feature: PPC::FeatureMFTB)) { |
1248 | assert(Inst.getNumOperands() == 2 && "Expecting two operands" ); |
1249 | Inst.setOpcode(PPC::MFSPR); |
1250 | } |
1251 | break; |
1252 | } |
1253 | } |
1254 | } |
1255 | |
1256 | static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, |
1257 | unsigned VariantID = 0); |
1258 | |
1259 | // Check that the register+immediate memory operand is in the right position and |
1260 | // is expected by the instruction. Returns true if the memory operand syntax is |
1261 | // valid; otherwise, returns false. |
1262 | static bool validateMemOp(const OperandVector &Operands, bool isMemriOp) { |
1263 | for (size_t idx = 0; idx < Operands.size(); ++idx) { |
1264 | const PPCOperand &Op = static_cast<const PPCOperand &>(*Operands[idx]); |
1265 | if (Op.isMemOpBase() != (idx == 3 && isMemriOp)) |
1266 | return false; |
1267 | } |
1268 | return true; |
1269 | } |
1270 | |
1271 | bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
1272 | OperandVector &Operands, |
1273 | MCStreamer &Out, uint64_t &ErrorInfo, |
1274 | bool MatchingInlineAsm) { |
1275 | MCInst Inst; |
1276 | const PPCInstrInfo *TII = static_cast<const PPCInstrInfo *>(&MII); |
1277 | |
1278 | switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, matchingInlineAsm: MatchingInlineAsm)) { |
1279 | case Match_Success: |
1280 | if (!validateMemOp(Operands, isMemriOp: TII->isMemriOp(Opcode: Inst.getOpcode()))) |
1281 | return Error(L: IDLoc, Msg: "invalid operand for instruction" ); |
1282 | // Post-process instructions (typically extended mnemonics) |
1283 | processInstruction(Inst, Operands); |
1284 | Inst.setLoc(IDLoc); |
1285 | Out.emitInstruction(Inst, STI: getSTI()); |
1286 | return false; |
1287 | case Match_MissingFeature: |
1288 | return Error(L: IDLoc, Msg: "instruction use requires an option to be enabled" ); |
1289 | case Match_MnemonicFail: { |
1290 | FeatureBitset FBS = ComputeAvailableFeatures(FB: getSTI().getFeatureBits()); |
1291 | std::string Suggestion = PPCMnemonicSpellCheck( |
1292 | S: ((PPCOperand &)*Operands[0]).getToken(), FBS); |
1293 | return Error(L: IDLoc, Msg: "invalid instruction" + Suggestion, |
1294 | Range: ((PPCOperand &)*Operands[0]).getLocRange()); |
1295 | } |
1296 | case Match_InvalidOperand: { |
1297 | SMLoc ErrorLoc = IDLoc; |
1298 | if (ErrorInfo != ~0ULL) { |
1299 | if (ErrorInfo >= Operands.size()) |
1300 | return Error(L: IDLoc, Msg: "too few operands for instruction" ); |
1301 | |
1302 | ErrorLoc = ((PPCOperand &)*Operands[ErrorInfo]).getStartLoc(); |
1303 | if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; |
1304 | } |
1305 | |
1306 | return Error(L: ErrorLoc, Msg: "invalid operand for instruction" ); |
1307 | } |
1308 | } |
1309 | |
1310 | llvm_unreachable("Implement any new match types added!" ); |
1311 | } |
1312 | |
1313 | #define GET_REGISTER_MATCHER |
1314 | #include "PPCGenAsmMatcher.inc" |
1315 | |
1316 | MCRegister PPCAsmParser::matchRegisterName(int64_t &IntVal) { |
1317 | if (getParser().getTok().is(K: AsmToken::Percent)) |
1318 | getParser().Lex(); // Eat the '%'. |
1319 | |
1320 | if (!getParser().getTok().is(K: AsmToken::Identifier)) |
1321 | return MCRegister(); |
1322 | |
1323 | // MatchRegisterName() expects lower-case registers, but we want to support |
1324 | // case-insensitive spelling. |
1325 | std::string NameBuf = getParser().getTok().getString().lower(); |
1326 | StringRef Name(NameBuf); |
1327 | MCRegister RegNo = MatchRegisterName(Name); |
1328 | if (!RegNo) |
1329 | return RegNo; |
1330 | |
1331 | Name.substr(Start: Name.find_first_of(Chars: "1234567890" )).getAsInteger(Radix: 10, Result&: IntVal); |
1332 | |
1333 | // MatchRegisterName doesn't seem to have special handling for 64bit vs 32bit |
1334 | // register types. |
1335 | if (Name == "lr" ) { |
1336 | RegNo = isPPC64() ? PPC::LR8 : PPC::LR; |
1337 | IntVal = 8; |
1338 | } else if (Name == "ctr" ) { |
1339 | RegNo = isPPC64() ? PPC::CTR8 : PPC::CTR; |
1340 | IntVal = 9; |
1341 | } else if (Name == "vrsave" ) |
1342 | IntVal = 256; |
1343 | else if (Name.starts_with(Prefix: "r" )) |
1344 | RegNo = isPPC64() ? XRegs[IntVal] : RRegs[IntVal]; |
1345 | |
1346 | getParser().Lex(); |
1347 | return RegNo; |
1348 | } |
1349 | |
1350 | bool PPCAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, |
1351 | SMLoc &EndLoc) { |
1352 | if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess()) |
1353 | return TokError(Msg: "invalid register name" ); |
1354 | return false; |
1355 | } |
1356 | |
1357 | ParseStatus PPCAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, |
1358 | SMLoc &EndLoc) { |
1359 | const AsmToken &Tok = getParser().getTok(); |
1360 | StartLoc = Tok.getLoc(); |
1361 | EndLoc = Tok.getEndLoc(); |
1362 | int64_t IntVal; |
1363 | if (!(Reg = matchRegisterName(IntVal))) |
1364 | return ParseStatus::NoMatch; |
1365 | return ParseStatus::Success; |
1366 | } |
1367 | |
1368 | // Extract the @l or @ha specifier from the expression, returning a modified |
1369 | // expression with the specifier removed. Stores the extracted specifier in |
1370 | // `Spec`. Reports an error if multiple specifiers are detected. |
1371 | const MCExpr *PPCAsmParser::(const MCExpr *E, |
1372 | PPCMCExpr::Specifier &Spec) { |
1373 | MCContext &Context = getParser().getContext(); |
1374 | switch (E->getKind()) { |
1375 | case MCExpr::Constant: |
1376 | break; |
1377 | case MCExpr::Specifier: { |
1378 | // Detect error but do not return a modified expression. |
1379 | auto *TE = cast<MCSpecifierExpr>(Val: E); |
1380 | Spec = TE->getSpecifier(); |
1381 | (void)extractSpecifier(E: TE->getSubExpr(), Spec); |
1382 | Spec = PPC::S_None; |
1383 | } break; |
1384 | |
1385 | case MCExpr::SymbolRef: { |
1386 | const auto *SRE = cast<MCSymbolRefExpr>(Val: E); |
1387 | switch (getSpecifier(SRE)) { |
1388 | case PPC::S_None: |
1389 | default: |
1390 | break; |
1391 | case PPC::S_LO: |
1392 | case PPC::S_HI: |
1393 | case PPC::S_HA: |
1394 | case PPC::S_HIGH: |
1395 | case PPC::S_HIGHA: |
1396 | case PPC::S_HIGHER: |
1397 | case PPC::S_HIGHERA: |
1398 | case PPC::S_HIGHEST: |
1399 | case PPC::S_HIGHESTA: |
1400 | if (Spec == PPC::S_None) |
1401 | Spec = getSpecifier(SRE); |
1402 | else |
1403 | Error(L: E->getLoc(), Msg: "cannot contain more than one relocation specifier" ); |
1404 | return MCSymbolRefExpr::create(Symbol: &SRE->getSymbol(), Ctx&: Context); |
1405 | } |
1406 | break; |
1407 | } |
1408 | |
1409 | case MCExpr::Unary: { |
1410 | const MCUnaryExpr *UE = cast<MCUnaryExpr>(Val: E); |
1411 | const MCExpr *Sub = extractSpecifier(E: UE->getSubExpr(), Spec); |
1412 | if (Spec != PPC::S_None) |
1413 | return MCUnaryExpr::create(Op: UE->getOpcode(), Expr: Sub, Ctx&: Context); |
1414 | break; |
1415 | } |
1416 | |
1417 | case MCExpr::Binary: { |
1418 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: E); |
1419 | const MCExpr *LHS = extractSpecifier(E: BE->getLHS(), Spec); |
1420 | const MCExpr *RHS = extractSpecifier(E: BE->getRHS(), Spec); |
1421 | if (Spec != PPC::S_None) |
1422 | return MCBinaryExpr::create(Op: BE->getOpcode(), LHS, RHS, Ctx&: Context); |
1423 | break; |
1424 | } |
1425 | case MCExpr::Target: |
1426 | llvm_unreachable("unused by this backend" ); |
1427 | } |
1428 | |
1429 | return E; |
1430 | } |
1431 | |
1432 | /// This differs from the default "parseExpression" in that it handles |
1433 | /// specifiers. |
1434 | bool PPCAsmParser::parseExpression(const MCExpr *&EVal) { |
1435 | // (ELF Platforms) |
1436 | // Handle \code @l/@ha \endcode |
1437 | if (getParser().parseExpression(Res&: EVal)) |
1438 | return true; |
1439 | |
1440 | uint16_t Spec = PPC::S_None; |
1441 | const MCExpr *E = extractSpecifier(E: EVal, Spec); |
1442 | if (Spec != PPC::S_None) |
1443 | EVal = MCSpecifierExpr::create(Expr: E, S: Spec, Ctx&: getParser().getContext()); |
1444 | |
1445 | return false; |
1446 | } |
1447 | |
1448 | /// This handles registers in the form 'NN', '%rNN' for ELF platforms and |
1449 | /// rNN for MachO. |
1450 | bool PPCAsmParser::parseOperand(OperandVector &Operands) { |
1451 | MCAsmParser &Parser = getParser(); |
1452 | SMLoc S = Parser.getTok().getLoc(); |
1453 | SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1); |
1454 | const MCExpr *EVal; |
1455 | |
1456 | // Attempt to parse the next token as an immediate |
1457 | switch (getLexer().getKind()) { |
1458 | // Special handling for register names. These are interpreted |
1459 | // as immediates corresponding to the register number. |
1460 | case AsmToken::Percent: { |
1461 | int64_t IntVal; |
1462 | if (!matchRegisterName(IntVal)) |
1463 | return Error(L: S, Msg: "invalid register name" ); |
1464 | |
1465 | Operands.push_back(Elt: PPCOperand::CreateImm(Val: IntVal, S, E, IsPPC64: isPPC64())); |
1466 | return false; |
1467 | } |
1468 | case AsmToken::Identifier: |
1469 | case AsmToken::LParen: |
1470 | case AsmToken::Plus: |
1471 | case AsmToken::Minus: |
1472 | case AsmToken::Integer: |
1473 | case AsmToken::Dot: |
1474 | case AsmToken::Dollar: |
1475 | case AsmToken::Exclaim: |
1476 | case AsmToken::Tilde: |
1477 | if (!parseExpression(EVal)) |
1478 | break; |
1479 | // Fall-through |
1480 | [[fallthrough]]; |
1481 | default: |
1482 | return Error(L: S, Msg: "unknown operand" ); |
1483 | } |
1484 | |
1485 | // Push the parsed operand into the list of operands |
1486 | Operands.push_back(Elt: PPCOperand::CreateFromMCExpr(Val: EVal, S, E, IsPPC64: isPPC64())); |
1487 | |
1488 | // Check whether this is a TLS call expression |
1489 | const char TlsGetAddr[] = "__tls_get_addr" ; |
1490 | bool TlsCall = false; |
1491 | const MCExpr *TlsCallAddend = nullptr; |
1492 | if (auto *Ref = dyn_cast<MCSymbolRefExpr>(Val: EVal)) { |
1493 | TlsCall = Ref->getSymbol().getName() == TlsGetAddr; |
1494 | } else if (auto *Bin = dyn_cast<MCBinaryExpr>(Val: EVal); |
1495 | Bin && Bin->getOpcode() == MCBinaryExpr::Add) { |
1496 | if (auto *Ref = dyn_cast<MCSymbolRefExpr>(Val: Bin->getLHS())) { |
1497 | TlsCall = Ref->getSymbol().getName() == TlsGetAddr; |
1498 | TlsCallAddend = Bin->getRHS(); |
1499 | } |
1500 | } |
1501 | |
1502 | if (TlsCall && parseOptionalToken(T: AsmToken::LParen)) { |
1503 | const MCExpr *TLSSym; |
1504 | const SMLoc S2 = Parser.getTok().getLoc(); |
1505 | if (parseExpression(EVal&: TLSSym)) |
1506 | return Error(L: S2, Msg: "invalid TLS call expression" ); |
1507 | E = Parser.getTok().getLoc(); |
1508 | if (parseToken(T: AsmToken::RParen, Msg: "expected ')'" )) |
1509 | return true; |
1510 | // PPC32 allows bl __tls_get_addr[+a](x@tlsgd)@plt+b. Parse "@plt[+b]". |
1511 | if (!isPPC64() && parseOptionalToken(T: AsmToken::At)) { |
1512 | AsmToken Tok = getTok(); |
1513 | if (!(parseOptionalToken(T: AsmToken::Identifier) && |
1514 | Tok.getString().compare_insensitive(RHS: "plt" ) == 0)) |
1515 | return Error(L: Tok.getLoc(), Msg: "expected 'plt'" ); |
1516 | EVal = MCSymbolRefExpr::create(Symbol: getContext().getOrCreateSymbol(Name: TlsGetAddr), |
1517 | specifier: PPC::S_PLT, Ctx&: getContext()); |
1518 | if (parseOptionalToken(T: AsmToken::Plus)) { |
1519 | const MCExpr *Addend = nullptr; |
1520 | SMLoc EndLoc; |
1521 | if (parsePrimaryExpr(Res&: Addend, EndLoc)) |
1522 | return true; |
1523 | if (TlsCallAddend) // __tls_get_addr+a(x@tlsgd)@plt+b |
1524 | TlsCallAddend = |
1525 | MCBinaryExpr::createAdd(LHS: TlsCallAddend, RHS: Addend, Ctx&: getContext()); |
1526 | else // __tls_get_addr(x@tlsgd)@plt+b |
1527 | TlsCallAddend = Addend; |
1528 | } |
1529 | if (TlsCallAddend) |
1530 | EVal = MCBinaryExpr::createAdd(LHS: EVal, RHS: TlsCallAddend, Ctx&: getContext()); |
1531 | // Add a __tls_get_addr operand with addend a, b, or a+b. |
1532 | Operands.back() = PPCOperand::CreateFromMCExpr( |
1533 | Val: EVal, S, E: Parser.getTok().getLoc(), IsPPC64: false); |
1534 | } |
1535 | |
1536 | Operands.push_back(Elt: PPCOperand::CreateFromMCExpr(Val: TLSSym, S, E, IsPPC64: isPPC64())); |
1537 | } |
1538 | |
1539 | // Otherwise, check for D-form memory operands |
1540 | if (!TlsCall && parseOptionalToken(T: AsmToken::LParen)) { |
1541 | S = Parser.getTok().getLoc(); |
1542 | |
1543 | int64_t IntVal; |
1544 | switch (getLexer().getKind()) { |
1545 | case AsmToken::Percent: { |
1546 | if (!matchRegisterName(IntVal)) |
1547 | return Error(L: S, Msg: "invalid register name" ); |
1548 | break; |
1549 | } |
1550 | case AsmToken::Integer: |
1551 | if (getParser().parseAbsoluteExpression(Res&: IntVal) || IntVal < 0 || |
1552 | IntVal > 31) |
1553 | return Error(L: S, Msg: "invalid register number" ); |
1554 | break; |
1555 | case AsmToken::Identifier: |
1556 | default: |
1557 | return Error(L: S, Msg: "invalid memory operand" ); |
1558 | } |
1559 | |
1560 | E = Parser.getTok().getLoc(); |
1561 | if (parseToken(T: AsmToken::RParen, Msg: "missing ')'" )) |
1562 | return true; |
1563 | Operands.push_back( |
1564 | Elt: PPCOperand::CreateImm(Val: IntVal, S, E, IsPPC64: isPPC64(), /*IsMemOpBase=*/true)); |
1565 | } |
1566 | |
1567 | return false; |
1568 | } |
1569 | |
1570 | /// Parse an instruction mnemonic followed by its operands. |
1571 | bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, |
1572 | SMLoc NameLoc, OperandVector &Operands) { |
1573 | // The first operand is the token for the instruction name. |
1574 | // If the next character is a '+' or '-', we need to add it to the |
1575 | // instruction name, to match what TableGen is doing. |
1576 | std::string NewOpcode; |
1577 | if (parseOptionalToken(T: AsmToken::Plus)) { |
1578 | NewOpcode = std::string(Name); |
1579 | NewOpcode += '+'; |
1580 | Name = NewOpcode; |
1581 | } |
1582 | if (parseOptionalToken(T: AsmToken::Minus)) { |
1583 | NewOpcode = std::string(Name); |
1584 | NewOpcode += '-'; |
1585 | Name = NewOpcode; |
1586 | } |
1587 | // If the instruction ends in a '.', we need to create a separate |
1588 | // token for it, to match what TableGen is doing. |
1589 | size_t Dot = Name.find(C: '.'); |
1590 | StringRef Mnemonic = Name.slice(Start: 0, End: Dot); |
1591 | if (!NewOpcode.empty()) // Underlying memory for Name is volatile. |
1592 | Operands.push_back( |
1593 | Elt: PPCOperand::CreateTokenWithStringCopy(Str: Mnemonic, S: NameLoc, IsPPC64: isPPC64())); |
1594 | else |
1595 | Operands.push_back(Elt: PPCOperand::CreateToken(Str: Mnemonic, S: NameLoc, IsPPC64: isPPC64())); |
1596 | if (Dot != StringRef::npos) { |
1597 | SMLoc DotLoc = SMLoc::getFromPointer(Ptr: NameLoc.getPointer() + Dot); |
1598 | StringRef DotStr = Name.substr(Start: Dot); |
1599 | if (!NewOpcode.empty()) // Underlying memory for Name is volatile. |
1600 | Operands.push_back( |
1601 | Elt: PPCOperand::CreateTokenWithStringCopy(Str: DotStr, S: DotLoc, IsPPC64: isPPC64())); |
1602 | else |
1603 | Operands.push_back(Elt: PPCOperand::CreateToken(Str: DotStr, S: DotLoc, IsPPC64: isPPC64())); |
1604 | } |
1605 | |
1606 | // If there are no more operands then finish |
1607 | if (parseOptionalToken(T: AsmToken::EndOfStatement)) |
1608 | return false; |
1609 | |
1610 | // Parse the first operand |
1611 | if (parseOperand(Operands)) |
1612 | return true; |
1613 | |
1614 | while (!parseOptionalToken(T: AsmToken::EndOfStatement)) { |
1615 | if (parseToken(T: AsmToken::Comma) || parseOperand(Operands)) |
1616 | return true; |
1617 | } |
1618 | |
1619 | // We'll now deal with an unfortunate special case: the syntax for the dcbt |
1620 | // and dcbtst instructions differs for server vs. embedded cores. |
1621 | // The syntax for dcbt is: |
1622 | // dcbt ra, rb, th [server] |
1623 | // dcbt th, ra, rb [embedded] |
1624 | // where th can be omitted when it is 0. dcbtst is the same. We take the |
1625 | // server form to be the default, so swap the operands if we're parsing for |
1626 | // an embedded core (they'll be swapped again upon printing). |
1627 | if (getSTI().hasFeature(Feature: PPC::FeatureBookE) && |
1628 | Operands.size() == 4 && |
1629 | (Name == "dcbt" || Name == "dcbtst" )) { |
1630 | std::swap(x&: Operands[1], y&: Operands[3]); |
1631 | std::swap(x&: Operands[2], y&: Operands[1]); |
1632 | } |
1633 | |
1634 | // Handle base mnemonic for atomic loads where the EH bit is zero. |
1635 | if (Name == "lqarx" || Name == "ldarx" || Name == "lwarx" || |
1636 | Name == "lharx" || Name == "lbarx" ) { |
1637 | if (Operands.size() != 5) |
1638 | return false; |
1639 | PPCOperand &EHOp = (PPCOperand &)*Operands[4]; |
1640 | if (EHOp.isU1Imm() && EHOp.getImm() == 0) |
1641 | Operands.pop_back(); |
1642 | } |
1643 | |
1644 | return false; |
1645 | } |
1646 | |
1647 | /// Parses the PPC specific directives |
1648 | bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) { |
1649 | StringRef IDVal = DirectiveID.getIdentifier(); |
1650 | if (IDVal == ".word" ) |
1651 | parseDirectiveWord(Size: 2, ID: DirectiveID); |
1652 | else if (IDVal == ".llong" ) |
1653 | parseDirectiveWord(Size: 8, ID: DirectiveID); |
1654 | else if (IDVal == ".tc" ) |
1655 | parseDirectiveTC(Size: isPPC64() ? 8 : 4, ID: DirectiveID); |
1656 | else if (IDVal == ".machine" ) |
1657 | parseDirectiveMachine(L: DirectiveID.getLoc()); |
1658 | else if (IDVal == ".abiversion" ) |
1659 | parseDirectiveAbiVersion(L: DirectiveID.getLoc()); |
1660 | else if (IDVal == ".localentry" ) |
1661 | parseDirectiveLocalEntry(L: DirectiveID.getLoc()); |
1662 | else if (IDVal.starts_with(Prefix: ".gnu_attribute" )) |
1663 | parseGNUAttribute(L: DirectiveID.getLoc()); |
1664 | else |
1665 | return true; |
1666 | return false; |
1667 | } |
1668 | |
1669 | /// ::= .word [ expression (, expression)* ] |
1670 | bool PPCAsmParser::parseDirectiveWord(unsigned Size, AsmToken ID) { |
1671 | auto parseOp = [&]() -> bool { |
1672 | const MCExpr *Value; |
1673 | SMLoc ExprLoc = getParser().getTok().getLoc(); |
1674 | if (getParser().parseExpression(Res&: Value)) |
1675 | return true; |
1676 | if (const auto *MCE = dyn_cast<MCConstantExpr>(Val: Value)) { |
1677 | assert(Size <= 8 && "Invalid size" ); |
1678 | uint64_t IntValue = MCE->getValue(); |
1679 | if (!isUIntN(N: 8 * Size, x: IntValue) && !isIntN(N: 8 * Size, x: IntValue)) |
1680 | return Error(L: ExprLoc, Msg: "literal value out of range for '" + |
1681 | ID.getIdentifier() + "' directive" ); |
1682 | getStreamer().emitIntValue(Value: IntValue, Size); |
1683 | } else |
1684 | getStreamer().emitValue(Value, Size, Loc: ExprLoc); |
1685 | return false; |
1686 | }; |
1687 | |
1688 | if (parseMany(parseOne: parseOp)) |
1689 | return addErrorSuffix(Suffix: " in '" + ID.getIdentifier() + "' directive" ); |
1690 | return false; |
1691 | } |
1692 | |
1693 | /// ::= .tc [ symbol (, expression)* ] |
1694 | bool PPCAsmParser::parseDirectiveTC(unsigned Size, AsmToken ID) { |
1695 | MCAsmParser &Parser = getParser(); |
1696 | // Skip TC symbol, which is only used with XCOFF. |
1697 | while (getLexer().isNot(K: AsmToken::EndOfStatement) |
1698 | && getLexer().isNot(K: AsmToken::Comma)) |
1699 | Parser.Lex(); |
1700 | if (parseToken(T: AsmToken::Comma)) |
1701 | return addErrorSuffix(Suffix: " in '.tc' directive" ); |
1702 | |
1703 | // Align to word size. |
1704 | getParser().getStreamer().emitValueToAlignment(Alignment: Align(Size)); |
1705 | |
1706 | // Emit expressions. |
1707 | return parseDirectiveWord(Size, ID); |
1708 | } |
1709 | |
1710 | /// ELF platforms. |
1711 | /// ::= .machine [ cpu | "push" | "pop" ] |
1712 | bool PPCAsmParser::parseDirectiveMachine(SMLoc L) { |
1713 | MCAsmParser &Parser = getParser(); |
1714 | if (Parser.getTok().isNot(K: AsmToken::Identifier) && |
1715 | Parser.getTok().isNot(K: AsmToken::String)) |
1716 | return Error(L, Msg: "unexpected token in '.machine' directive" ); |
1717 | |
1718 | StringRef CPU = Parser.getTok().getIdentifier(); |
1719 | |
1720 | // FIXME: Right now, the parser always allows any available |
1721 | // instruction, so the .machine directive is not useful. |
1722 | // In the wild, any/push/pop/ppc64/altivec/power[4-9] are seen. |
1723 | |
1724 | Parser.Lex(); |
1725 | |
1726 | if (parseToken(T: AsmToken::EndOfStatement)) |
1727 | return addErrorSuffix(Suffix: " in '.machine' directive" ); |
1728 | |
1729 | PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>( |
1730 | getParser().getStreamer().getTargetStreamer()); |
1731 | if (TStreamer != nullptr) |
1732 | TStreamer->emitMachine(CPU); |
1733 | |
1734 | return false; |
1735 | } |
1736 | |
1737 | /// ::= .abiversion constant-expression |
1738 | bool PPCAsmParser::parseDirectiveAbiVersion(SMLoc L) { |
1739 | int64_t AbiVersion; |
1740 | if (check(P: getParser().parseAbsoluteExpression(Res&: AbiVersion), Loc: L, |
1741 | Msg: "expected constant expression" ) || |
1742 | parseToken(T: AsmToken::EndOfStatement)) |
1743 | return addErrorSuffix(Suffix: " in '.abiversion' directive" ); |
1744 | |
1745 | PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>( |
1746 | getParser().getStreamer().getTargetStreamer()); |
1747 | if (TStreamer != nullptr) |
1748 | TStreamer->emitAbiVersion(AbiVersion); |
1749 | |
1750 | return false; |
1751 | } |
1752 | |
1753 | /// ::= .localentry symbol, expression |
1754 | bool PPCAsmParser::parseDirectiveLocalEntry(SMLoc L) { |
1755 | StringRef Name; |
1756 | if (getParser().parseIdentifier(Res&: Name)) |
1757 | return Error(L, Msg: "expected identifier in '.localentry' directive" ); |
1758 | |
1759 | MCSymbolELF *Sym = cast<MCSymbolELF>(Val: getContext().getOrCreateSymbol(Name)); |
1760 | const MCExpr *Expr; |
1761 | |
1762 | if (parseToken(T: AsmToken::Comma) || |
1763 | check(P: getParser().parseExpression(Res&: Expr), Loc: L, Msg: "expected expression" ) || |
1764 | parseToken(T: AsmToken::EndOfStatement)) |
1765 | return addErrorSuffix(Suffix: " in '.localentry' directive" ); |
1766 | |
1767 | PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>( |
1768 | getParser().getStreamer().getTargetStreamer()); |
1769 | if (TStreamer != nullptr) |
1770 | TStreamer->emitLocalEntry(S: Sym, LocalOffset: Expr); |
1771 | |
1772 | return false; |
1773 | } |
1774 | |
1775 | bool PPCAsmParser::parseGNUAttribute(SMLoc L) { |
1776 | int64_t Tag; |
1777 | int64_t IntegerValue; |
1778 | if (!getParser().parseGNUAttribute(L, Tag, IntegerValue)) |
1779 | return false; |
1780 | |
1781 | getParser().getStreamer().emitGNUAttribute(Tag, Value: IntegerValue); |
1782 | |
1783 | return true; |
1784 | } |
1785 | |
1786 | /// Force static initialization. |
1787 | extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void |
1788 | LLVMInitializePowerPCAsmParser() { |
1789 | RegisterMCAsmParser<PPCAsmParser> A(getThePPC32Target()); |
1790 | RegisterMCAsmParser<PPCAsmParser> B(getThePPC32LETarget()); |
1791 | RegisterMCAsmParser<PPCAsmParser> C(getThePPC64Target()); |
1792 | RegisterMCAsmParser<PPCAsmParser> D(getThePPC64LETarget()); |
1793 | } |
1794 | |
1795 | #define GET_MATCHER_IMPLEMENTATION |
1796 | #define GET_MNEMONIC_SPELL_CHECKER |
1797 | #include "PPCGenAsmMatcher.inc" |
1798 | |
1799 | // Define this matcher function after the auto-generated include so we |
1800 | // have the match class enum definitions. |
1801 | unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, |
1802 | unsigned Kind) { |
1803 | // If the kind is a token for a literal immediate, check if our asm |
1804 | // operand matches. This is for InstAliases which have a fixed-value |
1805 | // immediate in the syntax. |
1806 | int64_t ImmVal; |
1807 | switch (Kind) { |
1808 | case MCK_0: ImmVal = 0; break; |
1809 | case MCK_1: ImmVal = 1; break; |
1810 | case MCK_2: ImmVal = 2; break; |
1811 | case MCK_3: ImmVal = 3; break; |
1812 | case MCK_4: ImmVal = 4; break; |
1813 | case MCK_5: ImmVal = 5; break; |
1814 | case MCK_6: ImmVal = 6; break; |
1815 | case MCK_7: ImmVal = 7; break; |
1816 | default: return Match_InvalidOperand; |
1817 | } |
1818 | |
1819 | PPCOperand &Op = static_cast<PPCOperand &>(AsmOp); |
1820 | if (Op.isU3Imm() && Op.getImm() == ImmVal) |
1821 | return Match_Success; |
1822 | |
1823 | return Match_InvalidOperand; |
1824 | } |
1825 | |
1826 | const MCExpr *PPCAsmParser::applySpecifier(const MCExpr *E, uint32_t Spec, |
1827 | MCContext &Ctx) { |
1828 | if (isa<MCConstantExpr>(Val: E)) { |
1829 | switch (PPCMCExpr::Specifier(Spec)) { |
1830 | case PPC::S_LO: |
1831 | case PPC::S_HI: |
1832 | case PPC::S_HA: |
1833 | case PPC::S_HIGH: |
1834 | case PPC::S_HIGHA: |
1835 | case PPC::S_HIGHER: |
1836 | case PPC::S_HIGHERA: |
1837 | case PPC::S_HIGHEST: |
1838 | case PPC::S_HIGHESTA: |
1839 | break; |
1840 | default: |
1841 | return nullptr; |
1842 | } |
1843 | } |
1844 | |
1845 | return MCSpecifierExpr::create(Expr: E, S: Spec, Ctx); |
1846 | } |
1847 | |